xref: /aosp_15_r20/external/llvm/lib/MC/MCParser/COFFAsmParser.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmParserExtension.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSwitch.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectFileInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmLexer.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCTargetAsmParser.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionCOFF.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/COFF.h"
23*9880d681SAndroid Build Coastguard Worker using namespace llvm;
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker namespace {
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker class COFFAsmParser : public MCAsmParserExtension {
28*9880d681SAndroid Build Coastguard Worker   template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
addDirectiveHandler(StringRef Directive)29*9880d681SAndroid Build Coastguard Worker   void addDirectiveHandler(StringRef Directive) {
30*9880d681SAndroid Build Coastguard Worker     MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
31*9880d681SAndroid Build Coastguard Worker         this, HandleDirective<COFFAsmParser, HandlerMethod>);
32*9880d681SAndroid Build Coastguard Worker     getParser().addDirectiveHandler(Directive, Handler);
33*9880d681SAndroid Build Coastguard Worker   }
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker   bool ParseSectionSwitch(StringRef Section,
36*9880d681SAndroid Build Coastguard Worker                           unsigned Characteristics,
37*9880d681SAndroid Build Coastguard Worker                           SectionKind Kind);
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker   bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
40*9880d681SAndroid Build Coastguard Worker                           SectionKind Kind, StringRef COMDATSymName,
41*9880d681SAndroid Build Coastguard Worker                           COFF::COMDATType Type);
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker   bool ParseSectionName(StringRef &SectionName);
44*9880d681SAndroid Build Coastguard Worker   bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
45*9880d681SAndroid Build Coastguard Worker 
Initialize(MCAsmParser & Parser)46*9880d681SAndroid Build Coastguard Worker   void Initialize(MCAsmParser &Parser) override {
47*9880d681SAndroid Build Coastguard Worker     // Call the base implementation.
48*9880d681SAndroid Build Coastguard Worker     MCAsmParserExtension::Initialize(Parser);
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
51*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
52*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
53*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
54*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
55*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
56*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
57*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
58*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
59*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
60*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
61*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker     // Win64 EH directives.
64*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
65*9880d681SAndroid Build Coastguard Worker                                                                    ".seh_proc");
66*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
67*9880d681SAndroid Build Coastguard Worker                                                                 ".seh_endproc");
68*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
69*9880d681SAndroid Build Coastguard Worker                                                            ".seh_startchained");
70*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
71*9880d681SAndroid Build Coastguard Worker                                                              ".seh_endchained");
72*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
73*9880d681SAndroid Build Coastguard Worker                                                                 ".seh_handler");
74*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
75*9880d681SAndroid Build Coastguard Worker                                                             ".seh_handlerdata");
76*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
77*9880d681SAndroid Build Coastguard Worker                                                                 ".seh_pushreg");
78*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
79*9880d681SAndroid Build Coastguard Worker                                                                ".seh_setframe");
80*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
81*9880d681SAndroid Build Coastguard Worker                                                              ".seh_stackalloc");
82*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
83*9880d681SAndroid Build Coastguard Worker                                                                 ".seh_savereg");
84*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
85*9880d681SAndroid Build Coastguard Worker                                                                 ".seh_savexmm");
86*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
87*9880d681SAndroid Build Coastguard Worker                                                               ".seh_pushframe");
88*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
89*9880d681SAndroid Build Coastguard Worker                                                             ".seh_endprologue");
90*9880d681SAndroid Build Coastguard Worker     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
91*9880d681SAndroid Build Coastguard Worker   }
92*9880d681SAndroid Build Coastguard Worker 
ParseSectionDirectiveText(StringRef,SMLoc)93*9880d681SAndroid Build Coastguard Worker   bool ParseSectionDirectiveText(StringRef, SMLoc) {
94*9880d681SAndroid Build Coastguard Worker     return ParseSectionSwitch(".text",
95*9880d681SAndroid Build Coastguard Worker                               COFF::IMAGE_SCN_CNT_CODE
96*9880d681SAndroid Build Coastguard Worker                             | COFF::IMAGE_SCN_MEM_EXECUTE
97*9880d681SAndroid Build Coastguard Worker                             | COFF::IMAGE_SCN_MEM_READ,
98*9880d681SAndroid Build Coastguard Worker                               SectionKind::getText());
99*9880d681SAndroid Build Coastguard Worker   }
ParseSectionDirectiveData(StringRef,SMLoc)100*9880d681SAndroid Build Coastguard Worker   bool ParseSectionDirectiveData(StringRef, SMLoc) {
101*9880d681SAndroid Build Coastguard Worker     return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
102*9880d681SAndroid Build Coastguard Worker                                            COFF::IMAGE_SCN_MEM_READ |
103*9880d681SAndroid Build Coastguard Worker                                            COFF::IMAGE_SCN_MEM_WRITE,
104*9880d681SAndroid Build Coastguard Worker                               SectionKind::getData());
105*9880d681SAndroid Build Coastguard Worker   }
ParseSectionDirectiveBSS(StringRef,SMLoc)106*9880d681SAndroid Build Coastguard Worker   bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
107*9880d681SAndroid Build Coastguard Worker     return ParseSectionSwitch(".bss",
108*9880d681SAndroid Build Coastguard Worker                               COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
109*9880d681SAndroid Build Coastguard Worker                             | COFF::IMAGE_SCN_MEM_READ
110*9880d681SAndroid Build Coastguard Worker                             | COFF::IMAGE_SCN_MEM_WRITE,
111*9880d681SAndroid Build Coastguard Worker                               SectionKind::getBSS());
112*9880d681SAndroid Build Coastguard Worker   }
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveSection(StringRef, SMLoc);
115*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveDef(StringRef, SMLoc);
116*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveScl(StringRef, SMLoc);
117*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveType(StringRef, SMLoc);
118*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveEndef(StringRef, SMLoc);
119*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveSecRel32(StringRef, SMLoc);
120*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveSecIdx(StringRef, SMLoc);
121*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveSafeSEH(StringRef, SMLoc);
122*9880d681SAndroid Build Coastguard Worker   bool parseCOMDATType(COFF::COMDATType &Type);
123*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveLinkOnce(StringRef, SMLoc);
124*9880d681SAndroid Build Coastguard Worker 
125*9880d681SAndroid Build Coastguard Worker   // Win64 EH directives.
126*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
127*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
128*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
129*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
130*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveHandler(StringRef, SMLoc);
131*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
132*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectivePushReg(StringRef, SMLoc);
133*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
134*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
135*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
136*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
137*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
138*9880d681SAndroid Build Coastguard Worker   bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker   bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
141*9880d681SAndroid Build Coastguard Worker   bool ParseSEHRegisterNumber(unsigned &RegNo);
142*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
143*9880d681SAndroid Build Coastguard Worker public:
COFFAsmParser()144*9880d681SAndroid Build Coastguard Worker   COFFAsmParser() {}
145*9880d681SAndroid Build Coastguard Worker };
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker } // end annonomous namespace.
148*9880d681SAndroid Build Coastguard Worker 
computeSectionKind(unsigned Flags)149*9880d681SAndroid Build Coastguard Worker static SectionKind computeSectionKind(unsigned Flags) {
150*9880d681SAndroid Build Coastguard Worker   if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
151*9880d681SAndroid Build Coastguard Worker     return SectionKind::getText();
152*9880d681SAndroid Build Coastguard Worker   if (Flags & COFF::IMAGE_SCN_MEM_READ &&
153*9880d681SAndroid Build Coastguard Worker       (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
154*9880d681SAndroid Build Coastguard Worker     return SectionKind::getReadOnly();
155*9880d681SAndroid Build Coastguard Worker   return SectionKind::getData();
156*9880d681SAndroid Build Coastguard Worker }
157*9880d681SAndroid Build Coastguard Worker 
ParseSectionFlags(StringRef FlagsString,unsigned * Flags)158*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
159*9880d681SAndroid Build Coastguard Worker   enum {
160*9880d681SAndroid Build Coastguard Worker     None      = 0,
161*9880d681SAndroid Build Coastguard Worker     Alloc     = 1 << 0,
162*9880d681SAndroid Build Coastguard Worker     Code      = 1 << 1,
163*9880d681SAndroid Build Coastguard Worker     Load      = 1 << 2,
164*9880d681SAndroid Build Coastguard Worker     InitData  = 1 << 3,
165*9880d681SAndroid Build Coastguard Worker     Shared    = 1 << 4,
166*9880d681SAndroid Build Coastguard Worker     NoLoad    = 1 << 5,
167*9880d681SAndroid Build Coastguard Worker     NoRead    = 1 << 6,
168*9880d681SAndroid Build Coastguard Worker     NoWrite  =  1 << 7
169*9880d681SAndroid Build Coastguard Worker   };
170*9880d681SAndroid Build Coastguard Worker 
171*9880d681SAndroid Build Coastguard Worker   bool ReadOnlyRemoved = false;
172*9880d681SAndroid Build Coastguard Worker   unsigned SecFlags = None;
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker   for (char FlagChar : FlagsString) {
175*9880d681SAndroid Build Coastguard Worker     switch (FlagChar) {
176*9880d681SAndroid Build Coastguard Worker     case 'a':
177*9880d681SAndroid Build Coastguard Worker       // Ignored.
178*9880d681SAndroid Build Coastguard Worker       break;
179*9880d681SAndroid Build Coastguard Worker 
180*9880d681SAndroid Build Coastguard Worker     case 'b': // bss section
181*9880d681SAndroid Build Coastguard Worker       SecFlags |= Alloc;
182*9880d681SAndroid Build Coastguard Worker       if (SecFlags & InitData)
183*9880d681SAndroid Build Coastguard Worker         return TokError("conflicting section flags 'b' and 'd'.");
184*9880d681SAndroid Build Coastguard Worker       SecFlags &= ~Load;
185*9880d681SAndroid Build Coastguard Worker       break;
186*9880d681SAndroid Build Coastguard Worker 
187*9880d681SAndroid Build Coastguard Worker     case 'd': // data section
188*9880d681SAndroid Build Coastguard Worker       SecFlags |= InitData;
189*9880d681SAndroid Build Coastguard Worker       if (SecFlags & Alloc)
190*9880d681SAndroid Build Coastguard Worker         return TokError("conflicting section flags 'b' and 'd'.");
191*9880d681SAndroid Build Coastguard Worker       SecFlags &= ~NoWrite;
192*9880d681SAndroid Build Coastguard Worker       if ((SecFlags & NoLoad) == 0)
193*9880d681SAndroid Build Coastguard Worker         SecFlags |= Load;
194*9880d681SAndroid Build Coastguard Worker       break;
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker     case 'n': // section is not loaded
197*9880d681SAndroid Build Coastguard Worker       SecFlags |= NoLoad;
198*9880d681SAndroid Build Coastguard Worker       SecFlags &= ~Load;
199*9880d681SAndroid Build Coastguard Worker       break;
200*9880d681SAndroid Build Coastguard Worker 
201*9880d681SAndroid Build Coastguard Worker     case 'r': // read-only
202*9880d681SAndroid Build Coastguard Worker       ReadOnlyRemoved = false;
203*9880d681SAndroid Build Coastguard Worker       SecFlags |= NoWrite;
204*9880d681SAndroid Build Coastguard Worker       if ((SecFlags & Code) == 0)
205*9880d681SAndroid Build Coastguard Worker         SecFlags |= InitData;
206*9880d681SAndroid Build Coastguard Worker       if ((SecFlags & NoLoad) == 0)
207*9880d681SAndroid Build Coastguard Worker         SecFlags |= Load;
208*9880d681SAndroid Build Coastguard Worker       break;
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker     case 's': // shared section
211*9880d681SAndroid Build Coastguard Worker       SecFlags |= Shared | InitData;
212*9880d681SAndroid Build Coastguard Worker       SecFlags &= ~NoWrite;
213*9880d681SAndroid Build Coastguard Worker       if ((SecFlags & NoLoad) == 0)
214*9880d681SAndroid Build Coastguard Worker         SecFlags |= Load;
215*9880d681SAndroid Build Coastguard Worker       break;
216*9880d681SAndroid Build Coastguard Worker 
217*9880d681SAndroid Build Coastguard Worker     case 'w': // writable
218*9880d681SAndroid Build Coastguard Worker       SecFlags &= ~NoWrite;
219*9880d681SAndroid Build Coastguard Worker       ReadOnlyRemoved = true;
220*9880d681SAndroid Build Coastguard Worker       break;
221*9880d681SAndroid Build Coastguard Worker 
222*9880d681SAndroid Build Coastguard Worker     case 'x': // executable section
223*9880d681SAndroid Build Coastguard Worker       SecFlags |= Code;
224*9880d681SAndroid Build Coastguard Worker       if ((SecFlags & NoLoad) == 0)
225*9880d681SAndroid Build Coastguard Worker         SecFlags |= Load;
226*9880d681SAndroid Build Coastguard Worker       if (!ReadOnlyRemoved)
227*9880d681SAndroid Build Coastguard Worker         SecFlags |= NoWrite;
228*9880d681SAndroid Build Coastguard Worker       break;
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker     case 'y': // not readable
231*9880d681SAndroid Build Coastguard Worker       SecFlags |= NoRead | NoWrite;
232*9880d681SAndroid Build Coastguard Worker       break;
233*9880d681SAndroid Build Coastguard Worker 
234*9880d681SAndroid Build Coastguard Worker     default:
235*9880d681SAndroid Build Coastguard Worker       return TokError("unknown flag");
236*9880d681SAndroid Build Coastguard Worker     }
237*9880d681SAndroid Build Coastguard Worker   }
238*9880d681SAndroid Build Coastguard Worker 
239*9880d681SAndroid Build Coastguard Worker   *Flags = 0;
240*9880d681SAndroid Build Coastguard Worker 
241*9880d681SAndroid Build Coastguard Worker   if (SecFlags == None)
242*9880d681SAndroid Build Coastguard Worker     SecFlags = InitData;
243*9880d681SAndroid Build Coastguard Worker 
244*9880d681SAndroid Build Coastguard Worker   if (SecFlags & Code)
245*9880d681SAndroid Build Coastguard Worker     *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
246*9880d681SAndroid Build Coastguard Worker   if (SecFlags & InitData)
247*9880d681SAndroid Build Coastguard Worker     *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
248*9880d681SAndroid Build Coastguard Worker   if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
249*9880d681SAndroid Build Coastguard Worker     *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
250*9880d681SAndroid Build Coastguard Worker   if (SecFlags & NoLoad)
251*9880d681SAndroid Build Coastguard Worker     *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
252*9880d681SAndroid Build Coastguard Worker   if ((SecFlags & NoRead) == 0)
253*9880d681SAndroid Build Coastguard Worker     *Flags |= COFF::IMAGE_SCN_MEM_READ;
254*9880d681SAndroid Build Coastguard Worker   if ((SecFlags & NoWrite) == 0)
255*9880d681SAndroid Build Coastguard Worker     *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
256*9880d681SAndroid Build Coastguard Worker   if (SecFlags & Shared)
257*9880d681SAndroid Build Coastguard Worker     *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
258*9880d681SAndroid Build Coastguard Worker 
259*9880d681SAndroid Build Coastguard Worker   return false;
260*9880d681SAndroid Build Coastguard Worker }
261*9880d681SAndroid Build Coastguard Worker 
262*9880d681SAndroid Build Coastguard Worker /// ParseDirectiveSymbolAttribute
263*9880d681SAndroid Build Coastguard Worker ///  ::= { ".weak", ... } [ identifier ( , identifier )* ]
ParseDirectiveSymbolAttribute(StringRef Directive,SMLoc)264*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
265*9880d681SAndroid Build Coastguard Worker   MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
266*9880d681SAndroid Build Coastguard Worker     .Case(".weak", MCSA_Weak)
267*9880d681SAndroid Build Coastguard Worker     .Default(MCSA_Invalid);
268*9880d681SAndroid Build Coastguard Worker   assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
269*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement)) {
270*9880d681SAndroid Build Coastguard Worker     for (;;) {
271*9880d681SAndroid Build Coastguard Worker       StringRef Name;
272*9880d681SAndroid Build Coastguard Worker 
273*9880d681SAndroid Build Coastguard Worker       if (getParser().parseIdentifier(Name))
274*9880d681SAndroid Build Coastguard Worker         return TokError("expected identifier in directive");
275*9880d681SAndroid Build Coastguard Worker 
276*9880d681SAndroid Build Coastguard Worker       MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
277*9880d681SAndroid Build Coastguard Worker 
278*9880d681SAndroid Build Coastguard Worker       getStreamer().EmitSymbolAttribute(Sym, Attr);
279*9880d681SAndroid Build Coastguard Worker 
280*9880d681SAndroid Build Coastguard Worker       if (getLexer().is(AsmToken::EndOfStatement))
281*9880d681SAndroid Build Coastguard Worker         break;
282*9880d681SAndroid Build Coastguard Worker 
283*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Comma))
284*9880d681SAndroid Build Coastguard Worker         return TokError("unexpected token in directive");
285*9880d681SAndroid Build Coastguard Worker       Lex();
286*9880d681SAndroid Build Coastguard Worker     }
287*9880d681SAndroid Build Coastguard Worker   }
288*9880d681SAndroid Build Coastguard Worker 
289*9880d681SAndroid Build Coastguard Worker   Lex();
290*9880d681SAndroid Build Coastguard Worker   return false;
291*9880d681SAndroid Build Coastguard Worker }
292*9880d681SAndroid Build Coastguard Worker 
ParseSectionSwitch(StringRef Section,unsigned Characteristics,SectionKind Kind)293*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
294*9880d681SAndroid Build Coastguard Worker                                        unsigned Characteristics,
295*9880d681SAndroid Build Coastguard Worker                                        SectionKind Kind) {
296*9880d681SAndroid Build Coastguard Worker   return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
297*9880d681SAndroid Build Coastguard Worker }
298*9880d681SAndroid Build Coastguard Worker 
ParseSectionSwitch(StringRef Section,unsigned Characteristics,SectionKind Kind,StringRef COMDATSymName,COFF::COMDATType Type)299*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
300*9880d681SAndroid Build Coastguard Worker                                        unsigned Characteristics,
301*9880d681SAndroid Build Coastguard Worker                                        SectionKind Kind,
302*9880d681SAndroid Build Coastguard Worker                                        StringRef COMDATSymName,
303*9880d681SAndroid Build Coastguard Worker                                        COFF::COMDATType Type) {
304*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
305*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in section switching directive");
306*9880d681SAndroid Build Coastguard Worker   Lex();
307*9880d681SAndroid Build Coastguard Worker 
308*9880d681SAndroid Build Coastguard Worker   getStreamer().SwitchSection(getContext().getCOFFSection(
309*9880d681SAndroid Build Coastguard Worker       Section, Characteristics, Kind, COMDATSymName, Type));
310*9880d681SAndroid Build Coastguard Worker 
311*9880d681SAndroid Build Coastguard Worker   return false;
312*9880d681SAndroid Build Coastguard Worker }
313*9880d681SAndroid Build Coastguard Worker 
ParseSectionName(StringRef & SectionName)314*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
315*9880d681SAndroid Build Coastguard Worker   if (!getLexer().is(AsmToken::Identifier))
316*9880d681SAndroid Build Coastguard Worker     return true;
317*9880d681SAndroid Build Coastguard Worker 
318*9880d681SAndroid Build Coastguard Worker   SectionName = getTok().getIdentifier();
319*9880d681SAndroid Build Coastguard Worker   Lex();
320*9880d681SAndroid Build Coastguard Worker   return false;
321*9880d681SAndroid Build Coastguard Worker }
322*9880d681SAndroid Build Coastguard Worker 
323*9880d681SAndroid Build Coastguard Worker // .section name [, "flags"] [, identifier [ identifier ], identifier]
324*9880d681SAndroid Build Coastguard Worker //
325*9880d681SAndroid Build Coastguard Worker // Supported flags:
326*9880d681SAndroid Build Coastguard Worker //   a: Ignored.
327*9880d681SAndroid Build Coastguard Worker //   b: BSS section (uninitialized data)
328*9880d681SAndroid Build Coastguard Worker //   d: data section (initialized data)
329*9880d681SAndroid Build Coastguard Worker //   n: Discardable section
330*9880d681SAndroid Build Coastguard Worker //   r: Readable section
331*9880d681SAndroid Build Coastguard Worker //   s: Shared section
332*9880d681SAndroid Build Coastguard Worker //   w: Writable section
333*9880d681SAndroid Build Coastguard Worker //   x: Executable section
334*9880d681SAndroid Build Coastguard Worker //   y: Not-readable section (clears 'r')
335*9880d681SAndroid Build Coastguard Worker //
336*9880d681SAndroid Build Coastguard Worker // Subsections are not supported.
ParseDirectiveSection(StringRef,SMLoc)337*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
338*9880d681SAndroid Build Coastguard Worker   StringRef SectionName;
339*9880d681SAndroid Build Coastguard Worker 
340*9880d681SAndroid Build Coastguard Worker   if (ParseSectionName(SectionName))
341*9880d681SAndroid Build Coastguard Worker     return TokError("expected identifier in directive");
342*9880d681SAndroid Build Coastguard Worker 
343*9880d681SAndroid Build Coastguard Worker   unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
344*9880d681SAndroid Build Coastguard Worker                    COFF::IMAGE_SCN_MEM_READ |
345*9880d681SAndroid Build Coastguard Worker                    COFF::IMAGE_SCN_MEM_WRITE;
346*9880d681SAndroid Build Coastguard Worker 
347*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Comma)) {
348*9880d681SAndroid Build Coastguard Worker     Lex();
349*9880d681SAndroid Build Coastguard Worker 
350*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::String))
351*9880d681SAndroid Build Coastguard Worker       return TokError("expected string in directive");
352*9880d681SAndroid Build Coastguard Worker 
353*9880d681SAndroid Build Coastguard Worker     StringRef FlagsStr = getTok().getStringContents();
354*9880d681SAndroid Build Coastguard Worker     Lex();
355*9880d681SAndroid Build Coastguard Worker 
356*9880d681SAndroid Build Coastguard Worker     if (ParseSectionFlags(FlagsStr, &Flags))
357*9880d681SAndroid Build Coastguard Worker       return true;
358*9880d681SAndroid Build Coastguard Worker   }
359*9880d681SAndroid Build Coastguard Worker 
360*9880d681SAndroid Build Coastguard Worker   COFF::COMDATType Type = (COFF::COMDATType)0;
361*9880d681SAndroid Build Coastguard Worker   StringRef COMDATSymName;
362*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Comma)) {
363*9880d681SAndroid Build Coastguard Worker     Type = COFF::IMAGE_COMDAT_SELECT_ANY;
364*9880d681SAndroid Build Coastguard Worker     Lex();
365*9880d681SAndroid Build Coastguard Worker 
366*9880d681SAndroid Build Coastguard Worker     Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
367*9880d681SAndroid Build Coastguard Worker 
368*9880d681SAndroid Build Coastguard Worker     if (!getLexer().is(AsmToken::Identifier))
369*9880d681SAndroid Build Coastguard Worker       return TokError("expected comdat type such as 'discard' or 'largest' "
370*9880d681SAndroid Build Coastguard Worker                       "after protection bits");
371*9880d681SAndroid Build Coastguard Worker 
372*9880d681SAndroid Build Coastguard Worker     if (parseCOMDATType(Type))
373*9880d681SAndroid Build Coastguard Worker       return true;
374*9880d681SAndroid Build Coastguard Worker 
375*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::Comma))
376*9880d681SAndroid Build Coastguard Worker       return TokError("expected comma in directive");
377*9880d681SAndroid Build Coastguard Worker     Lex();
378*9880d681SAndroid Build Coastguard Worker 
379*9880d681SAndroid Build Coastguard Worker     if (getParser().parseIdentifier(COMDATSymName))
380*9880d681SAndroid Build Coastguard Worker       return TokError("expected identifier in directive");
381*9880d681SAndroid Build Coastguard Worker   }
382*9880d681SAndroid Build Coastguard Worker 
383*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
384*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
385*9880d681SAndroid Build Coastguard Worker 
386*9880d681SAndroid Build Coastguard Worker   SectionKind Kind = computeSectionKind(Flags);
387*9880d681SAndroid Build Coastguard Worker   if (Kind.isText()) {
388*9880d681SAndroid Build Coastguard Worker     const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
389*9880d681SAndroid Build Coastguard Worker     if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
390*9880d681SAndroid Build Coastguard Worker       Flags |= COFF::IMAGE_SCN_MEM_16BIT;
391*9880d681SAndroid Build Coastguard Worker   }
392*9880d681SAndroid Build Coastguard Worker   ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
393*9880d681SAndroid Build Coastguard Worker   return false;
394*9880d681SAndroid Build Coastguard Worker }
395*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveDef(StringRef,SMLoc)396*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
397*9880d681SAndroid Build Coastguard Worker   StringRef SymbolName;
398*9880d681SAndroid Build Coastguard Worker 
399*9880d681SAndroid Build Coastguard Worker   if (getParser().parseIdentifier(SymbolName))
400*9880d681SAndroid Build Coastguard Worker     return TokError("expected identifier in directive");
401*9880d681SAndroid Build Coastguard Worker 
402*9880d681SAndroid Build Coastguard Worker   MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
403*9880d681SAndroid Build Coastguard Worker 
404*9880d681SAndroid Build Coastguard Worker   getStreamer().BeginCOFFSymbolDef(Sym);
405*9880d681SAndroid Build Coastguard Worker 
406*9880d681SAndroid Build Coastguard Worker   Lex();
407*9880d681SAndroid Build Coastguard Worker   return false;
408*9880d681SAndroid Build Coastguard Worker }
409*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveScl(StringRef,SMLoc)410*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
411*9880d681SAndroid Build Coastguard Worker   int64_t SymbolStorageClass;
412*9880d681SAndroid Build Coastguard Worker   if (getParser().parseAbsoluteExpression(SymbolStorageClass))
413*9880d681SAndroid Build Coastguard Worker     return true;
414*9880d681SAndroid Build Coastguard Worker 
415*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
416*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
417*9880d681SAndroid Build Coastguard Worker 
418*9880d681SAndroid Build Coastguard Worker   Lex();
419*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
420*9880d681SAndroid Build Coastguard Worker   return false;
421*9880d681SAndroid Build Coastguard Worker }
422*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveType(StringRef,SMLoc)423*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
424*9880d681SAndroid Build Coastguard Worker   int64_t Type;
425*9880d681SAndroid Build Coastguard Worker   if (getParser().parseAbsoluteExpression(Type))
426*9880d681SAndroid Build Coastguard Worker     return true;
427*9880d681SAndroid Build Coastguard Worker 
428*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
429*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
430*9880d681SAndroid Build Coastguard Worker 
431*9880d681SAndroid Build Coastguard Worker   Lex();
432*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitCOFFSymbolType(Type);
433*9880d681SAndroid Build Coastguard Worker   return false;
434*9880d681SAndroid Build Coastguard Worker }
435*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveEndef(StringRef,SMLoc)436*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
437*9880d681SAndroid Build Coastguard Worker   Lex();
438*9880d681SAndroid Build Coastguard Worker   getStreamer().EndCOFFSymbolDef();
439*9880d681SAndroid Build Coastguard Worker   return false;
440*9880d681SAndroid Build Coastguard Worker }
441*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveSecRel32(StringRef,SMLoc)442*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
443*9880d681SAndroid Build Coastguard Worker   StringRef SymbolID;
444*9880d681SAndroid Build Coastguard Worker   if (getParser().parseIdentifier(SymbolID))
445*9880d681SAndroid Build Coastguard Worker     return TokError("expected identifier in directive");
446*9880d681SAndroid Build Coastguard Worker 
447*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
448*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
449*9880d681SAndroid Build Coastguard Worker 
450*9880d681SAndroid Build Coastguard Worker   MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
451*9880d681SAndroid Build Coastguard Worker 
452*9880d681SAndroid Build Coastguard Worker   Lex();
453*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitCOFFSecRel32(Symbol);
454*9880d681SAndroid Build Coastguard Worker   return false;
455*9880d681SAndroid Build Coastguard Worker }
456*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveSafeSEH(StringRef,SMLoc)457*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
458*9880d681SAndroid Build Coastguard Worker   StringRef SymbolID;
459*9880d681SAndroid Build Coastguard Worker   if (getParser().parseIdentifier(SymbolID))
460*9880d681SAndroid Build Coastguard Worker     return TokError("expected identifier in directive");
461*9880d681SAndroid Build Coastguard Worker 
462*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
463*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
464*9880d681SAndroid Build Coastguard Worker 
465*9880d681SAndroid Build Coastguard Worker   MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
466*9880d681SAndroid Build Coastguard Worker 
467*9880d681SAndroid Build Coastguard Worker   Lex();
468*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitCOFFSafeSEH(Symbol);
469*9880d681SAndroid Build Coastguard Worker   return false;
470*9880d681SAndroid Build Coastguard Worker }
471*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveSecIdx(StringRef,SMLoc)472*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
473*9880d681SAndroid Build Coastguard Worker   StringRef SymbolID;
474*9880d681SAndroid Build Coastguard Worker   if (getParser().parseIdentifier(SymbolID))
475*9880d681SAndroid Build Coastguard Worker     return TokError("expected identifier in directive");
476*9880d681SAndroid Build Coastguard Worker 
477*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
478*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
479*9880d681SAndroid Build Coastguard Worker 
480*9880d681SAndroid Build Coastguard Worker   MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
481*9880d681SAndroid Build Coastguard Worker 
482*9880d681SAndroid Build Coastguard Worker   Lex();
483*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitCOFFSectionIndex(Symbol);
484*9880d681SAndroid Build Coastguard Worker   return false;
485*9880d681SAndroid Build Coastguard Worker }
486*9880d681SAndroid Build Coastguard Worker 
487*9880d681SAndroid Build Coastguard Worker /// ::= [ identifier ]
parseCOMDATType(COFF::COMDATType & Type)488*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
489*9880d681SAndroid Build Coastguard Worker   StringRef TypeId = getTok().getIdentifier();
490*9880d681SAndroid Build Coastguard Worker 
491*9880d681SAndroid Build Coastguard Worker   Type = StringSwitch<COFF::COMDATType>(TypeId)
492*9880d681SAndroid Build Coastguard Worker     .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
493*9880d681SAndroid Build Coastguard Worker     .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
494*9880d681SAndroid Build Coastguard Worker     .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
495*9880d681SAndroid Build Coastguard Worker     .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
496*9880d681SAndroid Build Coastguard Worker     .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
497*9880d681SAndroid Build Coastguard Worker     .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
498*9880d681SAndroid Build Coastguard Worker     .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
499*9880d681SAndroid Build Coastguard Worker     .Default((COFF::COMDATType)0);
500*9880d681SAndroid Build Coastguard Worker 
501*9880d681SAndroid Build Coastguard Worker   if (Type == 0)
502*9880d681SAndroid Build Coastguard Worker     return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
503*9880d681SAndroid Build Coastguard Worker 
504*9880d681SAndroid Build Coastguard Worker   Lex();
505*9880d681SAndroid Build Coastguard Worker 
506*9880d681SAndroid Build Coastguard Worker   return false;
507*9880d681SAndroid Build Coastguard Worker }
508*9880d681SAndroid Build Coastguard Worker 
509*9880d681SAndroid Build Coastguard Worker /// ParseDirectiveLinkOnce
510*9880d681SAndroid Build Coastguard Worker ///  ::= .linkonce [ identifier ]
ParseDirectiveLinkOnce(StringRef,SMLoc Loc)511*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
512*9880d681SAndroid Build Coastguard Worker   COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
513*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Identifier))
514*9880d681SAndroid Build Coastguard Worker     if (parseCOMDATType(Type))
515*9880d681SAndroid Build Coastguard Worker       return true;
516*9880d681SAndroid Build Coastguard Worker 
517*9880d681SAndroid Build Coastguard Worker   const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
518*9880d681SAndroid Build Coastguard Worker                                        getStreamer().getCurrentSection().first);
519*9880d681SAndroid Build Coastguard Worker 
520*9880d681SAndroid Build Coastguard Worker   if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
521*9880d681SAndroid Build Coastguard Worker     return Error(Loc, "cannot make section associative with .linkonce");
522*9880d681SAndroid Build Coastguard Worker 
523*9880d681SAndroid Build Coastguard Worker   if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
524*9880d681SAndroid Build Coastguard Worker     return Error(Loc, Twine("section '") + Current->getSectionName() +
525*9880d681SAndroid Build Coastguard Worker                                                        "' is already linkonce");
526*9880d681SAndroid Build Coastguard Worker 
527*9880d681SAndroid Build Coastguard Worker   Current->setSelection(Type);
528*9880d681SAndroid Build Coastguard Worker 
529*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
530*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
531*9880d681SAndroid Build Coastguard Worker 
532*9880d681SAndroid Build Coastguard Worker   return false;
533*9880d681SAndroid Build Coastguard Worker }
534*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveStartProc(StringRef,SMLoc)535*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
536*9880d681SAndroid Build Coastguard Worker   StringRef SymbolID;
537*9880d681SAndroid Build Coastguard Worker   if (getParser().parseIdentifier(SymbolID))
538*9880d681SAndroid Build Coastguard Worker     return true;
539*9880d681SAndroid Build Coastguard Worker 
540*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
541*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
542*9880d681SAndroid Build Coastguard Worker 
543*9880d681SAndroid Build Coastguard Worker   MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
544*9880d681SAndroid Build Coastguard Worker 
545*9880d681SAndroid Build Coastguard Worker   Lex();
546*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFIStartProc(Symbol);
547*9880d681SAndroid Build Coastguard Worker   return false;
548*9880d681SAndroid Build Coastguard Worker }
549*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveEndProc(StringRef,SMLoc)550*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
551*9880d681SAndroid Build Coastguard Worker   Lex();
552*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFIEndProc();
553*9880d681SAndroid Build Coastguard Worker   return false;
554*9880d681SAndroid Build Coastguard Worker }
555*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveStartChained(StringRef,SMLoc)556*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
557*9880d681SAndroid Build Coastguard Worker   Lex();
558*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFIStartChained();
559*9880d681SAndroid Build Coastguard Worker   return false;
560*9880d681SAndroid Build Coastguard Worker }
561*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveEndChained(StringRef,SMLoc)562*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
563*9880d681SAndroid Build Coastguard Worker   Lex();
564*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFIEndChained();
565*9880d681SAndroid Build Coastguard Worker   return false;
566*9880d681SAndroid Build Coastguard Worker }
567*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveHandler(StringRef,SMLoc)568*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
569*9880d681SAndroid Build Coastguard Worker   StringRef SymbolID;
570*9880d681SAndroid Build Coastguard Worker   if (getParser().parseIdentifier(SymbolID))
571*9880d681SAndroid Build Coastguard Worker     return true;
572*9880d681SAndroid Build Coastguard Worker 
573*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
574*9880d681SAndroid Build Coastguard Worker     return TokError("you must specify one or both of @unwind or @except");
575*9880d681SAndroid Build Coastguard Worker   Lex();
576*9880d681SAndroid Build Coastguard Worker   bool unwind = false, except = false;
577*9880d681SAndroid Build Coastguard Worker   if (ParseAtUnwindOrAtExcept(unwind, except))
578*9880d681SAndroid Build Coastguard Worker     return true;
579*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Comma)) {
580*9880d681SAndroid Build Coastguard Worker     Lex();
581*9880d681SAndroid Build Coastguard Worker     if (ParseAtUnwindOrAtExcept(unwind, except))
582*9880d681SAndroid Build Coastguard Worker       return true;
583*9880d681SAndroid Build Coastguard Worker   }
584*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
585*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
586*9880d681SAndroid Build Coastguard Worker 
587*9880d681SAndroid Build Coastguard Worker   MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
588*9880d681SAndroid Build Coastguard Worker 
589*9880d681SAndroid Build Coastguard Worker   Lex();
590*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinEHHandler(handler, unwind, except);
591*9880d681SAndroid Build Coastguard Worker   return false;
592*9880d681SAndroid Build Coastguard Worker }
593*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveHandlerData(StringRef,SMLoc)594*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
595*9880d681SAndroid Build Coastguard Worker   Lex();
596*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinEHHandlerData();
597*9880d681SAndroid Build Coastguard Worker   return false;
598*9880d681SAndroid Build Coastguard Worker }
599*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectivePushReg(StringRef,SMLoc L)600*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
601*9880d681SAndroid Build Coastguard Worker   unsigned Reg = 0;
602*9880d681SAndroid Build Coastguard Worker   if (ParseSEHRegisterNumber(Reg))
603*9880d681SAndroid Build Coastguard Worker     return true;
604*9880d681SAndroid Build Coastguard Worker 
605*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
606*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
607*9880d681SAndroid Build Coastguard Worker 
608*9880d681SAndroid Build Coastguard Worker   Lex();
609*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFIPushReg(Reg);
610*9880d681SAndroid Build Coastguard Worker   return false;
611*9880d681SAndroid Build Coastguard Worker }
612*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveSetFrame(StringRef,SMLoc L)613*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
614*9880d681SAndroid Build Coastguard Worker   unsigned Reg = 0;
615*9880d681SAndroid Build Coastguard Worker   int64_t Off;
616*9880d681SAndroid Build Coastguard Worker   if (ParseSEHRegisterNumber(Reg))
617*9880d681SAndroid Build Coastguard Worker     return true;
618*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
619*9880d681SAndroid Build Coastguard Worker     return TokError("you must specify a stack pointer offset");
620*9880d681SAndroid Build Coastguard Worker 
621*9880d681SAndroid Build Coastguard Worker   Lex();
622*9880d681SAndroid Build Coastguard Worker   SMLoc startLoc = getLexer().getLoc();
623*9880d681SAndroid Build Coastguard Worker   if (getParser().parseAbsoluteExpression(Off))
624*9880d681SAndroid Build Coastguard Worker     return true;
625*9880d681SAndroid Build Coastguard Worker 
626*9880d681SAndroid Build Coastguard Worker   if (Off & 0x0F)
627*9880d681SAndroid Build Coastguard Worker     return Error(startLoc, "offset is not a multiple of 16");
628*9880d681SAndroid Build Coastguard Worker 
629*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
630*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
631*9880d681SAndroid Build Coastguard Worker 
632*9880d681SAndroid Build Coastguard Worker   Lex();
633*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFISetFrame(Reg, Off);
634*9880d681SAndroid Build Coastguard Worker   return false;
635*9880d681SAndroid Build Coastguard Worker }
636*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveAllocStack(StringRef,SMLoc)637*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
638*9880d681SAndroid Build Coastguard Worker   int64_t Size;
639*9880d681SAndroid Build Coastguard Worker   SMLoc startLoc = getLexer().getLoc();
640*9880d681SAndroid Build Coastguard Worker   if (getParser().parseAbsoluteExpression(Size))
641*9880d681SAndroid Build Coastguard Worker     return true;
642*9880d681SAndroid Build Coastguard Worker 
643*9880d681SAndroid Build Coastguard Worker   if (Size & 7)
644*9880d681SAndroid Build Coastguard Worker     return Error(startLoc, "size is not a multiple of 8");
645*9880d681SAndroid Build Coastguard Worker 
646*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
647*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
648*9880d681SAndroid Build Coastguard Worker 
649*9880d681SAndroid Build Coastguard Worker   Lex();
650*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFIAllocStack(Size);
651*9880d681SAndroid Build Coastguard Worker   return false;
652*9880d681SAndroid Build Coastguard Worker }
653*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveSaveReg(StringRef,SMLoc L)654*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
655*9880d681SAndroid Build Coastguard Worker   unsigned Reg = 0;
656*9880d681SAndroid Build Coastguard Worker   int64_t Off;
657*9880d681SAndroid Build Coastguard Worker   if (ParseSEHRegisterNumber(Reg))
658*9880d681SAndroid Build Coastguard Worker     return true;
659*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
660*9880d681SAndroid Build Coastguard Worker     return TokError("you must specify an offset on the stack");
661*9880d681SAndroid Build Coastguard Worker 
662*9880d681SAndroid Build Coastguard Worker   Lex();
663*9880d681SAndroid Build Coastguard Worker   SMLoc startLoc = getLexer().getLoc();
664*9880d681SAndroid Build Coastguard Worker   if (getParser().parseAbsoluteExpression(Off))
665*9880d681SAndroid Build Coastguard Worker     return true;
666*9880d681SAndroid Build Coastguard Worker 
667*9880d681SAndroid Build Coastguard Worker   if (Off & 7)
668*9880d681SAndroid Build Coastguard Worker     return Error(startLoc, "size is not a multiple of 8");
669*9880d681SAndroid Build Coastguard Worker 
670*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
671*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
672*9880d681SAndroid Build Coastguard Worker 
673*9880d681SAndroid Build Coastguard Worker   Lex();
674*9880d681SAndroid Build Coastguard Worker   // FIXME: Err on %xmm* registers
675*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFISaveReg(Reg, Off);
676*9880d681SAndroid Build Coastguard Worker   return false;
677*9880d681SAndroid Build Coastguard Worker }
678*9880d681SAndroid Build Coastguard Worker 
679*9880d681SAndroid Build Coastguard Worker // FIXME: This method is inherently x86-specific. It should really be in the
680*9880d681SAndroid Build Coastguard Worker // x86 backend.
ParseSEHDirectiveSaveXMM(StringRef,SMLoc L)681*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
682*9880d681SAndroid Build Coastguard Worker   unsigned Reg = 0;
683*9880d681SAndroid Build Coastguard Worker   int64_t Off;
684*9880d681SAndroid Build Coastguard Worker   if (ParseSEHRegisterNumber(Reg))
685*9880d681SAndroid Build Coastguard Worker     return true;
686*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
687*9880d681SAndroid Build Coastguard Worker     return TokError("you must specify an offset on the stack");
688*9880d681SAndroid Build Coastguard Worker 
689*9880d681SAndroid Build Coastguard Worker   Lex();
690*9880d681SAndroid Build Coastguard Worker   SMLoc startLoc = getLexer().getLoc();
691*9880d681SAndroid Build Coastguard Worker   if (getParser().parseAbsoluteExpression(Off))
692*9880d681SAndroid Build Coastguard Worker     return true;
693*9880d681SAndroid Build Coastguard Worker 
694*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
695*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
696*9880d681SAndroid Build Coastguard Worker 
697*9880d681SAndroid Build Coastguard Worker   if (Off & 0x0F)
698*9880d681SAndroid Build Coastguard Worker     return Error(startLoc, "offset is not a multiple of 16");
699*9880d681SAndroid Build Coastguard Worker 
700*9880d681SAndroid Build Coastguard Worker   Lex();
701*9880d681SAndroid Build Coastguard Worker   // FIXME: Err on non-%xmm* registers
702*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFISaveXMM(Reg, Off);
703*9880d681SAndroid Build Coastguard Worker   return false;
704*9880d681SAndroid Build Coastguard Worker }
705*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectivePushFrame(StringRef,SMLoc)706*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
707*9880d681SAndroid Build Coastguard Worker   bool Code = false;
708*9880d681SAndroid Build Coastguard Worker   StringRef CodeID;
709*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::At)) {
710*9880d681SAndroid Build Coastguard Worker     SMLoc startLoc = getLexer().getLoc();
711*9880d681SAndroid Build Coastguard Worker     Lex();
712*9880d681SAndroid Build Coastguard Worker     if (!getParser().parseIdentifier(CodeID)) {
713*9880d681SAndroid Build Coastguard Worker       if (CodeID != "code")
714*9880d681SAndroid Build Coastguard Worker         return Error(startLoc, "expected @code");
715*9880d681SAndroid Build Coastguard Worker       Code = true;
716*9880d681SAndroid Build Coastguard Worker     }
717*9880d681SAndroid Build Coastguard Worker   }
718*9880d681SAndroid Build Coastguard Worker 
719*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement))
720*9880d681SAndroid Build Coastguard Worker     return TokError("unexpected token in directive");
721*9880d681SAndroid Build Coastguard Worker 
722*9880d681SAndroid Build Coastguard Worker   Lex();
723*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFIPushFrame(Code);
724*9880d681SAndroid Build Coastguard Worker   return false;
725*9880d681SAndroid Build Coastguard Worker }
726*9880d681SAndroid Build Coastguard Worker 
ParseSEHDirectiveEndProlog(StringRef,SMLoc)727*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
728*9880d681SAndroid Build Coastguard Worker   Lex();
729*9880d681SAndroid Build Coastguard Worker   getStreamer().EmitWinCFIEndProlog();
730*9880d681SAndroid Build Coastguard Worker   return false;
731*9880d681SAndroid Build Coastguard Worker }
732*9880d681SAndroid Build Coastguard Worker 
ParseAtUnwindOrAtExcept(bool & unwind,bool & except)733*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
734*9880d681SAndroid Build Coastguard Worker   StringRef identifier;
735*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::At))
736*9880d681SAndroid Build Coastguard Worker     return TokError("a handler attribute must begin with '@'");
737*9880d681SAndroid Build Coastguard Worker   SMLoc startLoc = getLexer().getLoc();
738*9880d681SAndroid Build Coastguard Worker   Lex();
739*9880d681SAndroid Build Coastguard Worker   if (getParser().parseIdentifier(identifier))
740*9880d681SAndroid Build Coastguard Worker     return Error(startLoc, "expected @unwind or @except");
741*9880d681SAndroid Build Coastguard Worker   if (identifier == "unwind")
742*9880d681SAndroid Build Coastguard Worker     unwind = true;
743*9880d681SAndroid Build Coastguard Worker   else if (identifier == "except")
744*9880d681SAndroid Build Coastguard Worker     except = true;
745*9880d681SAndroid Build Coastguard Worker   else
746*9880d681SAndroid Build Coastguard Worker     return Error(startLoc, "expected @unwind or @except");
747*9880d681SAndroid Build Coastguard Worker   return false;
748*9880d681SAndroid Build Coastguard Worker }
749*9880d681SAndroid Build Coastguard Worker 
ParseSEHRegisterNumber(unsigned & RegNo)750*9880d681SAndroid Build Coastguard Worker bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
751*9880d681SAndroid Build Coastguard Worker   SMLoc startLoc = getLexer().getLoc();
752*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Percent)) {
753*9880d681SAndroid Build Coastguard Worker     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
754*9880d681SAndroid Build Coastguard Worker     SMLoc endLoc;
755*9880d681SAndroid Build Coastguard Worker     unsigned LLVMRegNo;
756*9880d681SAndroid Build Coastguard Worker     if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
757*9880d681SAndroid Build Coastguard Worker       return true;
758*9880d681SAndroid Build Coastguard Worker 
759*9880d681SAndroid Build Coastguard Worker #if 0
760*9880d681SAndroid Build Coastguard Worker     // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
761*9880d681SAndroid Build Coastguard Worker     // violation so this validation code is disabled.
762*9880d681SAndroid Build Coastguard Worker 
763*9880d681SAndroid Build Coastguard Worker     // Check that this is a non-volatile register.
764*9880d681SAndroid Build Coastguard Worker     const unsigned *NVRegs = TAI.getCalleeSavedRegs();
765*9880d681SAndroid Build Coastguard Worker     unsigned i;
766*9880d681SAndroid Build Coastguard Worker     for (i = 0; NVRegs[i] != 0; ++i)
767*9880d681SAndroid Build Coastguard Worker       if (NVRegs[i] == LLVMRegNo)
768*9880d681SAndroid Build Coastguard Worker         break;
769*9880d681SAndroid Build Coastguard Worker     if (NVRegs[i] == 0)
770*9880d681SAndroid Build Coastguard Worker       return Error(startLoc, "expected non-volatile register");
771*9880d681SAndroid Build Coastguard Worker #endif
772*9880d681SAndroid Build Coastguard Worker 
773*9880d681SAndroid Build Coastguard Worker     int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
774*9880d681SAndroid Build Coastguard Worker     if (SEHRegNo < 0)
775*9880d681SAndroid Build Coastguard Worker       return Error(startLoc,"register can't be represented in SEH unwind info");
776*9880d681SAndroid Build Coastguard Worker     RegNo = SEHRegNo;
777*9880d681SAndroid Build Coastguard Worker   }
778*9880d681SAndroid Build Coastguard Worker   else {
779*9880d681SAndroid Build Coastguard Worker     int64_t n;
780*9880d681SAndroid Build Coastguard Worker     if (getParser().parseAbsoluteExpression(n))
781*9880d681SAndroid Build Coastguard Worker       return true;
782*9880d681SAndroid Build Coastguard Worker     if (n > 15)
783*9880d681SAndroid Build Coastguard Worker       return Error(startLoc, "register number is too high");
784*9880d681SAndroid Build Coastguard Worker     RegNo = n;
785*9880d681SAndroid Build Coastguard Worker   }
786*9880d681SAndroid Build Coastguard Worker 
787*9880d681SAndroid Build Coastguard Worker   return false;
788*9880d681SAndroid Build Coastguard Worker }
789*9880d681SAndroid Build Coastguard Worker 
790*9880d681SAndroid Build Coastguard Worker namespace llvm {
791*9880d681SAndroid Build Coastguard Worker 
createCOFFAsmParser()792*9880d681SAndroid Build Coastguard Worker MCAsmParserExtension *createCOFFAsmParser() {
793*9880d681SAndroid Build Coastguard Worker   return new COFFAsmParser;
794*9880d681SAndroid Build Coastguard Worker }
795*9880d681SAndroid Build Coastguard Worker 
796*9880d681SAndroid Build Coastguard Worker }
797