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