LLVM API Documentation
00001 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "llvm/MC/MCParser/MCAsmParserExtension.h" 00011 #include "llvm/ADT/StringSwitch.h" 00012 #include "llvm/ADT/Twine.h" 00013 #include "llvm/MC/MCAsmInfo.h" 00014 #include "llvm/MC/MCContext.h" 00015 #include "llvm/MC/MCExpr.h" 00016 #include "llvm/MC/MCObjectFileInfo.h" 00017 #include "llvm/MC/MCParser/MCAsmLexer.h" 00018 #include "llvm/MC/MCRegisterInfo.h" 00019 #include "llvm/MC/MCSectionCOFF.h" 00020 #include "llvm/MC/MCStreamer.h" 00021 #include "llvm/MC/MCTargetAsmParser.h" 00022 #include "llvm/Support/COFF.h" 00023 using namespace llvm; 00024 00025 namespace { 00026 00027 class COFFAsmParser : public MCAsmParserExtension { 00028 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)> 00029 void addDirectiveHandler(StringRef Directive) { 00030 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( 00031 this, HandleDirective<COFFAsmParser, HandlerMethod>); 00032 getParser().addDirectiveHandler(Directive, Handler); 00033 } 00034 00035 bool ParseSectionSwitch(StringRef Section, 00036 unsigned Characteristics, 00037 SectionKind Kind); 00038 00039 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 00040 SectionKind Kind, StringRef COMDATSymName, 00041 COFF::COMDATType Type); 00042 00043 bool ParseSectionName(StringRef &SectionName); 00044 bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); 00045 00046 void Initialize(MCAsmParser &Parser) override { 00047 // Call the base implementation. 00048 MCAsmParserExtension::Initialize(Parser); 00049 00050 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); 00051 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); 00052 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); 00053 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section"); 00054 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); 00055 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); 00056 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); 00057 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); 00058 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); 00059 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx"); 00060 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); 00061 00062 // Win64 EH directives. 00063 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( 00064 ".seh_proc"); 00065 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>( 00066 ".seh_endproc"); 00067 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>( 00068 ".seh_startchained"); 00069 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>( 00070 ".seh_endchained"); 00071 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>( 00072 ".seh_handler"); 00073 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>( 00074 ".seh_handlerdata"); 00075 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>( 00076 ".seh_pushreg"); 00077 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>( 00078 ".seh_setframe"); 00079 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>( 00080 ".seh_stackalloc"); 00081 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>( 00082 ".seh_savereg"); 00083 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>( 00084 ".seh_savexmm"); 00085 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>( 00086 ".seh_pushframe"); 00087 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( 00088 ".seh_endprologue"); 00089 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); 00090 } 00091 00092 bool ParseSectionDirectiveText(StringRef, SMLoc) { 00093 return ParseSectionSwitch(".text", 00094 COFF::IMAGE_SCN_CNT_CODE 00095 | COFF::IMAGE_SCN_MEM_EXECUTE 00096 | COFF::IMAGE_SCN_MEM_READ, 00097 SectionKind::getText()); 00098 } 00099 bool ParseSectionDirectiveData(StringRef, SMLoc) { 00100 return ParseSectionSwitch(".data", 00101 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA 00102 | COFF::IMAGE_SCN_MEM_READ 00103 | COFF::IMAGE_SCN_MEM_WRITE, 00104 SectionKind::getDataRel()); 00105 } 00106 bool ParseSectionDirectiveBSS(StringRef, SMLoc) { 00107 return ParseSectionSwitch(".bss", 00108 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA 00109 | COFF::IMAGE_SCN_MEM_READ 00110 | COFF::IMAGE_SCN_MEM_WRITE, 00111 SectionKind::getBSS()); 00112 } 00113 00114 bool ParseDirectiveSection(StringRef, SMLoc); 00115 bool ParseDirectiveDef(StringRef, SMLoc); 00116 bool ParseDirectiveScl(StringRef, SMLoc); 00117 bool ParseDirectiveType(StringRef, SMLoc); 00118 bool ParseDirectiveEndef(StringRef, SMLoc); 00119 bool ParseDirectiveSecRel32(StringRef, SMLoc); 00120 bool ParseDirectiveSecIdx(StringRef, SMLoc); 00121 bool parseCOMDATType(COFF::COMDATType &Type); 00122 bool ParseDirectiveLinkOnce(StringRef, SMLoc); 00123 00124 // Win64 EH directives. 00125 bool ParseSEHDirectiveStartProc(StringRef, SMLoc); 00126 bool ParseSEHDirectiveEndProc(StringRef, SMLoc); 00127 bool ParseSEHDirectiveStartChained(StringRef, SMLoc); 00128 bool ParseSEHDirectiveEndChained(StringRef, SMLoc); 00129 bool ParseSEHDirectiveHandler(StringRef, SMLoc); 00130 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc); 00131 bool ParseSEHDirectivePushReg(StringRef, SMLoc); 00132 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc); 00133 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); 00134 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc); 00135 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc); 00136 bool ParseSEHDirectivePushFrame(StringRef, SMLoc); 00137 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); 00138 00139 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); 00140 bool ParseSEHRegisterNumber(unsigned &RegNo); 00141 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc); 00142 public: 00143 COFFAsmParser() {} 00144 }; 00145 00146 } // end annonomous namespace. 00147 00148 static SectionKind computeSectionKind(unsigned Flags) { 00149 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) 00150 return SectionKind::getText(); 00151 if (Flags & COFF::IMAGE_SCN_MEM_READ && 00152 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) 00153 return SectionKind::getReadOnly(); 00154 return SectionKind::getDataRel(); 00155 } 00156 00157 bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) { 00158 enum { 00159 None = 0, 00160 Alloc = 1 << 0, 00161 Code = 1 << 1, 00162 Load = 1 << 2, 00163 InitData = 1 << 3, 00164 Shared = 1 << 4, 00165 NoLoad = 1 << 5, 00166 NoRead = 1 << 6, 00167 NoWrite = 1 << 7 00168 }; 00169 00170 bool ReadOnlyRemoved = false; 00171 unsigned SecFlags = None; 00172 00173 for (char FlagChar : FlagsString) { 00174 switch (FlagChar) { 00175 case 'a': 00176 // Ignored. 00177 break; 00178 00179 case 'b': // bss section 00180 SecFlags |= Alloc; 00181 if (SecFlags & InitData) 00182 return TokError("conflicting section flags 'b' and 'd'."); 00183 SecFlags &= ~Load; 00184 break; 00185 00186 case 'd': // data section 00187 SecFlags |= InitData; 00188 if (SecFlags & Alloc) 00189 return TokError("conflicting section flags 'b' and 'd'."); 00190 SecFlags &= ~NoWrite; 00191 if ((SecFlags & NoLoad) == 0) 00192 SecFlags |= Load; 00193 break; 00194 00195 case 'n': // section is not loaded 00196 SecFlags |= NoLoad; 00197 SecFlags &= ~Load; 00198 break; 00199 00200 case 'r': // read-only 00201 ReadOnlyRemoved = false; 00202 SecFlags |= NoWrite; 00203 if ((SecFlags & Code) == 0) 00204 SecFlags |= InitData; 00205 if ((SecFlags & NoLoad) == 0) 00206 SecFlags |= Load; 00207 break; 00208 00209 case 's': // shared section 00210 SecFlags |= Shared | InitData; 00211 SecFlags &= ~NoWrite; 00212 if ((SecFlags & NoLoad) == 0) 00213 SecFlags |= Load; 00214 break; 00215 00216 case 'w': // writable 00217 SecFlags &= ~NoWrite; 00218 ReadOnlyRemoved = true; 00219 break; 00220 00221 case 'x': // executable section 00222 SecFlags |= Code; 00223 if ((SecFlags & NoLoad) == 0) 00224 SecFlags |= Load; 00225 if (!ReadOnlyRemoved) 00226 SecFlags |= NoWrite; 00227 break; 00228 00229 case 'y': // not readable 00230 SecFlags |= NoRead | NoWrite; 00231 break; 00232 00233 default: 00234 return TokError("unknown flag"); 00235 } 00236 } 00237 00238 *Flags = 0; 00239 00240 if (SecFlags == None) 00241 SecFlags = InitData; 00242 00243 if (SecFlags & Code) 00244 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; 00245 if (SecFlags & InitData) 00246 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 00247 if ((SecFlags & Alloc) && (SecFlags & Load) == 0) 00248 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 00249 if (SecFlags & NoLoad) 00250 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; 00251 if ((SecFlags & NoRead) == 0) 00252 *Flags |= COFF::IMAGE_SCN_MEM_READ; 00253 if ((SecFlags & NoWrite) == 0) 00254 *Flags |= COFF::IMAGE_SCN_MEM_WRITE; 00255 if (SecFlags & Shared) 00256 *Flags |= COFF::IMAGE_SCN_MEM_SHARED; 00257 00258 return false; 00259 } 00260 00261 /// ParseDirectiveSymbolAttribute 00262 /// ::= { ".weak", ... } [ identifier ( , identifier )* ] 00263 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { 00264 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) 00265 .Case(".weak", MCSA_Weak) 00266 .Default(MCSA_Invalid); 00267 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); 00268 if (getLexer().isNot(AsmToken::EndOfStatement)) { 00269 for (;;) { 00270 StringRef Name; 00271 00272 if (getParser().parseIdentifier(Name)) 00273 return TokError("expected identifier in directive"); 00274 00275 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 00276 00277 getStreamer().EmitSymbolAttribute(Sym, Attr); 00278 00279 if (getLexer().is(AsmToken::EndOfStatement)) 00280 break; 00281 00282 if (getLexer().isNot(AsmToken::Comma)) 00283 return TokError("unexpected token in directive"); 00284 Lex(); 00285 } 00286 } 00287 00288 Lex(); 00289 return false; 00290 } 00291 00292 bool COFFAsmParser::ParseSectionSwitch(StringRef Section, 00293 unsigned Characteristics, 00294 SectionKind Kind) { 00295 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0); 00296 } 00297 00298 bool COFFAsmParser::ParseSectionSwitch(StringRef Section, 00299 unsigned Characteristics, 00300 SectionKind Kind, 00301 StringRef COMDATSymName, 00302 COFF::COMDATType Type) { 00303 if (getLexer().isNot(AsmToken::EndOfStatement)) 00304 return TokError("unexpected token in section switching directive"); 00305 Lex(); 00306 00307 getStreamer().SwitchSection(getContext().getCOFFSection( 00308 Section, Characteristics, Kind, COMDATSymName, Type)); 00309 00310 return false; 00311 } 00312 00313 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { 00314 if (!getLexer().is(AsmToken::Identifier)) 00315 return true; 00316 00317 SectionName = getTok().getIdentifier(); 00318 Lex(); 00319 return false; 00320 } 00321 00322 // .section name [, "flags"] [, identifier [ identifier ], identifier] 00323 // 00324 // Supported flags: 00325 // a: Ignored. 00326 // b: BSS section (uninitialized data) 00327 // d: data section (initialized data) 00328 // n: Discardable section 00329 // r: Readable section 00330 // s: Shared section 00331 // w: Writable section 00332 // x: Executable section 00333 // y: Not-readable section (clears 'r') 00334 // 00335 // Subsections are not supported. 00336 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { 00337 StringRef SectionName; 00338 00339 if (ParseSectionName(SectionName)) 00340 return TokError("expected identifier in directive"); 00341 00342 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 00343 COFF::IMAGE_SCN_MEM_READ | 00344 COFF::IMAGE_SCN_MEM_WRITE; 00345 00346 if (getLexer().is(AsmToken::Comma)) { 00347 Lex(); 00348 00349 if (getLexer().isNot(AsmToken::String)) 00350 return TokError("expected string in directive"); 00351 00352 StringRef FlagsStr = getTok().getStringContents(); 00353 Lex(); 00354 00355 if (ParseSectionFlags(FlagsStr, &Flags)) 00356 return true; 00357 } 00358 00359 COFF::COMDATType Type = (COFF::COMDATType)0; 00360 StringRef COMDATSymName; 00361 if (getLexer().is(AsmToken::Comma)) { 00362 Type = COFF::IMAGE_COMDAT_SELECT_ANY;; 00363 Lex(); 00364 00365 Flags |= COFF::IMAGE_SCN_LNK_COMDAT; 00366 00367 if (!getLexer().is(AsmToken::Identifier)) 00368 return TokError("expected comdat type such as 'discard' or 'largest' " 00369 "after protection bits"); 00370 00371 if (parseCOMDATType(Type)) 00372 return true; 00373 00374 if (getLexer().isNot(AsmToken::Comma)) 00375 return TokError("expected comma in directive"); 00376 Lex(); 00377 00378 if (getParser().parseIdentifier(COMDATSymName)) 00379 return TokError("expected identifier in directive"); 00380 } 00381 00382 if (getLexer().isNot(AsmToken::EndOfStatement)) 00383 return TokError("unexpected token in directive"); 00384 00385 SectionKind Kind = computeSectionKind(Flags); 00386 if (Kind.isText()) { 00387 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); 00388 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) 00389 Flags |= COFF::IMAGE_SCN_MEM_16BIT; 00390 } 00391 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type); 00392 return false; 00393 } 00394 00395 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { 00396 StringRef SymbolName; 00397 00398 if (getParser().parseIdentifier(SymbolName)) 00399 return TokError("expected identifier in directive"); 00400 00401 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName); 00402 00403 getStreamer().BeginCOFFSymbolDef(Sym); 00404 00405 Lex(); 00406 return false; 00407 } 00408 00409 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) { 00410 int64_t SymbolStorageClass; 00411 if (getParser().parseAbsoluteExpression(SymbolStorageClass)) 00412 return true; 00413 00414 if (getLexer().isNot(AsmToken::EndOfStatement)) 00415 return TokError("unexpected token in directive"); 00416 00417 Lex(); 00418 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass); 00419 return false; 00420 } 00421 00422 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) { 00423 int64_t Type; 00424 if (getParser().parseAbsoluteExpression(Type)) 00425 return true; 00426 00427 if (getLexer().isNot(AsmToken::EndOfStatement)) 00428 return TokError("unexpected token in directive"); 00429 00430 Lex(); 00431 getStreamer().EmitCOFFSymbolType(Type); 00432 return false; 00433 } 00434 00435 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { 00436 Lex(); 00437 getStreamer().EndCOFFSymbolDef(); 00438 return false; 00439 } 00440 00441 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { 00442 StringRef SymbolID; 00443 if (getParser().parseIdentifier(SymbolID)) 00444 return TokError("expected identifier in directive"); 00445 00446 if (getLexer().isNot(AsmToken::EndOfStatement)) 00447 return TokError("unexpected token in directive"); 00448 00449 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); 00450 00451 Lex(); 00452 getStreamer().EmitCOFFSecRel32(Symbol); 00453 return false; 00454 } 00455 00456 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) { 00457 StringRef SymbolID; 00458 if (getParser().parseIdentifier(SymbolID)) 00459 return TokError("expected identifier in directive"); 00460 00461 if (getLexer().isNot(AsmToken::EndOfStatement)) 00462 return TokError("unexpected token in directive"); 00463 00464 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); 00465 00466 Lex(); 00467 getStreamer().EmitCOFFSectionIndex(Symbol); 00468 return false; 00469 } 00470 00471 /// ::= [ identifier ] 00472 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) { 00473 StringRef TypeId = getTok().getIdentifier(); 00474 00475 Type = StringSwitch<COFF::COMDATType>(TypeId) 00476 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) 00477 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) 00478 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) 00479 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) 00480 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) 00481 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) 00482 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) 00483 .Default((COFF::COMDATType)0); 00484 00485 if (Type == 0) 00486 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); 00487 00488 Lex(); 00489 00490 return false; 00491 } 00492 00493 /// ParseDirectiveLinkOnce 00494 /// ::= .linkonce [ identifier ] 00495 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { 00496 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; 00497 if (getLexer().is(AsmToken::Identifier)) 00498 if (parseCOMDATType(Type)) 00499 return true; 00500 00501 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>( 00502 getStreamer().getCurrentSection().first); 00503 00504 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) 00505 return Error(Loc, "cannot make section associative with .linkonce"); 00506 00507 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) 00508 return Error(Loc, Twine("section '") + Current->getSectionName() + 00509 "' is already linkonce"); 00510 00511 Current->setSelection(Type); 00512 00513 if (getLexer().isNot(AsmToken::EndOfStatement)) 00514 return TokError("unexpected token in directive"); 00515 00516 return false; 00517 } 00518 00519 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { 00520 StringRef SymbolID; 00521 if (getParser().parseIdentifier(SymbolID)) 00522 return true; 00523 00524 if (getLexer().isNot(AsmToken::EndOfStatement)) 00525 return TokError("unexpected token in directive"); 00526 00527 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); 00528 00529 Lex(); 00530 getStreamer().EmitWinCFIStartProc(Symbol); 00531 return false; 00532 } 00533 00534 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) { 00535 Lex(); 00536 getStreamer().EmitWinCFIEndProc(); 00537 return false; 00538 } 00539 00540 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) { 00541 Lex(); 00542 getStreamer().EmitWinCFIStartChained(); 00543 return false; 00544 } 00545 00546 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { 00547 Lex(); 00548 getStreamer().EmitWinCFIEndChained(); 00549 return false; 00550 } 00551 00552 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { 00553 StringRef SymbolID; 00554 if (getParser().parseIdentifier(SymbolID)) 00555 return true; 00556 00557 if (getLexer().isNot(AsmToken::Comma)) 00558 return TokError("you must specify one or both of @unwind or @except"); 00559 Lex(); 00560 bool unwind = false, except = false; 00561 if (ParseAtUnwindOrAtExcept(unwind, except)) 00562 return true; 00563 if (getLexer().is(AsmToken::Comma)) { 00564 Lex(); 00565 if (ParseAtUnwindOrAtExcept(unwind, except)) 00566 return true; 00567 } 00568 if (getLexer().isNot(AsmToken::EndOfStatement)) 00569 return TokError("unexpected token in directive"); 00570 00571 MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID); 00572 00573 Lex(); 00574 getStreamer().EmitWinEHHandler(handler, unwind, except); 00575 return false; 00576 } 00577 00578 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) { 00579 Lex(); 00580 getStreamer().EmitWinEHHandlerData(); 00581 return false; 00582 } 00583 00584 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { 00585 unsigned Reg; 00586 if (ParseSEHRegisterNumber(Reg)) 00587 return true; 00588 00589 if (getLexer().isNot(AsmToken::EndOfStatement)) 00590 return TokError("unexpected token in directive"); 00591 00592 Lex(); 00593 getStreamer().EmitWinCFIPushReg(Reg); 00594 return false; 00595 } 00596 00597 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { 00598 unsigned Reg; 00599 int64_t Off; 00600 if (ParseSEHRegisterNumber(Reg)) 00601 return true; 00602 if (getLexer().isNot(AsmToken::Comma)) 00603 return TokError("you must specify a stack pointer offset"); 00604 00605 Lex(); 00606 SMLoc startLoc = getLexer().getLoc(); 00607 if (getParser().parseAbsoluteExpression(Off)) 00608 return true; 00609 00610 if (Off & 0x0F) 00611 return Error(startLoc, "offset is not a multiple of 16"); 00612 00613 if (getLexer().isNot(AsmToken::EndOfStatement)) 00614 return TokError("unexpected token in directive"); 00615 00616 Lex(); 00617 getStreamer().EmitWinCFISetFrame(Reg, Off); 00618 return false; 00619 } 00620 00621 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) { 00622 int64_t Size; 00623 SMLoc startLoc = getLexer().getLoc(); 00624 if (getParser().parseAbsoluteExpression(Size)) 00625 return true; 00626 00627 if (Size & 7) 00628 return Error(startLoc, "size is not a multiple of 8"); 00629 00630 if (getLexer().isNot(AsmToken::EndOfStatement)) 00631 return TokError("unexpected token in directive"); 00632 00633 Lex(); 00634 getStreamer().EmitWinCFIAllocStack(Size); 00635 return false; 00636 } 00637 00638 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { 00639 unsigned Reg; 00640 int64_t Off; 00641 if (ParseSEHRegisterNumber(Reg)) 00642 return true; 00643 if (getLexer().isNot(AsmToken::Comma)) 00644 return TokError("you must specify an offset on the stack"); 00645 00646 Lex(); 00647 SMLoc startLoc = getLexer().getLoc(); 00648 if (getParser().parseAbsoluteExpression(Off)) 00649 return true; 00650 00651 if (Off & 7) 00652 return Error(startLoc, "size is not a multiple of 8"); 00653 00654 if (getLexer().isNot(AsmToken::EndOfStatement)) 00655 return TokError("unexpected token in directive"); 00656 00657 Lex(); 00658 // FIXME: Err on %xmm* registers 00659 getStreamer().EmitWinCFISaveReg(Reg, Off); 00660 return false; 00661 } 00662 00663 // FIXME: This method is inherently x86-specific. It should really be in the 00664 // x86 backend. 00665 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { 00666 unsigned Reg; 00667 int64_t Off; 00668 if (ParseSEHRegisterNumber(Reg)) 00669 return true; 00670 if (getLexer().isNot(AsmToken::Comma)) 00671 return TokError("you must specify an offset on the stack"); 00672 00673 Lex(); 00674 SMLoc startLoc = getLexer().getLoc(); 00675 if (getParser().parseAbsoluteExpression(Off)) 00676 return true; 00677 00678 if (getLexer().isNot(AsmToken::EndOfStatement)) 00679 return TokError("unexpected token in directive"); 00680 00681 if (Off & 0x0F) 00682 return Error(startLoc, "offset is not a multiple of 16"); 00683 00684 Lex(); 00685 // FIXME: Err on non-%xmm* registers 00686 getStreamer().EmitWinCFISaveXMM(Reg, Off); 00687 return false; 00688 } 00689 00690 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) { 00691 bool Code = false; 00692 StringRef CodeID; 00693 if (getLexer().is(AsmToken::At)) { 00694 SMLoc startLoc = getLexer().getLoc(); 00695 Lex(); 00696 if (!getParser().parseIdentifier(CodeID)) { 00697 if (CodeID != "code") 00698 return Error(startLoc, "expected @code"); 00699 Code = true; 00700 } 00701 } 00702 00703 if (getLexer().isNot(AsmToken::EndOfStatement)) 00704 return TokError("unexpected token in directive"); 00705 00706 Lex(); 00707 getStreamer().EmitWinCFIPushFrame(Code); 00708 return false; 00709 } 00710 00711 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) { 00712 Lex(); 00713 getStreamer().EmitWinCFIEndProlog(); 00714 return false; 00715 } 00716 00717 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { 00718 StringRef identifier; 00719 if (getLexer().isNot(AsmToken::At)) 00720 return TokError("a handler attribute must begin with '@'"); 00721 SMLoc startLoc = getLexer().getLoc(); 00722 Lex(); 00723 if (getParser().parseIdentifier(identifier)) 00724 return Error(startLoc, "expected @unwind or @except"); 00725 if (identifier == "unwind") 00726 unwind = true; 00727 else if (identifier == "except") 00728 except = true; 00729 else 00730 return Error(startLoc, "expected @unwind or @except"); 00731 return false; 00732 } 00733 00734 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { 00735 SMLoc startLoc = getLexer().getLoc(); 00736 if (getLexer().is(AsmToken::Percent)) { 00737 const MCRegisterInfo *MRI = getContext().getRegisterInfo(); 00738 SMLoc endLoc; 00739 unsigned LLVMRegNo; 00740 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc)) 00741 return true; 00742 00743 #if 0 00744 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering 00745 // violation so this validation code is disabled. 00746 00747 // Check that this is a non-volatile register. 00748 const unsigned *NVRegs = TAI.getCalleeSavedRegs(); 00749 unsigned i; 00750 for (i = 0; NVRegs[i] != 0; ++i) 00751 if (NVRegs[i] == LLVMRegNo) 00752 break; 00753 if (NVRegs[i] == 0) 00754 return Error(startLoc, "expected non-volatile register"); 00755 #endif 00756 00757 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo); 00758 if (SEHRegNo < 0) 00759 return Error(startLoc,"register can't be represented in SEH unwind info"); 00760 RegNo = SEHRegNo; 00761 } 00762 else { 00763 int64_t n; 00764 if (getParser().parseAbsoluteExpression(n)) 00765 return true; 00766 if (n > 15) 00767 return Error(startLoc, "register number is too high"); 00768 RegNo = n; 00769 } 00770 00771 return false; 00772 } 00773 00774 namespace llvm { 00775 00776 MCAsmParserExtension *createCOFFAsmParser() { 00777 return new COFFAsmParser; 00778 } 00779 00780 }