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