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