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