blob: 0045950dcaaca82e2560cd2be4161dcc732b0c25 [file] [log] [blame]
Michael J. Spencer7d490042010-10-09 11:01:07 +00001//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/MC/MCParser/MCAsmParserExtension.h"
11#include "llvm/ADT/Twine.h"
12#include "llvm/MC/MCAsmInfo.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCParser/MCAsmLexer.h"
15#include "llvm/MC/MCSectionCOFF.h"
16#include "llvm/MC/MCStreamer.h"
Charles Davisfbc539f2011-05-22 21:12:15 +000017#include "llvm/MC/MCExpr.h"
Michael J. Spencer7d490042010-10-09 11:01:07 +000018#include "llvm/Support/COFF.h"
19using namespace llvm;
20
21namespace {
22
23class COFFAsmParser : public MCAsmParserExtension {
24 template<bool (COFFAsmParser::*Handler)(StringRef, SMLoc)>
25 void AddDirectiveHandler(StringRef Directive) {
26 getParser().AddDirectiveHandler(this, Directive,
27 HandleDirective<COFFAsmParser, Handler>);
28 }
29
30 bool ParseSectionSwitch(StringRef Section,
31 unsigned Characteristics,
32 SectionKind Kind);
33
34 virtual void Initialize(MCAsmParser &Parser) {
35 // Call the base implementation.
36 MCAsmParserExtension::Initialize(Parser);
37
38 AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
39 AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
40 AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
41 AddDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
42 AddDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
43 AddDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
44 AddDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
Charles Davisfbc539f2011-05-22 21:12:15 +000045
46 // Win64 EH directives.
47 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
48 ".seh_proc");
49 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
50 ".seh_endproc");
51 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
52 ".seh_startchained");
53 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
54 ".seh_endchained");
55 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
56 ".seh_handler");
57 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
58 ".seh_handlerdata");
59 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
60 ".seh_pushreg");
61 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
62 ".seh_setframe");
63 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
64 ".seh_stackalloc");
65 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
66 ".seh_savereg");
67 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
68 ".seh_savexmm");
69 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
70 ".seh_pushframe");
71 AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
72 ".seh_endprologue");
Michael J. Spencer7d490042010-10-09 11:01:07 +000073 }
74
75 bool ParseSectionDirectiveText(StringRef, SMLoc) {
76 return ParseSectionSwitch(".text",
77 COFF::IMAGE_SCN_CNT_CODE
78 | COFF::IMAGE_SCN_MEM_EXECUTE
79 | COFF::IMAGE_SCN_MEM_READ,
80 SectionKind::getText());
81 }
82 bool ParseSectionDirectiveData(StringRef, SMLoc) {
83 return ParseSectionSwitch(".data",
84 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
85 | COFF::IMAGE_SCN_MEM_READ
86 | COFF::IMAGE_SCN_MEM_WRITE,
87 SectionKind::getDataRel());
88 }
89 bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
90 return ParseSectionSwitch(".bss",
91 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
92 | COFF::IMAGE_SCN_MEM_READ
93 | COFF::IMAGE_SCN_MEM_WRITE,
94 SectionKind::getBSS());
95 }
96
97 bool ParseDirectiveDef(StringRef, SMLoc);
98 bool ParseDirectiveScl(StringRef, SMLoc);
99 bool ParseDirectiveType(StringRef, SMLoc);
100 bool ParseDirectiveEndef(StringRef, SMLoc);
101
Charles Davisfbc539f2011-05-22 21:12:15 +0000102 // Win64 EH directives.
103 bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
104 bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
105 bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
106 bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
107 bool ParseSEHDirectiveHandler(StringRef, SMLoc);
108 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
109 bool ParseSEHDirectivePushReg(StringRef, SMLoc L);
110 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc L);
111 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc L);
112 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc L);
113 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc L);
114 bool ParseSEHDirectivePushFrame(StringRef, SMLoc L);
115 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
116
117 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
Michael J. Spencer7d490042010-10-09 11:01:07 +0000118public:
119 COFFAsmParser() {}
120};
121
122} // end annonomous namespace.
123
124bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
125 unsigned Characteristics,
126 SectionKind Kind) {
127 if (getLexer().isNot(AsmToken::EndOfStatement))
128 return TokError("unexpected token in section switching directive");
129 Lex();
130
131 getStreamer().SwitchSection(getContext().getCOFFSection(
132 Section, Characteristics, Kind));
133
134 return false;
135}
136
137bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
138 StringRef SymbolName;
139
140 if (getParser().ParseIdentifier(SymbolName))
141 return TokError("expected identifier in directive");
142
143 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
144
145 getStreamer().BeginCOFFSymbolDef(Sym);
146
147 Lex();
148 return false;
149}
150
151bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
152 int64_t SymbolStorageClass;
153 if (getParser().ParseAbsoluteExpression(SymbolStorageClass))
154 return true;
155
156 if (getLexer().isNot(AsmToken::EndOfStatement))
157 return TokError("unexpected token in directive");
158
159 Lex();
160 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
161 return false;
162}
163
164bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
165 int64_t Type;
166 if (getParser().ParseAbsoluteExpression(Type))
167 return true;
168
169 if (getLexer().isNot(AsmToken::EndOfStatement))
170 return TokError("unexpected token in directive");
171
172 Lex();
173 getStreamer().EmitCOFFSymbolType(Type);
174 return false;
175}
176
177bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
178 Lex();
179 getStreamer().EndCOFFSymbolDef();
180 return false;
181}
182
Charles Davisfbc539f2011-05-22 21:12:15 +0000183bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
184 const MCExpr *e;
185 const MCSymbolRefExpr *funcExpr;
186 SMLoc startLoc = getLexer().getLoc();
187 if (getParser().ParseExpression(e))
188 return true;
189
190 if (!(funcExpr = dyn_cast<MCSymbolRefExpr>(e)))
191 return Error(startLoc, "expected symbol");
192
193 if (getLexer().isNot(AsmToken::EndOfStatement))
194 return TokError("unexpected token in directive");
195
196 Lex();
197 getStreamer().EmitWin64EHStartProc(&funcExpr->getSymbol());
198 return false;
199}
200
201bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
202 Lex();
203 getStreamer().EmitWin64EHEndProc();
204 return false;
205}
206
207bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
208 Lex();
209 getStreamer().EmitWin64EHStartChained();
210 return false;
211}
212
213bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
214 Lex();
215 getStreamer().EmitWin64EHEndChained();
216 return false;
217}
218
219bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
220 const MCExpr *e;
221 const MCSymbolRefExpr *funcExpr;
222 SMLoc startLoc = getLexer().getLoc();
223 if (getParser().ParseExpression(e))
224 return true;
225
226 if (!(funcExpr = dyn_cast<MCSymbolRefExpr>(e)))
227 return Error(startLoc, "expected symbol");
228
229 bool unwind = false, except = false;
230 if (!ParseAtUnwindOrAtExcept(unwind, except))
231 return true;
232 if (getLexer().is(AsmToken::Comma)) {
233 Lex();
234 if (!ParseAtUnwindOrAtExcept(unwind, except))
235 return true;
236 }
237 if (getLexer().isNot(AsmToken::EndOfStatement))
238 return TokError("unexpected token in directive");
239
240 Lex();
241 getStreamer().EmitWin64EHHandler(&funcExpr->getSymbol(), unwind, except);
242 return false;
243}
244
245bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
246 Lex();
247 getStreamer().EmitWin64EHHandlerData();
248 return false;
249}
250
251bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
252 return Error(L, "not implemented yet");
253}
254
255bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
256 return Error(L, "not implemented yet");
257}
258
259bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc L) {
260 return Error(L, "not implemented yet");
261}
262
263bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
264 return Error(L, "not implemented yet");
265}
266
267bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
268 return Error(L, "not implemented yet");
269}
270
271bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc L) {
272 return Error(L, "not implemented yet");
273}
274
275bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
276 Lex();
277 getStreamer().EmitWin64EHEndProlog();
278 return false;
279}
280
281bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
282 StringRef identifier;
283 SMLoc startLoc = getLexer().getLoc();
284 if (!getParser().ParseIdentifier(identifier))
285 return Error(startLoc, "expected @unwind or @except");
286 if (identifier == "@unwind")
287 unwind = true;
288 else if (identifier == "@except")
289 except = true;
290 else
291 return Error(startLoc, "expected @unwind or @except");
292 return false;
293}
294
Michael J. Spencer7d490042010-10-09 11:01:07 +0000295namespace llvm {
296
297MCAsmParserExtension *createCOFFAsmParser() {
298 return new COFFAsmParser;
299}
300
301}