1 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/Target/TargetAsmInfo.h"
19 #include "llvm/Target/TargetAsmParser.h"
20 #include "llvm/Support/COFF.h"
25 class COFFAsmParser
: public MCAsmParserExtension
{
26 template<bool (COFFAsmParser::*Handler
)(StringRef
, SMLoc
)>
27 void AddDirectiveHandler(StringRef Directive
) {
28 getParser().AddDirectiveHandler(this, Directive
,
29 HandleDirective
<COFFAsmParser
, Handler
>);
32 bool ParseSectionSwitch(StringRef Section
,
33 unsigned Characteristics
,
36 virtual void Initialize(MCAsmParser
&Parser
) {
37 // Call the base implementation.
38 MCAsmParserExtension::Initialize(Parser
);
40 AddDirectiveHandler
<&COFFAsmParser::ParseSectionDirectiveText
>(".text");
41 AddDirectiveHandler
<&COFFAsmParser::ParseSectionDirectiveData
>(".data");
42 AddDirectiveHandler
<&COFFAsmParser::ParseSectionDirectiveBSS
>(".bss");
43 AddDirectiveHandler
<&COFFAsmParser::ParseDirectiveDef
>(".def");
44 AddDirectiveHandler
<&COFFAsmParser::ParseDirectiveScl
>(".scl");
45 AddDirectiveHandler
<&COFFAsmParser::ParseDirectiveType
>(".type");
46 AddDirectiveHandler
<&COFFAsmParser::ParseDirectiveEndef
>(".endef");
48 // Win64 EH directives.
49 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveStartProc
>(
51 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndProc
>(
53 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveStartChained
>(
55 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndChained
>(
57 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveHandler
>(
59 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveHandlerData
>(
61 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectivePushReg
>(
63 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveSetFrame
>(
65 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveAllocStack
>(
67 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveSaveReg
>(
69 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveSaveXMM
>(
71 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectivePushFrame
>(
73 AddDirectiveHandler
<&COFFAsmParser::ParseSEHDirectiveEndProlog
>(
77 bool ParseSectionDirectiveText(StringRef
, SMLoc
) {
78 return ParseSectionSwitch(".text",
79 COFF::IMAGE_SCN_CNT_CODE
80 | COFF::IMAGE_SCN_MEM_EXECUTE
81 | COFF::IMAGE_SCN_MEM_READ
,
82 SectionKind::getText());
84 bool ParseSectionDirectiveData(StringRef
, SMLoc
) {
85 return ParseSectionSwitch(".data",
86 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
87 | COFF::IMAGE_SCN_MEM_READ
88 | COFF::IMAGE_SCN_MEM_WRITE
,
89 SectionKind::getDataRel());
91 bool ParseSectionDirectiveBSS(StringRef
, SMLoc
) {
92 return ParseSectionSwitch(".bss",
93 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
94 | COFF::IMAGE_SCN_MEM_READ
95 | COFF::IMAGE_SCN_MEM_WRITE
,
96 SectionKind::getBSS());
99 bool ParseDirectiveDef(StringRef
, SMLoc
);
100 bool ParseDirectiveScl(StringRef
, SMLoc
);
101 bool ParseDirectiveType(StringRef
, SMLoc
);
102 bool ParseDirectiveEndef(StringRef
, SMLoc
);
104 // Win64 EH directives.
105 bool ParseSEHDirectiveStartProc(StringRef
, SMLoc
);
106 bool ParseSEHDirectiveEndProc(StringRef
, SMLoc
);
107 bool ParseSEHDirectiveStartChained(StringRef
, SMLoc
);
108 bool ParseSEHDirectiveEndChained(StringRef
, SMLoc
);
109 bool ParseSEHDirectiveHandler(StringRef
, SMLoc
);
110 bool ParseSEHDirectiveHandlerData(StringRef
, SMLoc
);
111 bool ParseSEHDirectivePushReg(StringRef
, SMLoc
);
112 bool ParseSEHDirectiveSetFrame(StringRef
, SMLoc
);
113 bool ParseSEHDirectiveAllocStack(StringRef
, SMLoc
);
114 bool ParseSEHDirectiveSaveReg(StringRef
, SMLoc
);
115 bool ParseSEHDirectiveSaveXMM(StringRef
, SMLoc
);
116 bool ParseSEHDirectivePushFrame(StringRef
, SMLoc
);
117 bool ParseSEHDirectiveEndProlog(StringRef
, SMLoc
);
119 bool ParseAtUnwindOrAtExcept(bool &unwind
, bool &except
);
120 bool ParseSEHRegisterNumber(unsigned &RegNo
);
125 } // end annonomous namespace.
127 bool COFFAsmParser::ParseSectionSwitch(StringRef Section
,
128 unsigned Characteristics
,
130 if (getLexer().isNot(AsmToken::EndOfStatement
))
131 return TokError("unexpected token in section switching directive");
134 getStreamer().SwitchSection(getContext().getCOFFSection(
135 Section
, Characteristics
, Kind
));
140 bool COFFAsmParser::ParseDirectiveDef(StringRef
, SMLoc
) {
141 StringRef SymbolName
;
143 if (getParser().ParseIdentifier(SymbolName
))
144 return TokError("expected identifier in directive");
146 MCSymbol
*Sym
= getContext().GetOrCreateSymbol(SymbolName
);
148 getStreamer().BeginCOFFSymbolDef(Sym
);
154 bool COFFAsmParser::ParseDirectiveScl(StringRef
, SMLoc
) {
155 int64_t SymbolStorageClass
;
156 if (getParser().ParseAbsoluteExpression(SymbolStorageClass
))
159 if (getLexer().isNot(AsmToken::EndOfStatement
))
160 return TokError("unexpected token in directive");
163 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass
);
167 bool COFFAsmParser::ParseDirectiveType(StringRef
, SMLoc
) {
169 if (getParser().ParseAbsoluteExpression(Type
))
172 if (getLexer().isNot(AsmToken::EndOfStatement
))
173 return TokError("unexpected token in directive");
176 getStreamer().EmitCOFFSymbolType(Type
);
180 bool COFFAsmParser::ParseDirectiveEndef(StringRef
, SMLoc
) {
182 getStreamer().EndCOFFSymbolDef();
186 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef
, SMLoc
) {
188 if (getParser().ParseIdentifier(SymbolID
))
191 if (getLexer().isNot(AsmToken::EndOfStatement
))
192 return TokError("unexpected token in directive");
194 MCSymbol
*Symbol
= getContext().GetOrCreateSymbol(SymbolID
);
197 getStreamer().EmitWin64EHStartProc(Symbol
);
201 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef
, SMLoc
) {
203 getStreamer().EmitWin64EHEndProc();
207 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef
, SMLoc
) {
209 getStreamer().EmitWin64EHStartChained();
213 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef
, SMLoc
) {
215 getStreamer().EmitWin64EHEndChained();
219 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef
, SMLoc
) {
221 if (getParser().ParseIdentifier(SymbolID
))
224 if (getLexer().isNot(AsmToken::Comma
))
225 return TokError("you must specify one or both of @unwind or @except");
227 bool unwind
= false, except
= false;
228 if (ParseAtUnwindOrAtExcept(unwind
, except
))
230 if (getLexer().is(AsmToken::Comma
)) {
232 if (ParseAtUnwindOrAtExcept(unwind
, except
))
235 if (getLexer().isNot(AsmToken::EndOfStatement
))
236 return TokError("unexpected token in directive");
238 MCSymbol
*handler
= getContext().GetOrCreateSymbol(SymbolID
);
241 getStreamer().EmitWin64EHHandler(handler
, unwind
, except
);
245 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef
, SMLoc
) {
247 getStreamer().EmitWin64EHHandlerData();
251 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef
, SMLoc L
) {
253 if (ParseSEHRegisterNumber(Reg
))
256 if (getLexer().isNot(AsmToken::EndOfStatement
))
257 return TokError("unexpected token in directive");
260 getStreamer().EmitWin64EHPushReg(Reg
);
264 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef
, SMLoc L
) {
267 if (ParseSEHRegisterNumber(Reg
))
269 if (getLexer().isNot(AsmToken::Comma
))
270 return TokError("you must specify a stack pointer offset");
273 SMLoc startLoc
= getLexer().getLoc();
274 if (getParser().ParseAbsoluteExpression(Off
))
278 return Error(startLoc
, "offset is not a multiple of 16");
280 if (getLexer().isNot(AsmToken::EndOfStatement
))
281 return TokError("unexpected token in directive");
284 getStreamer().EmitWin64EHSetFrame(Reg
, Off
);
288 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef
, SMLoc
) {
290 SMLoc startLoc
= getLexer().getLoc();
291 if (getParser().ParseAbsoluteExpression(Size
))
295 return Error(startLoc
, "size is not a multiple of 8");
297 if (getLexer().isNot(AsmToken::EndOfStatement
))
298 return TokError("unexpected token in directive");
301 getStreamer().EmitWin64EHAllocStack(Size
);
305 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef
, SMLoc L
) {
308 if (ParseSEHRegisterNumber(Reg
))
310 if (getLexer().isNot(AsmToken::Comma
))
311 return TokError("you must specify an offset on the stack");
314 SMLoc startLoc
= getLexer().getLoc();
315 if (getParser().ParseAbsoluteExpression(Off
))
319 return Error(startLoc
, "size is not a multiple of 8");
321 if (getLexer().isNot(AsmToken::EndOfStatement
))
322 return TokError("unexpected token in directive");
325 // FIXME: Err on %xmm* registers
326 getStreamer().EmitWin64EHSaveReg(Reg
, Off
);
330 // FIXME: This method is inherently x86-specific. It should really be in the
332 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef
, SMLoc L
) {
335 if (ParseSEHRegisterNumber(Reg
))
337 if (getLexer().isNot(AsmToken::Comma
))
338 return TokError("you must specify an offset on the stack");
341 SMLoc startLoc
= getLexer().getLoc();
342 if (getParser().ParseAbsoluteExpression(Off
))
345 if (getLexer().isNot(AsmToken::EndOfStatement
))
346 return TokError("unexpected token in directive");
349 return Error(startLoc
, "offset is not a multiple of 16");
352 // FIXME: Err on non-%xmm* registers
353 getStreamer().EmitWin64EHSaveXMM(Reg
, Off
);
357 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef
, SMLoc
) {
360 if (getLexer().is(AsmToken::At
)) {
361 SMLoc startLoc
= getLexer().getLoc();
363 if (!getParser().ParseIdentifier(CodeID
)) {
364 if (CodeID
!= "code")
365 return Error(startLoc
, "expected @code");
370 if (getLexer().isNot(AsmToken::EndOfStatement
))
371 return TokError("unexpected token in directive");
374 getStreamer().EmitWin64EHPushFrame(Code
);
378 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef
, SMLoc
) {
380 getStreamer().EmitWin64EHEndProlog();
384 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind
, bool &except
) {
385 StringRef identifier
;
386 if (getLexer().isNot(AsmToken::At
))
387 return TokError("a handler attribute must begin with '@'");
388 SMLoc startLoc
= getLexer().getLoc();
390 if (getParser().ParseIdentifier(identifier
))
391 return Error(startLoc
, "expected @unwind or @except");
392 if (identifier
== "unwind")
394 else if (identifier
== "except")
397 return Error(startLoc
, "expected @unwind or @except");
401 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo
) {
402 SMLoc startLoc
= getLexer().getLoc();
403 if (getLexer().is(AsmToken::Percent
)) {
404 const TargetAsmInfo
&asmInfo
= getContext().getTargetAsmInfo();
407 if (getParser().getTargetParser().ParseRegister(LLVMRegNo
,startLoc
,endLoc
))
410 // Check that this is a non-volatile register.
411 const unsigned *NVRegs
= asmInfo
.getCalleeSavedRegs();
413 for (i
= 0; NVRegs
[i
] != 0; ++i
)
414 if (NVRegs
[i
] == LLVMRegNo
)
417 return Error(startLoc
, "expected non-volatile register");
419 int SEHRegNo
= asmInfo
.getSEHRegNum(LLVMRegNo
);
421 return Error(startLoc
,"register can't be represented in SEH unwind info");
426 if (getParser().ParseAbsoluteExpression(n
))
429 return Error(startLoc
, "register number is too high");
438 MCAsmParserExtension
*createCOFFAsmParser() {
439 return new COFFAsmParser
;