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