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