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