1 //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/MC/MCParser/MCAsmParserExtension.h" 11 #include "llvm/ADT/StringSwitch.h" 12 #include "llvm/ADT/Twine.h" 13 #include "llvm/MC/MCAsmInfo.h" 14 #include "llvm/MC/MCContext.h" 15 #include "llvm/MC/MCExpr.h" 16 #include "llvm/MC/MCObjectFileInfo.h" 17 #include "llvm/MC/MCParser/MCAsmLexer.h" 18 #include "llvm/MC/MCRegisterInfo.h" 19 #include "llvm/MC/MCSectionCOFF.h" 20 #include "llvm/MC/MCStreamer.h" 21 #include "llvm/MC/MCTargetAsmParser.h" 22 #include "llvm/Support/COFF.h" 23 using namespace llvm; 24 25 namespace { 26 27 class COFFAsmParser : public MCAsmParserExtension { 28 template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)> 29 void addDirectiveHandler(StringRef Directive) { 30 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( 31 this, HandleDirective<COFFAsmParser, HandlerMethod>); 32 getParser().addDirectiveHandler(Directive, Handler); 33 } 34 35 bool ParseSectionSwitch(StringRef Section, 36 unsigned Characteristics, 37 SectionKind Kind); 38 39 bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 40 SectionKind Kind, StringRef COMDATSymName, 41 COFF::COMDATType Type); 42 43 bool ParseSectionName(StringRef &SectionName); 44 bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); 45 46 void Initialize(MCAsmParser &Parser) override { 47 // Call the base implementation. 48 MCAsmParserExtension::Initialize(Parser); 49 50 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); 51 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); 52 addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); 53 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section"); 54 addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); 55 addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); 56 addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); 57 addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); 58 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); 59 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx"); 60 addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); 61 62 // Win64 EH directives. 63 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( 64 ".seh_proc"); 65 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>( 66 ".seh_endproc"); 67 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>( 68 ".seh_startchained"); 69 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>( 70 ".seh_endchained"); 71 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>( 72 ".seh_handler"); 73 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>( 74 ".seh_handlerdata"); 75 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>( 76 ".seh_pushreg"); 77 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>( 78 ".seh_setframe"); 79 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>( 80 ".seh_stackalloc"); 81 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>( 82 ".seh_savereg"); 83 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>( 84 ".seh_savexmm"); 85 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>( 86 ".seh_pushframe"); 87 addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( 88 ".seh_endprologue"); 89 addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); 90 } 91 92 bool ParseSectionDirectiveText(StringRef, SMLoc) { 93 return ParseSectionSwitch(".text", 94 COFF::IMAGE_SCN_CNT_CODE 95 | COFF::IMAGE_SCN_MEM_EXECUTE 96 | COFF::IMAGE_SCN_MEM_READ, 97 SectionKind::getText()); 98 } 99 bool ParseSectionDirectiveData(StringRef, SMLoc) { 100 return ParseSectionSwitch(".data", 101 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA 102 | COFF::IMAGE_SCN_MEM_READ 103 | COFF::IMAGE_SCN_MEM_WRITE, 104 SectionKind::getDataRel()); 105 } 106 bool ParseSectionDirectiveBSS(StringRef, SMLoc) { 107 return ParseSectionSwitch(".bss", 108 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA 109 | COFF::IMAGE_SCN_MEM_READ 110 | COFF::IMAGE_SCN_MEM_WRITE, 111 SectionKind::getBSS()); 112 } 113 114 bool ParseDirectiveSection(StringRef, SMLoc); 115 bool ParseDirectiveDef(StringRef, SMLoc); 116 bool ParseDirectiveScl(StringRef, SMLoc); 117 bool ParseDirectiveType(StringRef, SMLoc); 118 bool ParseDirectiveEndef(StringRef, SMLoc); 119 bool ParseDirectiveSecRel32(StringRef, SMLoc); 120 bool ParseDirectiveSecIdx(StringRef, SMLoc); 121 bool parseCOMDATType(COFF::COMDATType &Type); 122 bool ParseDirectiveLinkOnce(StringRef, SMLoc); 123 124 // Win64 EH directives. 125 bool ParseSEHDirectiveStartProc(StringRef, SMLoc); 126 bool ParseSEHDirectiveEndProc(StringRef, SMLoc); 127 bool ParseSEHDirectiveStartChained(StringRef, SMLoc); 128 bool ParseSEHDirectiveEndChained(StringRef, SMLoc); 129 bool ParseSEHDirectiveHandler(StringRef, SMLoc); 130 bool ParseSEHDirectiveHandlerData(StringRef, SMLoc); 131 bool ParseSEHDirectivePushReg(StringRef, SMLoc); 132 bool ParseSEHDirectiveSetFrame(StringRef, SMLoc); 133 bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); 134 bool ParseSEHDirectiveSaveReg(StringRef, SMLoc); 135 bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc); 136 bool ParseSEHDirectivePushFrame(StringRef, SMLoc); 137 bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); 138 139 bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); 140 bool ParseSEHRegisterNumber(unsigned &RegNo); 141 bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc); 142 public: 143 COFFAsmParser() {} 144 }; 145 146 } // end annonomous namespace. 147 148 static SectionKind computeSectionKind(unsigned Flags) { 149 if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) 150 return SectionKind::getText(); 151 if (Flags & COFF::IMAGE_SCN_MEM_READ && 152 (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) 153 return SectionKind::getReadOnly(); 154 return SectionKind::getDataRel(); 155 } 156 157 bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) { 158 enum { 159 None = 0, 160 Alloc = 1 << 0, 161 Code = 1 << 1, 162 Load = 1 << 2, 163 InitData = 1 << 3, 164 Shared = 1 << 4, 165 NoLoad = 1 << 5, 166 NoRead = 1 << 6, 167 NoWrite = 1 << 7 168 }; 169 170 bool ReadOnlyRemoved = false; 171 unsigned SecFlags = None; 172 173 for (char FlagChar : FlagsString) { 174 switch (FlagChar) { 175 case 'a': 176 // Ignored. 177 break; 178 179 case 'b': // bss section 180 SecFlags |= Alloc; 181 if (SecFlags & InitData) 182 return TokError("conflicting section flags 'b' and 'd'."); 183 SecFlags &= ~Load; 184 break; 185 186 case 'd': // data section 187 SecFlags |= InitData; 188 if (SecFlags & Alloc) 189 return TokError("conflicting section flags 'b' and 'd'."); 190 SecFlags &= ~NoWrite; 191 if ((SecFlags & NoLoad) == 0) 192 SecFlags |= Load; 193 break; 194 195 case 'n': // section is not loaded 196 SecFlags |= NoLoad; 197 SecFlags &= ~Load; 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 default: 234 return TokError("unknown flag"); 235 } 236 } 237 238 *Flags = 0; 239 240 if (SecFlags == None) 241 SecFlags = InitData; 242 243 if (SecFlags & Code) 244 *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; 245 if (SecFlags & InitData) 246 *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 247 if ((SecFlags & Alloc) && (SecFlags & Load) == 0) 248 *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 249 if (SecFlags & NoLoad) 250 *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; 251 if ((SecFlags & NoRead) == 0) 252 *Flags |= COFF::IMAGE_SCN_MEM_READ; 253 if ((SecFlags & NoWrite) == 0) 254 *Flags |= COFF::IMAGE_SCN_MEM_WRITE; 255 if (SecFlags & Shared) 256 *Flags |= COFF::IMAGE_SCN_MEM_SHARED; 257 258 return false; 259 } 260 261 /// ParseDirectiveSymbolAttribute 262 /// ::= { ".weak", ... } [ identifier ( , identifier )* ] 263 bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { 264 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) 265 .Case(".weak", MCSA_Weak) 266 .Default(MCSA_Invalid); 267 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); 268 if (getLexer().isNot(AsmToken::EndOfStatement)) { 269 for (;;) { 270 StringRef Name; 271 272 if (getParser().parseIdentifier(Name)) 273 return TokError("expected identifier in directive"); 274 275 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 276 277 getStreamer().EmitSymbolAttribute(Sym, Attr); 278 279 if (getLexer().is(AsmToken::EndOfStatement)) 280 break; 281 282 if (getLexer().isNot(AsmToken::Comma)) 283 return TokError("unexpected token in directive"); 284 Lex(); 285 } 286 } 287 288 Lex(); 289 return false; 290 } 291 292 bool COFFAsmParser::ParseSectionSwitch(StringRef Section, 293 unsigned Characteristics, 294 SectionKind Kind) { 295 return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0); 296 } 297 298 bool COFFAsmParser::ParseSectionSwitch(StringRef Section, 299 unsigned Characteristics, 300 SectionKind Kind, 301 StringRef COMDATSymName, 302 COFF::COMDATType Type) { 303 if (getLexer().isNot(AsmToken::EndOfStatement)) 304 return TokError("unexpected token in section switching directive"); 305 Lex(); 306 307 getStreamer().SwitchSection(getContext().getCOFFSection( 308 Section, Characteristics, Kind, COMDATSymName, Type)); 309 310 return false; 311 } 312 313 bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { 314 if (!getLexer().is(AsmToken::Identifier)) 315 return true; 316 317 SectionName = getTok().getIdentifier(); 318 Lex(); 319 return false; 320 } 321 322 // .section name [, "flags"] [, identifier [ identifier ], identifier] 323 // 324 // Supported flags: 325 // a: Ignored. 326 // b: BSS section (uninitialized data) 327 // d: data section (initialized data) 328 // n: Discardable section 329 // r: Readable section 330 // s: Shared section 331 // w: Writable section 332 // x: Executable section 333 // y: Not-readable section (clears 'r') 334 // 335 // Subsections are not supported. 336 bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { 337 StringRef SectionName; 338 339 if (ParseSectionName(SectionName)) 340 return TokError("expected identifier in directive"); 341 342 unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 343 COFF::IMAGE_SCN_MEM_READ | 344 COFF::IMAGE_SCN_MEM_WRITE; 345 346 if (getLexer().is(AsmToken::Comma)) { 347 Lex(); 348 349 if (getLexer().isNot(AsmToken::String)) 350 return TokError("expected string in directive"); 351 352 StringRef FlagsStr = getTok().getStringContents(); 353 Lex(); 354 355 if (ParseSectionFlags(FlagsStr, &Flags)) 356 return true; 357 } 358 359 COFF::COMDATType Type = (COFF::COMDATType)0; 360 StringRef COMDATSymName; 361 if (getLexer().is(AsmToken::Comma)) { 362 Type = COFF::IMAGE_COMDAT_SELECT_ANY;; 363 Lex(); 364 365 Flags |= COFF::IMAGE_SCN_LNK_COMDAT; 366 367 if (parseCOMDATType(Type)) 368 return true; 369 370 if (getLexer().isNot(AsmToken::Comma)) 371 return TokError("expected comma in directive"); 372 Lex(); 373 374 if (getParser().parseIdentifier(COMDATSymName)) 375 return TokError("expected identifier in directive"); 376 } 377 378 if (getLexer().isNot(AsmToken::EndOfStatement)) 379 return TokError("unexpected token in directive"); 380 381 SectionKind Kind = computeSectionKind(Flags); 382 if (Kind.isText()) { 383 const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); 384 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) 385 Flags |= COFF::IMAGE_SCN_MEM_16BIT; 386 } 387 ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type); 388 return false; 389 } 390 391 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { 392 StringRef SymbolName; 393 394 if (getParser().parseIdentifier(SymbolName)) 395 return TokError("expected identifier in directive"); 396 397 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName); 398 399 getStreamer().BeginCOFFSymbolDef(Sym); 400 401 Lex(); 402 return false; 403 } 404 405 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) { 406 int64_t SymbolStorageClass; 407 if (getParser().parseAbsoluteExpression(SymbolStorageClass)) 408 return true; 409 410 if (getLexer().isNot(AsmToken::EndOfStatement)) 411 return TokError("unexpected token in directive"); 412 413 Lex(); 414 getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass); 415 return false; 416 } 417 418 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) { 419 int64_t Type; 420 if (getParser().parseAbsoluteExpression(Type)) 421 return true; 422 423 if (getLexer().isNot(AsmToken::EndOfStatement)) 424 return TokError("unexpected token in directive"); 425 426 Lex(); 427 getStreamer().EmitCOFFSymbolType(Type); 428 return false; 429 } 430 431 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { 432 Lex(); 433 getStreamer().EndCOFFSymbolDef(); 434 return false; 435 } 436 437 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { 438 StringRef SymbolID; 439 if (getParser().parseIdentifier(SymbolID)) 440 return TokError("expected identifier in directive"); 441 442 if (getLexer().isNot(AsmToken::EndOfStatement)) 443 return TokError("unexpected token in directive"); 444 445 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); 446 447 Lex(); 448 getStreamer().EmitCOFFSecRel32(Symbol); 449 return false; 450 } 451 452 bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) { 453 StringRef SymbolID; 454 if (getParser().parseIdentifier(SymbolID)) 455 return TokError("expected identifier in directive"); 456 457 if (getLexer().isNot(AsmToken::EndOfStatement)) 458 return TokError("unexpected token in directive"); 459 460 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); 461 462 Lex(); 463 getStreamer().EmitCOFFSectionIndex(Symbol); 464 return false; 465 } 466 467 /// ::= [ identifier ] 468 bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) { 469 StringRef TypeId = getTok().getIdentifier(); 470 471 Type = StringSwitch<COFF::COMDATType>(TypeId) 472 .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) 473 .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) 474 .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) 475 .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) 476 .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) 477 .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) 478 .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) 479 .Default((COFF::COMDATType)0); 480 481 if (Type == 0) 482 return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); 483 484 Lex(); 485 486 return false; 487 } 488 489 /// ParseDirectiveLinkOnce 490 /// ::= .linkonce [ identifier ] 491 bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { 492 COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; 493 if (getLexer().is(AsmToken::Identifier)) 494 if (parseCOMDATType(Type)) 495 return true; 496 497 const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>( 498 getStreamer().getCurrentSection().first); 499 500 if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) 501 return Error(Loc, "cannot make section associative with .linkonce"); 502 503 if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) 504 return Error(Loc, Twine("section '") + Current->getSectionName() + 505 "' is already linkonce"); 506 507 Current->setSelection(Type); 508 509 if (getLexer().isNot(AsmToken::EndOfStatement)) 510 return TokError("unexpected token in directive"); 511 512 return false; 513 } 514 515 bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { 516 StringRef SymbolID; 517 if (getParser().parseIdentifier(SymbolID)) 518 return true; 519 520 if (getLexer().isNot(AsmToken::EndOfStatement)) 521 return TokError("unexpected token in directive"); 522 523 MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); 524 525 Lex(); 526 getStreamer().EmitWinCFIStartProc(Symbol); 527 return false; 528 } 529 530 bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) { 531 Lex(); 532 getStreamer().EmitWinCFIEndProc(); 533 return false; 534 } 535 536 bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) { 537 Lex(); 538 getStreamer().EmitWinCFIStartChained(); 539 return false; 540 } 541 542 bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { 543 Lex(); 544 getStreamer().EmitWinCFIEndChained(); 545 return false; 546 } 547 548 bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { 549 StringRef SymbolID; 550 if (getParser().parseIdentifier(SymbolID)) 551 return true; 552 553 if (getLexer().isNot(AsmToken::Comma)) 554 return TokError("you must specify one or both of @unwind or @except"); 555 Lex(); 556 bool unwind = false, except = false; 557 if (ParseAtUnwindOrAtExcept(unwind, except)) 558 return true; 559 if (getLexer().is(AsmToken::Comma)) { 560 Lex(); 561 if (ParseAtUnwindOrAtExcept(unwind, except)) 562 return true; 563 } 564 if (getLexer().isNot(AsmToken::EndOfStatement)) 565 return TokError("unexpected token in directive"); 566 567 MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID); 568 569 Lex(); 570 getStreamer().EmitWinEHHandler(handler, unwind, except); 571 return false; 572 } 573 574 bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) { 575 Lex(); 576 getStreamer().EmitWinEHHandlerData(); 577 return false; 578 } 579 580 bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { 581 unsigned Reg; 582 if (ParseSEHRegisterNumber(Reg)) 583 return true; 584 585 if (getLexer().isNot(AsmToken::EndOfStatement)) 586 return TokError("unexpected token in directive"); 587 588 Lex(); 589 getStreamer().EmitWinCFIPushReg(Reg); 590 return false; 591 } 592 593 bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { 594 unsigned Reg; 595 int64_t Off; 596 if (ParseSEHRegisterNumber(Reg)) 597 return true; 598 if (getLexer().isNot(AsmToken::Comma)) 599 return TokError("you must specify a stack pointer offset"); 600 601 Lex(); 602 SMLoc startLoc = getLexer().getLoc(); 603 if (getParser().parseAbsoluteExpression(Off)) 604 return true; 605 606 if (Off & 0x0F) 607 return Error(startLoc, "offset is not a multiple of 16"); 608 609 if (getLexer().isNot(AsmToken::EndOfStatement)) 610 return TokError("unexpected token in directive"); 611 612 Lex(); 613 getStreamer().EmitWinCFISetFrame(Reg, Off); 614 return false; 615 } 616 617 bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) { 618 int64_t Size; 619 SMLoc startLoc = getLexer().getLoc(); 620 if (getParser().parseAbsoluteExpression(Size)) 621 return true; 622 623 if (Size & 7) 624 return Error(startLoc, "size is not a multiple of 8"); 625 626 if (getLexer().isNot(AsmToken::EndOfStatement)) 627 return TokError("unexpected token in directive"); 628 629 Lex(); 630 getStreamer().EmitWinCFIAllocStack(Size); 631 return false; 632 } 633 634 bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { 635 unsigned Reg; 636 int64_t Off; 637 if (ParseSEHRegisterNumber(Reg)) 638 return true; 639 if (getLexer().isNot(AsmToken::Comma)) 640 return TokError("you must specify an offset on the stack"); 641 642 Lex(); 643 SMLoc startLoc = getLexer().getLoc(); 644 if (getParser().parseAbsoluteExpression(Off)) 645 return true; 646 647 if (Off & 7) 648 return Error(startLoc, "size is not a multiple of 8"); 649 650 if (getLexer().isNot(AsmToken::EndOfStatement)) 651 return TokError("unexpected token in directive"); 652 653 Lex(); 654 // FIXME: Err on %xmm* registers 655 getStreamer().EmitWinCFISaveReg(Reg, Off); 656 return false; 657 } 658 659 // FIXME: This method is inherently x86-specific. It should really be in the 660 // x86 backend. 661 bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { 662 unsigned Reg; 663 int64_t Off; 664 if (ParseSEHRegisterNumber(Reg)) 665 return true; 666 if (getLexer().isNot(AsmToken::Comma)) 667 return TokError("you must specify an offset on the stack"); 668 669 Lex(); 670 SMLoc startLoc = getLexer().getLoc(); 671 if (getParser().parseAbsoluteExpression(Off)) 672 return true; 673 674 if (getLexer().isNot(AsmToken::EndOfStatement)) 675 return TokError("unexpected token in directive"); 676 677 if (Off & 0x0F) 678 return Error(startLoc, "offset is not a multiple of 16"); 679 680 Lex(); 681 // FIXME: Err on non-%xmm* registers 682 getStreamer().EmitWinCFISaveXMM(Reg, Off); 683 return false; 684 } 685 686 bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) { 687 bool Code = false; 688 StringRef CodeID; 689 if (getLexer().is(AsmToken::At)) { 690 SMLoc startLoc = getLexer().getLoc(); 691 Lex(); 692 if (!getParser().parseIdentifier(CodeID)) { 693 if (CodeID != "code") 694 return Error(startLoc, "expected @code"); 695 Code = true; 696 } 697 } 698 699 if (getLexer().isNot(AsmToken::EndOfStatement)) 700 return TokError("unexpected token in directive"); 701 702 Lex(); 703 getStreamer().EmitWinCFIPushFrame(Code); 704 return false; 705 } 706 707 bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) { 708 Lex(); 709 getStreamer().EmitWinCFIEndProlog(); 710 return false; 711 } 712 713 bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { 714 StringRef identifier; 715 if (getLexer().isNot(AsmToken::At)) 716 return TokError("a handler attribute must begin with '@'"); 717 SMLoc startLoc = getLexer().getLoc(); 718 Lex(); 719 if (getParser().parseIdentifier(identifier)) 720 return Error(startLoc, "expected @unwind or @except"); 721 if (identifier == "unwind") 722 unwind = true; 723 else if (identifier == "except") 724 except = true; 725 else 726 return Error(startLoc, "expected @unwind or @except"); 727 return false; 728 } 729 730 bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { 731 SMLoc startLoc = getLexer().getLoc(); 732 if (getLexer().is(AsmToken::Percent)) { 733 const MCRegisterInfo *MRI = getContext().getRegisterInfo(); 734 SMLoc endLoc; 735 unsigned LLVMRegNo; 736 if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc)) 737 return true; 738 739 #if 0 740 // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering 741 // violation so this validation code is disabled. 742 743 // Check that this is a non-volatile register. 744 const unsigned *NVRegs = TAI.getCalleeSavedRegs(); 745 unsigned i; 746 for (i = 0; NVRegs[i] != 0; ++i) 747 if (NVRegs[i] == LLVMRegNo) 748 break; 749 if (NVRegs[i] == 0) 750 return Error(startLoc, "expected non-volatile register"); 751 #endif 752 753 int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo); 754 if (SEHRegNo < 0) 755 return Error(startLoc,"register can't be represented in SEH unwind info"); 756 RegNo = SEHRegNo; 757 } 758 else { 759 int64_t n; 760 if (getParser().parseAbsoluteExpression(n)) 761 return true; 762 if (n > 15) 763 return Error(startLoc, "register number is too high"); 764 RegNo = n; 765 } 766 767 return false; 768 } 769 770 namespace llvm { 771 772 MCAsmParserExtension *createCOFFAsmParser() { 773 return new COFFAsmParser; 774 } 775 776 } 777