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