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