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