1 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/StringRef.h" 10 #include "llvm/ADT/StringSwitch.h" 11 #include "llvm/ADT/Triple.h" 12 #include "llvm/ADT/Twine.h" 13 #include "llvm/BinaryFormat/COFF.h" 14 #include "llvm/MC/MCContext.h" 15 #include "llvm/MC/MCDirectives.h" 16 #include "llvm/MC/MCObjectFileInfo.h" 17 #include "llvm/MC/MCParser/MCAsmLexer.h" 18 #include "llvm/MC/MCParser/MCAsmParserExtension.h" 19 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 20 #include "llvm/MC/MCRegisterInfo.h" 21 #include "llvm/MC/MCSectionCOFF.h" 22 #include "llvm/MC/MCStreamer.h" 23 #include "llvm/MC/SectionKind.h" 24 #include "llvm/Support/SMLoc.h" 25 #include <cassert> 26 #include <cstdint> 27 #include <limits> 28 #include <utility> 29 30 using namespace llvm; 31 32 namespace { 33 34 class COFFAsmParser : public MCAsmParserExtension { 35 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)> 36 void addDirectiveHandler(StringRef Directive) { 37 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( 38 this, HandleDirective<COFFAsmParser, HandlerMethod>); 39 getParser().addDirectiveHandler(Directive, Handler); 40 } 41 42 bool ParseSectionSwitch(StringRef Section, 43 unsigned Characteristics, 44 SectionKind Kind); 45 46 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 47 SectionKind Kind, StringRef COMDATSymName, 48 COFF::COMDATType Type); 49 50 bool ParseSectionName(StringRef &SectionName); 51 bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString, 52 unsigned *Flags); 53 54 void Initialize(MCAsmParser &Parser) override { 55 // Call the base implementation. 56 MCAsmParserExtension::Initialize(Parser); 57 58 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); 59 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); 60 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); 61 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section"); 62 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); 63 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); 64 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); 65 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); 66 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); 67 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx"); 68 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh"); 69 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx"); 70 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); 71 addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva"); 72 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); 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::ParseSEHDirectiveAllocStack>( 88 ".seh_stackalloc"); 89 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( 90 ".seh_endprologue"); 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 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 108 bool ParseSectionDirectiveBSS(StringRef, SMLoc) { 109 return ParseSectionSwitch(".bss", 110 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA 111 | COFF::IMAGE_SCN_MEM_READ 112 | COFF::IMAGE_SCN_MEM_WRITE, 113 SectionKind::getBSS()); 114 } 115 116 bool ParseDirectiveSection(StringRef, SMLoc); 117 bool ParseDirectiveDef(StringRef, SMLoc); 118 bool ParseDirectiveScl(StringRef, SMLoc); 119 bool ParseDirectiveType(StringRef, SMLoc); 120 bool ParseDirectiveEndef(StringRef, SMLoc); 121 bool ParseDirectiveSecRel32(StringRef, SMLoc); 122 bool ParseDirectiveSecIdx(StringRef, SMLoc); 123 bool ParseDirectiveSafeSEH(StringRef, SMLoc); 124 bool ParseDirectiveSymIdx(StringRef, SMLoc); 125 bool parseCOMDATType(COFF::COMDATType &Type); 126 bool ParseDirectiveLinkOnce(StringRef, SMLoc); 127 bool ParseDirectiveRVA(StringRef, SMLoc); 128 129 // Win64 EH directives. 130 bool ParseSEHDirectiveStartProc(StringRef, SMLoc); 131 bool ParseSEHDirectiveEndProc(StringRef, SMLoc); 132 bool ParseSEHDirectiveStartChained(StringRef, SMLoc); 133 bool ParseSEHDirectiveEndChained(StringRef, SMLoc); 134 bool ParseSEHDirectiveHandler(StringRef, SMLoc); 135 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc); 136 bool ParseSEHDirectiveAllocStack(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); 142 143 public: 144 COFFAsmParser() = default; 145 }; 146 147 } // end anonymous namespace. 148 149 static SectionKind computeSectionKind(unsigned Flags) { 150 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) 151 return SectionKind::getText(); 152 if (Flags & COFF::IMAGE_SCN_MEM_READ && 153 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) 154 return SectionKind::getReadOnly(); 155 return SectionKind::getData(); 156 } 157 158 bool COFFAsmParser::ParseSectionFlags(StringRef SectionName, 159 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 Discardable = 1 << 8, 171 }; 172 173 bool ReadOnlyRemoved = false; 174 unsigned SecFlags = None; 175 176 for (char FlagChar : FlagsString) { 177 switch (FlagChar) { 178 case 'a': 179 // Ignored. 180 break; 181 182 case 'b': // bss section 183 SecFlags |= Alloc; 184 if (SecFlags & InitData) 185 return TokError("conflicting section flags 'b' and 'd'."); 186 SecFlags &= ~Load; 187 break; 188 189 case 'd': // data section 190 SecFlags |= InitData; 191 if (SecFlags & Alloc) 192 return TokError("conflicting section flags 'b' and 'd'."); 193 SecFlags &= ~NoWrite; 194 if ((SecFlags & NoLoad) == 0) 195 SecFlags |= Load; 196 break; 197 198 case 'n': // section is not loaded 199 SecFlags |= NoLoad; 200 SecFlags &= ~Load; 201 break; 202 203 case 'D': // discardable 204 SecFlags |= Discardable; 205 break; 206 207 case 'r': // read-only 208 ReadOnlyRemoved = false; 209 SecFlags |= NoWrite; 210 if ((SecFlags & Code) == 0) 211 SecFlags |= InitData; 212 if ((SecFlags & NoLoad) == 0) 213 SecFlags |= Load; 214 break; 215 216 case 's': // shared section 217 SecFlags |= Shared | InitData; 218 SecFlags &= ~NoWrite; 219 if ((SecFlags & NoLoad) == 0) 220 SecFlags |= Load; 221 break; 222 223 case 'w': // writable 224 SecFlags &= ~NoWrite; 225 ReadOnlyRemoved = true; 226 break; 227 228 case 'x': // executable section 229 SecFlags |= Code; 230 if ((SecFlags & NoLoad) == 0) 231 SecFlags |= Load; 232 if (!ReadOnlyRemoved) 233 SecFlags |= NoWrite; 234 break; 235 236 case 'y': // not readable 237 SecFlags |= NoRead | NoWrite; 238 break; 239 240 default: 241 return TokError("unknown flag"); 242 } 243 } 244 245 *Flags = 0; 246 247 if (SecFlags == None) 248 SecFlags = InitData; 249 250 if (SecFlags & Code) 251 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; 252 if (SecFlags & InitData) 253 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 254 if ((SecFlags & Alloc) && (SecFlags & Load) == 0) 255 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 256 if (SecFlags & NoLoad) 257 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; 258 if ((SecFlags & Discardable) || 259 MCSectionCOFF::isImplicitlyDiscardable(SectionName)) 260 *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE; 261 if ((SecFlags & NoRead) == 0) 262 *Flags |= COFF::IMAGE_SCN_MEM_READ; 263 if ((SecFlags & NoWrite) == 0) 264 *Flags |= COFF::IMAGE_SCN_MEM_WRITE; 265 if (SecFlags & Shared) 266 *Flags |= COFF::IMAGE_SCN_MEM_SHARED; 267 268 return false; 269 } 270 271 /// ParseDirectiveSymbolAttribute 272 /// ::= { ".weak", ... } [ identifier ( , identifier )* ] 273 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { 274 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) 275 .Case(".weak", MCSA_Weak) 276 .Default(MCSA_Invalid); 277 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); 278 if (getLexer().isNot(AsmToken::EndOfStatement)) { 279 while (true) { 280 StringRef Name; 281 282 if (getParser().parseIdentifier(Name)) 283 return TokError("expected identifier in directive"); 284 285 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 286 287 getStreamer().EmitSymbolAttribute(Sym, Attr); 288 289 if (getLexer().is(AsmToken::EndOfStatement)) 290 break; 291 292 if (getLexer().isNot(AsmToken::Comma)) 293 return TokError("unexpected token in directive"); 294 Lex(); 295 } 296 } 297 298 Lex(); 299 return false; 300 } 301 302 bool COFFAsmParser::ParseSectionSwitch(StringRef Section, 303 unsigned Characteristics, 304 SectionKind Kind) { 305 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0); 306 } 307 308 bool COFFAsmParser::ParseSectionSwitch(StringRef Section, 309 unsigned Characteristics, 310 SectionKind Kind, 311 StringRef COMDATSymName, 312 COFF::COMDATType Type) { 313 if (getLexer().isNot(AsmToken::EndOfStatement)) 314 return TokError("unexpected token in section switching directive"); 315 Lex(); 316 317 getStreamer().SwitchSection(getContext().getCOFFSection( 318 Section, Characteristics, Kind, COMDATSymName, Type)); 319 320 return false; 321 } 322 323 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { 324 if (!getLexer().is(AsmToken::Identifier)) 325 return true; 326 327 SectionName = getTok().getIdentifier(); 328 Lex(); 329 return false; 330 } 331 332 // .section name [, "flags"] [, identifier [ identifier ], identifier] 333 // 334 // Supported flags: 335 // a: Ignored. 336 // b: BSS section (uninitialized data) 337 // d: data section (initialized data) 338 // n: "noload" section (removed by linker) 339 // D: Discardable section 340 // r: Readable section 341 // s: Shared section 342 // w: Writable section 343 // x: Executable section 344 // y: Not-readable section (clears 'r') 345 // 346 // Subsections are not supported. 347 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { 348 StringRef SectionName; 349 350 if (ParseSectionName(SectionName)) 351 return TokError("expected identifier in directive"); 352 353 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 354 COFF::IMAGE_SCN_MEM_READ | 355 COFF::IMAGE_SCN_MEM_WRITE; 356 357 if (getLexer().is(AsmToken::Comma)) { 358 Lex(); 359 360 if (getLexer().isNot(AsmToken::String)) 361 return TokError("expected string in directive"); 362 363 StringRef FlagsStr = getTok().getStringContents(); 364 Lex(); 365 366 if (ParseSectionFlags(SectionName, FlagsStr, &Flags)) 367 return true; 368 } 369 370 COFF::COMDATType Type = (COFF::COMDATType)0; 371 StringRef COMDATSymName; 372 if (getLexer().is(AsmToken::Comma)) { 373 Type = COFF::IMAGE_COMDAT_SELECT_ANY; 374 Lex(); 375 376 Flags |= COFF::IMAGE_SCN_LNK_COMDAT; 377 378 if (!getLexer().is(AsmToken::Identifier)) 379 return TokError("expected comdat type such as 'discard' or 'largest' " 380 "after protection bits"); 381 382 if (parseCOMDATType(Type)) 383 return true; 384 385 if (getLexer().isNot(AsmToken::Comma)) 386 return TokError("expected comma in directive"); 387 Lex(); 388 389 if (getParser().parseIdentifier(COMDATSymName)) 390 return TokError("expected identifier in directive"); 391 } 392 393 if (getLexer().isNot(AsmToken::EndOfStatement)) 394 return TokError("unexpected token in directive"); 395 396 SectionKind Kind = computeSectionKind(Flags); 397 if (Kind.isText()) { 398 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); 399 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) 400 Flags |= COFF::IMAGE_SCN_MEM_16BIT; 401 } 402 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type); 403 return false; 404 } 405 406 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { 407 StringRef SymbolName; 408 409 if (getParser().parseIdentifier(SymbolName)) 410 return TokError("expected identifier in directive"); 411 412 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName); 413 414 getStreamer().BeginCOFFSymbolDef(Sym); 415 416 Lex(); 417 return false; 418 } 419 420 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) { 421 int64_t SymbolStorageClass; 422 if (getParser().parseAbsoluteExpression(SymbolStorageClass)) 423 return true; 424 425 if (getLexer().isNot(AsmToken::EndOfStatement)) 426 return TokError("unexpected token in directive"); 427 428 Lex(); 429 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass); 430 return false; 431 } 432 433 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) { 434 int64_t Type; 435 if (getParser().parseAbsoluteExpression(Type)) 436 return true; 437 438 if (getLexer().isNot(AsmToken::EndOfStatement)) 439 return TokError("unexpected token in directive"); 440 441 Lex(); 442 getStreamer().EmitCOFFSymbolType(Type); 443 return false; 444 } 445 446 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { 447 Lex(); 448 getStreamer().EndCOFFSymbolDef(); 449 return false; 450 } 451 452 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { 453 StringRef SymbolID; 454 if (getParser().parseIdentifier(SymbolID)) 455 return TokError("expected identifier in directive"); 456 457 int64_t Offset = 0; 458 SMLoc OffsetLoc; 459 if (getLexer().is(AsmToken::Plus)) { 460 OffsetLoc = getLexer().getLoc(); 461 if (getParser().parseAbsoluteExpression(Offset)) 462 return true; 463 } 464 465 if (getLexer().isNot(AsmToken::EndOfStatement)) 466 return TokError("unexpected token in directive"); 467 468 if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max()) 469 return Error( 470 OffsetLoc, 471 "invalid '.secrel32' directive offset, can't be less " 472 "than zero or greater than std::numeric_limits<uint32_t>::max()"); 473 474 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 475 476 Lex(); 477 getStreamer().EmitCOFFSecRel32(Symbol, Offset); 478 return false; 479 } 480 481 bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) { 482 auto parseOp = [&]() -> bool { 483 StringRef SymbolID; 484 if (getParser().parseIdentifier(SymbolID)) 485 return TokError("expected identifier in directive"); 486 487 int64_t Offset = 0; 488 SMLoc OffsetLoc; 489 if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) { 490 OffsetLoc = getLexer().getLoc(); 491 if (getParser().parseAbsoluteExpression(Offset)) 492 return true; 493 } 494 495 if (Offset < std::numeric_limits<int32_t>::min() || 496 Offset > std::numeric_limits<int32_t>::max()) 497 return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less " 498 "than -2147483648 or greater than " 499 "2147483647"); 500 501 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 502 503 getStreamer().EmitCOFFImgRel32(Symbol, Offset); 504 return false; 505 }; 506 507 if (getParser().parseMany(parseOp)) 508 return addErrorSuffix(" in directive"); 509 return false; 510 } 511 512 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) { 513 StringRef SymbolID; 514 if (getParser().parseIdentifier(SymbolID)) 515 return TokError("expected identifier in directive"); 516 517 if (getLexer().isNot(AsmToken::EndOfStatement)) 518 return TokError("unexpected token in directive"); 519 520 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 521 522 Lex(); 523 getStreamer().EmitCOFFSafeSEH(Symbol); 524 return false; 525 } 526 527 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) { 528 StringRef SymbolID; 529 if (getParser().parseIdentifier(SymbolID)) 530 return TokError("expected identifier in directive"); 531 532 if (getLexer().isNot(AsmToken::EndOfStatement)) 533 return TokError("unexpected token in directive"); 534 535 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 536 537 Lex(); 538 getStreamer().EmitCOFFSectionIndex(Symbol); 539 return false; 540 } 541 542 bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) { 543 StringRef SymbolID; 544 if (getParser().parseIdentifier(SymbolID)) 545 return TokError("expected identifier in directive"); 546 547 if (getLexer().isNot(AsmToken::EndOfStatement)) 548 return TokError("unexpected token in directive"); 549 550 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 551 552 Lex(); 553 getStreamer().EmitCOFFSymbolIndex(Symbol); 554 return false; 555 } 556 557 /// ::= [ identifier ] 558 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) { 559 StringRef TypeId = getTok().getIdentifier(); 560 561 Type = StringSwitch<COFF::COMDATType>(TypeId) 562 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) 563 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) 564 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) 565 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) 566 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) 567 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) 568 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) 569 .Default((COFF::COMDATType)0); 570 571 if (Type == 0) 572 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); 573 574 Lex(); 575 576 return false; 577 } 578 579 /// ParseDirectiveLinkOnce 580 /// ::= .linkonce [ identifier ] 581 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { 582 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; 583 if (getLexer().is(AsmToken::Identifier)) 584 if (parseCOMDATType(Type)) 585 return true; 586 587 const MCSectionCOFF *Current = 588 static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly()); 589 590 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) 591 return Error(Loc, "cannot make section associative with .linkonce"); 592 593 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) 594 return Error(Loc, Twine("section '") + Current->getSectionName() + 595 "' is already linkonce"); 596 597 Current->setSelection(Type); 598 599 if (getLexer().isNot(AsmToken::EndOfStatement)) 600 return TokError("unexpected token in directive"); 601 602 return false; 603 } 604 605 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) { 606 StringRef SymbolID; 607 if (getParser().parseIdentifier(SymbolID)) 608 return true; 609 610 if (getLexer().isNot(AsmToken::EndOfStatement)) 611 return TokError("unexpected token in directive"); 612 613 MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 614 615 Lex(); 616 getStreamer().EmitWinCFIStartProc(Symbol, Loc); 617 return false; 618 } 619 620 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) { 621 Lex(); 622 getStreamer().EmitWinCFIEndProc(Loc); 623 return false; 624 } 625 626 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) { 627 Lex(); 628 getStreamer().EmitWinCFIStartChained(Loc); 629 return false; 630 } 631 632 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) { 633 Lex(); 634 getStreamer().EmitWinCFIEndChained(Loc); 635 return false; 636 } 637 638 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) { 639 StringRef SymbolID; 640 if (getParser().parseIdentifier(SymbolID)) 641 return true; 642 643 if (getLexer().isNot(AsmToken::Comma)) 644 return TokError("you must specify one or both of @unwind or @except"); 645 Lex(); 646 bool unwind = false, except = false; 647 if (ParseAtUnwindOrAtExcept(unwind, except)) 648 return true; 649 if (getLexer().is(AsmToken::Comma)) { 650 Lex(); 651 if (ParseAtUnwindOrAtExcept(unwind, except)) 652 return true; 653 } 654 if (getLexer().isNot(AsmToken::EndOfStatement)) 655 return TokError("unexpected token in directive"); 656 657 MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID); 658 659 Lex(); 660 getStreamer().EmitWinEHHandler(handler, unwind, except, Loc); 661 return false; 662 } 663 664 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) { 665 Lex(); 666 getStreamer().EmitWinEHHandlerData(); 667 return false; 668 } 669 670 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) { 671 int64_t Size; 672 if (getParser().parseAbsoluteExpression(Size)) 673 return true; 674 675 if (getLexer().isNot(AsmToken::EndOfStatement)) 676 return TokError("unexpected token in directive"); 677 678 Lex(); 679 getStreamer().EmitWinCFIAllocStack(Size, Loc); 680 return false; 681 } 682 683 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) { 684 Lex(); 685 getStreamer().EmitWinCFIEndProlog(Loc); 686 return false; 687 } 688 689 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { 690 StringRef identifier; 691 if (getLexer().isNot(AsmToken::At)) 692 return TokError("a handler attribute must begin with '@'"); 693 SMLoc startLoc = getLexer().getLoc(); 694 Lex(); 695 if (getParser().parseIdentifier(identifier)) 696 return Error(startLoc, "expected @unwind or @except"); 697 if (identifier == "unwind") 698 unwind = true; 699 else if (identifier == "except") 700 except = true; 701 else 702 return Error(startLoc, "expected @unwind or @except"); 703 return false; 704 } 705 706 namespace llvm { 707 708 MCAsmParserExtension *createCOFFAsmParser() { 709 return new COFFAsmParser; 710 } 711 712 } // end namespace llvm 713