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