COFFAsmParser.cpp revision 263508
155714Skris//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===// 255714Skris// 355714Skris// The LLVM Compiler Infrastructure 455714Skris// 555714Skris// This file is distributed under the University of Illinois Open Source 655714Skris// License. See LICENSE.TXT for details. 755714Skris// 8280297Sjkim//===----------------------------------------------------------------------===// 955714Skris 1055714Skris#include "llvm/MC/MCParser/MCAsmParserExtension.h" 1155714Skris#include "llvm/ADT/StringSwitch.h" 1255714Skris#include "llvm/ADT/Twine.h" 1355714Skris#include "llvm/MC/MCAsmInfo.h" 1455714Skris#include "llvm/MC/MCContext.h" 15280297Sjkim#include "llvm/MC/MCExpr.h" 1655714Skris#include "llvm/MC/MCParser/MCAsmLexer.h" 1755714Skris#include "llvm/MC/MCRegisterInfo.h" 1855714Skris#include "llvm/MC/MCSectionCOFF.h" 1955714Skris#include "llvm/MC/MCStreamer.h" 2055714Skris#include "llvm/MC/MCTargetAsmParser.h" 2155714Skris#include "llvm/Support/COFF.h" 22280297Sjkimusing namespace llvm; 2355714Skris 2455714Skrisnamespace { 2555714Skris 2655714Skrisclass COFFAsmParser : public MCAsmParserExtension { 2755714Skris template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)> 2855714Skris void addDirectiveHandler(StringRef Directive) { 2955714Skris MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( 3055714Skris this, HandleDirective<COFFAsmParser, HandlerMethod>); 3155714Skris getParser().addDirectiveHandler(Directive, Handler); 3255714Skris } 3355714Skris 3455714Skris bool ParseSectionSwitch(StringRef Section, 3555714Skris unsigned Characteristics, 3655714Skris SectionKind Kind); 37280297Sjkim 3855714Skris bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 3955714Skris SectionKind Kind, StringRef COMDATSymName, 40280297Sjkim COFF::COMDATType Type, const MCSectionCOFF *Assoc); 4155714Skris 4255714Skris bool ParseSectionName(StringRef &SectionName); 4355714Skris bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags); 4455714Skris 4555714Skris virtual void Initialize(MCAsmParser &Parser) { 4655714Skris // Call the base implementation. 4755714Skris MCAsmParserExtension::Initialize(Parser); 4855714Skris 4955714Skris addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); 5055714Skris addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); 5155714Skris addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); 52280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section"); 5355714Skris addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); 5455714Skris addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); 5555714Skris addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); 5655714Skris addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); 5755714Skris addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); 5855714Skris addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); 5955714Skris 60280297Sjkim // Win64 EH directives. 6155714Skris addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( 62280297Sjkim ".seh_proc"); 63109998Smarkm addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>( 64280297Sjkim ".seh_endproc"); 65280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>( 66280297Sjkim ".seh_startchained"); 67280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>( 68280297Sjkim ".seh_endchained"); 6955714Skris addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>( 70280297Sjkim ".seh_handler"); 71280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>( 7255714Skris ".seh_handlerdata"); 73280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>( 74280297Sjkim ".seh_pushreg"); 75280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>( 76280297Sjkim ".seh_setframe"); 77280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>( 78280297Sjkim ".seh_stackalloc"); 79280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>( 80280297Sjkim ".seh_savereg"); 81280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>( 82280297Sjkim ".seh_savexmm"); 83280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>( 8455714Skris ".seh_pushframe"); 85280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( 86280297Sjkim ".seh_endprologue"); 87280297Sjkim addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); 88280297Sjkim } 89280297Sjkim 90280297Sjkim bool ParseSectionDirectiveText(StringRef, SMLoc) { 9155714Skris return ParseSectionSwitch(".text", 92280297Sjkim COFF::IMAGE_SCN_CNT_CODE 93280297Sjkim | COFF::IMAGE_SCN_MEM_EXECUTE 94280297Sjkim | COFF::IMAGE_SCN_MEM_READ, 9555714Skris SectionKind::getText()); 96280297Sjkim } 97280297Sjkim bool ParseSectionDirectiveData(StringRef, SMLoc) { 98280297Sjkim return ParseSectionSwitch(".data", 99280297Sjkim COFF::IMAGE_SCN_CNT_INITIALIZED_DATA 100109998Smarkm | COFF::IMAGE_SCN_MEM_READ 101280297Sjkim | COFF::IMAGE_SCN_MEM_WRITE, 102280297Sjkim SectionKind::getDataRel()); 10355714Skris } 10455714Skris bool ParseSectionDirectiveBSS(StringRef, SMLoc) { 105280297Sjkim return ParseSectionSwitch(".bss", 106280297Sjkim COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA 10755714Skris | COFF::IMAGE_SCN_MEM_READ 108280297Sjkim | COFF::IMAGE_SCN_MEM_WRITE, 109280297Sjkim SectionKind::getBSS()); 110280297Sjkim } 111280297Sjkim 11255714Skris bool ParseDirectiveSection(StringRef, SMLoc); 11355714Skris bool ParseDirectiveDef(StringRef, SMLoc); 114280297Sjkim bool ParseDirectiveScl(StringRef, SMLoc); 115280297Sjkim bool ParseDirectiveType(StringRef, SMLoc); 116280297Sjkim bool ParseDirectiveEndef(StringRef, SMLoc); 117280297Sjkim bool ParseDirectiveSecRel32(StringRef, SMLoc); 118280297Sjkim bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type, 119280297Sjkim const MCSectionCOFF *&Assoc); 120280297Sjkim bool ParseDirectiveLinkOnce(StringRef, SMLoc); 121280297Sjkim 122280297Sjkim // Win64 EH directives. 123280297Sjkim bool ParseSEHDirectiveStartProc(StringRef, SMLoc); 124280297Sjkim bool ParseSEHDirectiveEndProc(StringRef, SMLoc); 125280297Sjkim bool ParseSEHDirectiveStartChained(StringRef, SMLoc); 126280297Sjkim bool ParseSEHDirectiveEndChained(StringRef, SMLoc); 127280297Sjkim bool ParseSEHDirectiveHandler(StringRef, SMLoc); 12855714Skris bool ParseSEHDirectiveHandlerData(StringRef, SMLoc); 129280297Sjkim bool ParseSEHDirectivePushReg(StringRef, SMLoc); 130280297Sjkim bool ParseSEHDirectiveSetFrame(StringRef, SMLoc); 131280297Sjkim bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); 132280297Sjkim bool ParseSEHDirectiveSaveReg(StringRef, SMLoc); 13355714Skris bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc); 134280297Sjkim bool ParseSEHDirectivePushFrame(StringRef, SMLoc); 135280297Sjkim bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); 136280297Sjkim 137280297Sjkim bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); 138280297Sjkim bool ParseSEHRegisterNumber(unsigned &RegNo); 13955714Skris bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc); 140280297Sjkimpublic: 141280297Sjkim COFFAsmParser() {} 142280297Sjkim}; 143280297Sjkim 14455714Skris} // end annonomous namespace. 145280297Sjkim 146280297Sjkimstatic SectionKind computeSectionKind(unsigned Flags) { 147280297Sjkim if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) 148280297Sjkim return SectionKind::getText(); 14955714Skris if (Flags & COFF::IMAGE_SCN_MEM_READ && 15055714Skris (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) 151280297Sjkim return SectionKind::getReadOnly(); 152280297Sjkim return SectionKind::getDataRel(); 153280297Sjkim} 154280297Sjkim 155280297Sjkimbool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) { 156280297Sjkim enum { 157280297Sjkim None = 0, 158280297Sjkim Alloc = 1 << 0, 159280297Sjkim Code = 1 << 1, 160280297Sjkim Load = 1 << 2, 161280297Sjkim InitData = 1 << 3, 162280297Sjkim Shared = 1 << 4, 163280297Sjkim NoLoad = 1 << 5, 16455714Skris NoRead = 1 << 6, 165290207Sjkim NoWrite = 1 << 7 166280297Sjkim }; 167290207Sjkim 168290207Sjkim bool ReadOnlyRemoved = false; 169280297Sjkim unsigned SecFlags = None; 170280297Sjkim 171280297Sjkim for (unsigned i = 0; i < FlagsString.size(); ++i) { 172280297Sjkim switch (FlagsString[i]) { 173280297Sjkim case 'a': 174280297Sjkim // Ignored. 175280297Sjkim break; 176280297Sjkim 177280297Sjkim case 'b': // bss section 178280297Sjkim SecFlags |= Alloc; 179109998Smarkm if (SecFlags & InitData) 180280297Sjkim return TokError("conflicting section flags 'b' and 'd'."); 181280297Sjkim SecFlags &= ~Load; 182280297Sjkim break; 18355714Skris 184280297Sjkim case 'd': // data section 185280297Sjkim SecFlags |= InitData; 186280297Sjkim if (SecFlags & Alloc) 187280297Sjkim return TokError("conflicting section flags 'b' and 'd'."); 18855714Skris SecFlags &= ~NoWrite; 189280297Sjkim if ((SecFlags & NoLoad) == 0) 19055714Skris SecFlags |= Load; 191280297Sjkim break; 192280297Sjkim 19355714Skris case 'n': // section is not loaded 194280297Sjkim SecFlags |= NoLoad; 195280297Sjkim SecFlags &= ~Load; 196280297Sjkim break; 197280297Sjkim 198280297Sjkim case 'r': // read-only 199280297Sjkim ReadOnlyRemoved = false; 200280297Sjkim SecFlags |= NoWrite; 201280297Sjkim if ((SecFlags & Code) == 0) 202280297Sjkim SecFlags |= InitData; 203280297Sjkim if ((SecFlags & NoLoad) == 0) 204280297Sjkim SecFlags |= Load; 20555714Skris break; 206280297Sjkim 207280297Sjkim case 's': // shared section 208280297Sjkim SecFlags |= Shared | InitData; 209280297Sjkim SecFlags &= ~NoWrite; 210280297Sjkim if ((SecFlags & NoLoad) == 0) 211280297Sjkim SecFlags |= Load; 212280297Sjkim break; 213280297Sjkim 214280297Sjkim case 'w': // writable 21555714Skris SecFlags &= ~NoWrite; 216280297Sjkim ReadOnlyRemoved = true; 217280297Sjkim break; 218280297Sjkim 219280297Sjkim case 'x': // executable section 220280297Sjkim SecFlags |= Code; 22155714Skris if ((SecFlags & NoLoad) == 0) 222280297Sjkim SecFlags |= Load; 223280297Sjkim if (!ReadOnlyRemoved) 224280297Sjkim SecFlags |= NoWrite; 225280297Sjkim break; 226280297Sjkim 227280297Sjkim case 'y': // not readable 228280297Sjkim SecFlags |= NoRead | NoWrite; 229280297Sjkim break; 230280297Sjkim 231280297Sjkim default: 232280297Sjkim return TokError("unknown flag"); 233280297Sjkim } 234280297Sjkim } 235280297Sjkim 236280297Sjkim *Flags = 0; 237280297Sjkim 238280297Sjkim if (SecFlags == None) 239280297Sjkim SecFlags = InitData; 240280297Sjkim 241280297Sjkim if (SecFlags & Code) 242280297Sjkim *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; 243280297Sjkim if (SecFlags & InitData) 244280297Sjkim *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 245280297Sjkim if ((SecFlags & Alloc) && (SecFlags & Load) == 0) 246280297Sjkim *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 247280297Sjkim if (SecFlags & NoLoad) 248280297Sjkim *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; 249280297Sjkim if ((SecFlags & NoRead) == 0) 250280297Sjkim *Flags |= COFF::IMAGE_SCN_MEM_READ; 251280297Sjkim if ((SecFlags & NoWrite) == 0) 252280297Sjkim *Flags |= COFF::IMAGE_SCN_MEM_WRITE; 253280297Sjkim if (SecFlags & Shared) 254280297Sjkim *Flags |= COFF::IMAGE_SCN_MEM_SHARED; 255280297Sjkim 256280297Sjkim return false; 257280297Sjkim} 258280297Sjkim 259280297Sjkim/// ParseDirectiveSymbolAttribute 260280297Sjkim/// ::= { ".weak", ... } [ identifier ( , identifier )* ] 261280297Sjkimbool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { 262280297Sjkim MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) 263280297Sjkim .Case(".weak", MCSA_Weak) 264280297Sjkim .Default(MCSA_Invalid); 265280297Sjkim assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); 266280297Sjkim if (getLexer().isNot(AsmToken::EndOfStatement)) { 267280297Sjkim for (;;) { 268280297Sjkim StringRef Name; 269280297Sjkim 270280297Sjkim if (getParser().parseIdentifier(Name)) 271280297Sjkim return TokError("expected identifier in directive"); 272280297Sjkim 273280297Sjkim MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 274280297Sjkim 275280297Sjkim getStreamer().EmitSymbolAttribute(Sym, Attr); 276280297Sjkim 277280297Sjkim if (getLexer().is(AsmToken::EndOfStatement)) 278280297Sjkim break; 279280297Sjkim 280280297Sjkim if (getLexer().isNot(AsmToken::Comma)) 281280297Sjkim return TokError("unexpected token in directive"); 282280297Sjkim Lex(); 283280297Sjkim } 284280297Sjkim } 285280297Sjkim 286280297Sjkim Lex(); 287280297Sjkim return false; 288280297Sjkim} 289280297Sjkim 290280297Sjkimbool COFFAsmParser::ParseSectionSwitch(StringRef Section, 291280297Sjkim unsigned Characteristics, 292280297Sjkim SectionKind Kind) { 29355714Skris return ParseSectionSwitch(Section, Characteristics, Kind, "", 294280297Sjkim COFF::IMAGE_COMDAT_SELECT_ANY, 0); 29555714Skris} 296280297Sjkim 297280297Sjkimbool COFFAsmParser::ParseSectionSwitch(StringRef Section, 298280297Sjkim unsigned Characteristics, 299280297Sjkim SectionKind Kind, 300280297Sjkim StringRef COMDATSymName, 301280297Sjkim COFF::COMDATType Type, 302280297Sjkim const MCSectionCOFF *Assoc) { 303280297Sjkim if (getLexer().isNot(AsmToken::EndOfStatement)) 304280297Sjkim return TokError("unexpected token in section switching directive"); 305280297Sjkim Lex(); 306280297Sjkim 307280297Sjkim getStreamer().SwitchSection(getContext().getCOFFSection( 308280297Sjkim Section, Characteristics, Kind, COMDATSymName, Type, Assoc)); 309280297Sjkim 310280297Sjkim return false; 311280297Sjkim} 312280297Sjkim 313280297Sjkimbool COFFAsmParser::ParseSectionName(StringRef &SectionName) { 314280297Sjkim if (!getLexer().is(AsmToken::Identifier)) 315280297Sjkim return true; 316280297Sjkim 317280297Sjkim SectionName = getTok().getIdentifier(); 318280297Sjkim Lex(); 319280297Sjkim return false; 320280297Sjkim} 321280297Sjkim 322280297Sjkim// .section name [, "flags"] [, identifier [ identifier ], identifier] 323280297Sjkim// 324280297Sjkim// Supported flags: 325280297Sjkim// a: Ignored. 326280297Sjkim// b: BSS section (uninitialized data) 327280297Sjkim// d: data section (initialized data) 328280297Sjkim// n: Discardable section 329280297Sjkim// r: Readable section 330280297Sjkim// s: Shared section 331280297Sjkim// w: Writable section 332280297Sjkim// x: Executable section 333280297Sjkim// y: Not-readable section (clears 'r') 334280297Sjkim// 335280297Sjkim// Subsections are not supported. 336280297Sjkimbool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { 337280297Sjkim StringRef SectionName; 338280297Sjkim 339280297Sjkim if (ParseSectionName(SectionName)) 340280297Sjkim return TokError("expected identifier in directive"); 341280297Sjkim 342280297Sjkim unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 343280297Sjkim COFF::IMAGE_SCN_MEM_READ | 344280297Sjkim COFF::IMAGE_SCN_MEM_WRITE; 345280297Sjkim 346280297Sjkim if (getLexer().is(AsmToken::Comma)) { 347280297Sjkim Lex(); 348280297Sjkim 349280297Sjkim if (getLexer().isNot(AsmToken::String)) 350280297Sjkim return TokError("expected string in directive"); 351280297Sjkim 352280297Sjkim StringRef FlagsStr = getTok().getStringContents(); 353280297Sjkim Lex(); 354280297Sjkim 35555714Skris if (ParseSectionFlags(FlagsStr, &Flags)) 356280297Sjkim return true; 35755714Skris } 358280297Sjkim 359280297Sjkim COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; 360280297Sjkim const MCSectionCOFF *Assoc = 0; 361280297Sjkim StringRef COMDATSymName; 362280297Sjkim if (getLexer().is(AsmToken::Comma)) { 363280297Sjkim Lex(); 364280297Sjkim 365280297Sjkim Flags |= COFF::IMAGE_SCN_LNK_COMDAT; 366280297Sjkim 367280297Sjkim if (parseCOMDATTypeAndAssoc(Type, Assoc)) 368280297Sjkim return true; 369280297Sjkim 370280297Sjkim if (getLexer().isNot(AsmToken::Comma)) 371280297Sjkim return TokError("expected comma in directive"); 37255714Skris Lex(); 373280297Sjkim 374280297Sjkim if (getParser().parseIdentifier(COMDATSymName)) 375280297Sjkim return TokError("expected identifier in directive"); 376280297Sjkim } 377280297Sjkim 378280297Sjkim if (getLexer().isNot(AsmToken::EndOfStatement)) 379280297Sjkim return TokError("unexpected token in directive"); 38055714Skris 381280297Sjkim SectionKind Kind = computeSectionKind(Flags); 382280297Sjkim ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc); 383280297Sjkim return false; 384280297Sjkim} 38555714Skris 386280297Sjkimbool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { 387280297Sjkim StringRef SymbolName; 388280297Sjkim 389280297Sjkim if (getParser().parseIdentifier(SymbolName)) 390280297Sjkim return TokError("expected identifier in directive"); 391280297Sjkim 392280297Sjkim MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName); 393280297Sjkim 39455714Skris getStreamer().BeginCOFFSymbolDef(Sym); 395280297Sjkim 396280297Sjkim Lex(); 397280297Sjkim return false; 398280297Sjkim} 399280297Sjkim 400280297Sjkimbool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) { 401280297Sjkim int64_t SymbolStorageClass; 402280297Sjkim if (getParser().parseAbsoluteExpression(SymbolStorageClass)) 403280297Sjkim return true; 40455714Skris 405280297Sjkim if (getLexer().isNot(AsmToken::EndOfStatement)) 406280297Sjkim return TokError("unexpected token in directive"); 407280297Sjkim 408280297Sjkim Lex(); 409280297Sjkim getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass); 410280297Sjkim return false; 411280297Sjkim} 412280297Sjkim 413280297Sjkimbool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) { 41455714Skris int64_t Type; 415280297Sjkim if (getParser().parseAbsoluteExpression(Type)) 416280297Sjkim return true; 417280297Sjkim 418280297Sjkim if (getLexer().isNot(AsmToken::EndOfStatement)) 419280297Sjkim return TokError("unexpected token in directive"); 420280297Sjkim 421280297Sjkim Lex(); 422280297Sjkim getStreamer().EmitCOFFSymbolType(Type); 423280297Sjkim return false; 42455714Skris} 425280297Sjkim 426280297Sjkimbool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { 427280297Sjkim Lex(); 428280297Sjkim getStreamer().EndCOFFSymbolDef(); 429280297Sjkim return false; 430280297Sjkim} 431280297Sjkim 432280297Sjkimbool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { 433280297Sjkim StringRef SymbolID; 43455714Skris if (getParser().parseIdentifier(SymbolID)) 435160814Ssimon return true; 43655714Skris 437280297Sjkim if (getLexer().isNot(AsmToken::EndOfStatement)) 438280297Sjkim return TokError("unexpected token in directive"); 439238405Sjkim 440280297Sjkim MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); 441280297Sjkim 442280297Sjkim Lex(); 44355714Skris 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