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