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