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