10b57cec5SDimitry Andric //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 100b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 110b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 120b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 130b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 140b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h" 150b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCSectionCOFF.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 190b57cec5SDimitry Andric #include "llvm/MC/SectionKind.h" 200b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h" 2106c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 220b57cec5SDimitry Andric #include <cassert> 230b57cec5SDimitry Andric #include <cstdint> 240b57cec5SDimitry Andric #include <limits> 250b57cec5SDimitry Andric #include <utility> 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace llvm; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric namespace { 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric class COFFAsmParser : public MCAsmParserExtension { 320b57cec5SDimitry Andric template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)> 330b57cec5SDimitry Andric void addDirectiveHandler(StringRef Directive) { 340b57cec5SDimitry Andric MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( 350b57cec5SDimitry Andric this, HandleDirective<COFFAsmParser, HandlerMethod>); 360b57cec5SDimitry Andric getParser().addDirectiveHandler(Directive, Handler); 370b57cec5SDimitry Andric } 380b57cec5SDimitry Andric 39*0fca6ea1SDimitry Andric bool ParseSectionSwitch(StringRef Section, unsigned Characteristics); 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 42*0fca6ea1SDimitry Andric StringRef COMDATSymName, COFF::COMDATType Type); 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric bool ParseSectionName(StringRef &SectionName); 450b57cec5SDimitry Andric bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString, 460b57cec5SDimitry Andric unsigned *Flags); 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric void Initialize(MCAsmParser &Parser) override { 490b57cec5SDimitry Andric // Call the base implementation. 500b57cec5SDimitry Andric MCAsmParserExtension::Initialize(Parser); 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); 530b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); 540b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); 550b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section"); 5606c3fb27SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectivePushSection>( 5706c3fb27SDimitry Andric ".pushsection"); 5806c3fb27SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectivePopSection>( 5906c3fb27SDimitry Andric ".popsection"); 600b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); 610b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); 620b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); 630b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); 640b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); 650b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx"); 660b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh"); 670b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx"); 680b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce"); 690b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva"); 708bcb0991SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); 7106c3fb27SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak_anti_dep"); 725ffd83dbSDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile"); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Win64 EH directives. 750b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( 760b57cec5SDimitry Andric ".seh_proc"); 770b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>( 780b57cec5SDimitry Andric ".seh_endproc"); 79e8d8bef9SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc>( 80e8d8bef9SDimitry Andric ".seh_endfunclet"); 810b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>( 820b57cec5SDimitry Andric ".seh_startchained"); 830b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>( 840b57cec5SDimitry Andric ".seh_endchained"); 850b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>( 860b57cec5SDimitry Andric ".seh_handler"); 870b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>( 880b57cec5SDimitry Andric ".seh_handlerdata"); 890b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>( 900b57cec5SDimitry Andric ".seh_stackalloc"); 910b57cec5SDimitry Andric addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( 920b57cec5SDimitry Andric ".seh_endprologue"); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric bool ParseSectionDirectiveText(StringRef, SMLoc) { 96*0fca6ea1SDimitry Andric return ParseSectionSwitch(".text", COFF::IMAGE_SCN_CNT_CODE | 97*0fca6ea1SDimitry Andric COFF::IMAGE_SCN_MEM_EXECUTE | 98*0fca6ea1SDimitry Andric COFF::IMAGE_SCN_MEM_READ); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric bool ParseSectionDirectiveData(StringRef, SMLoc) { 1020b57cec5SDimitry Andric return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 1030b57cec5SDimitry Andric COFF::IMAGE_SCN_MEM_READ | 104*0fca6ea1SDimitry Andric COFF::IMAGE_SCN_MEM_WRITE); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric bool ParseSectionDirectiveBSS(StringRef, SMLoc) { 108*0fca6ea1SDimitry Andric return ParseSectionSwitch(".bss", COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 109*0fca6ea1SDimitry Andric COFF::IMAGE_SCN_MEM_READ | 110*0fca6ea1SDimitry Andric COFF::IMAGE_SCN_MEM_WRITE); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric bool ParseDirectiveSection(StringRef, SMLoc); 11406c3fb27SDimitry Andric bool parseSectionArguments(StringRef, SMLoc); 11506c3fb27SDimitry Andric bool ParseDirectivePushSection(StringRef, SMLoc); 11606c3fb27SDimitry Andric bool ParseDirectivePopSection(StringRef, SMLoc); 1170b57cec5SDimitry Andric bool ParseDirectiveDef(StringRef, SMLoc); 1180b57cec5SDimitry Andric bool ParseDirectiveScl(StringRef, SMLoc); 1190b57cec5SDimitry Andric bool ParseDirectiveType(StringRef, SMLoc); 1200b57cec5SDimitry Andric bool ParseDirectiveEndef(StringRef, SMLoc); 1210b57cec5SDimitry Andric bool ParseDirectiveSecRel32(StringRef, SMLoc); 1220b57cec5SDimitry Andric bool ParseDirectiveSecIdx(StringRef, SMLoc); 1230b57cec5SDimitry Andric bool ParseDirectiveSafeSEH(StringRef, SMLoc); 1240b57cec5SDimitry Andric bool ParseDirectiveSymIdx(StringRef, SMLoc); 1250b57cec5SDimitry Andric bool parseCOMDATType(COFF::COMDATType &Type); 1260b57cec5SDimitry Andric bool ParseDirectiveLinkOnce(StringRef, SMLoc); 1270b57cec5SDimitry Andric bool ParseDirectiveRVA(StringRef, SMLoc); 1285ffd83dbSDimitry Andric bool ParseDirectiveCGProfile(StringRef, SMLoc); 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric // Win64 EH directives. 1310b57cec5SDimitry Andric bool ParseSEHDirectiveStartProc(StringRef, SMLoc); 1320b57cec5SDimitry Andric bool ParseSEHDirectiveEndProc(StringRef, SMLoc); 133e8d8bef9SDimitry Andric bool ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc); 1340b57cec5SDimitry Andric bool ParseSEHDirectiveStartChained(StringRef, SMLoc); 1350b57cec5SDimitry Andric bool ParseSEHDirectiveEndChained(StringRef, SMLoc); 1360b57cec5SDimitry Andric bool ParseSEHDirectiveHandler(StringRef, SMLoc); 1370b57cec5SDimitry Andric bool ParseSEHDirectiveHandlerData(StringRef, SMLoc); 1380b57cec5SDimitry Andric bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); 1390b57cec5SDimitry Andric bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); 1420b57cec5SDimitry Andric bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric public: 1450b57cec5SDimitry Andric COFFAsmParser() = default; 1460b57cec5SDimitry Andric }; 1470b57cec5SDimitry Andric 148480093f4SDimitry Andric } // end anonymous namespace. 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric bool COFFAsmParser::ParseSectionFlags(StringRef SectionName, 1510b57cec5SDimitry Andric StringRef FlagsString, unsigned *Flags) { 1520b57cec5SDimitry Andric enum { 1530b57cec5SDimitry Andric None = 0, 1540b57cec5SDimitry Andric Alloc = 1 << 0, 1550b57cec5SDimitry Andric Code = 1 << 1, 1560b57cec5SDimitry Andric Load = 1 << 2, 1570b57cec5SDimitry Andric InitData = 1 << 3, 1580b57cec5SDimitry Andric Shared = 1 << 4, 1590b57cec5SDimitry Andric NoLoad = 1 << 5, 1600b57cec5SDimitry Andric NoRead = 1 << 6, 1610b57cec5SDimitry Andric NoWrite = 1 << 7, 1620b57cec5SDimitry Andric Discardable = 1 << 8, 163bdd1243dSDimitry Andric Info = 1 << 9, 1640b57cec5SDimitry Andric }; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric bool ReadOnlyRemoved = false; 1670b57cec5SDimitry Andric unsigned SecFlags = None; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric for (char FlagChar : FlagsString) { 1700b57cec5SDimitry Andric switch (FlagChar) { 1710b57cec5SDimitry Andric case 'a': 1720b57cec5SDimitry Andric // Ignored. 1730b57cec5SDimitry Andric break; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric case 'b': // bss section 1760b57cec5SDimitry Andric SecFlags |= Alloc; 1770b57cec5SDimitry Andric if (SecFlags & InitData) 1780b57cec5SDimitry Andric return TokError("conflicting section flags 'b' and 'd'."); 1790b57cec5SDimitry Andric SecFlags &= ~Load; 1800b57cec5SDimitry Andric break; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric case 'd': // data section 1830b57cec5SDimitry Andric SecFlags |= InitData; 1840b57cec5SDimitry Andric if (SecFlags & Alloc) 1850b57cec5SDimitry Andric return TokError("conflicting section flags 'b' and 'd'."); 1860b57cec5SDimitry Andric SecFlags &= ~NoWrite; 1870b57cec5SDimitry Andric if ((SecFlags & NoLoad) == 0) 1880b57cec5SDimitry Andric SecFlags |= Load; 1890b57cec5SDimitry Andric break; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric case 'n': // section is not loaded 1920b57cec5SDimitry Andric SecFlags |= NoLoad; 1930b57cec5SDimitry Andric SecFlags &= ~Load; 1940b57cec5SDimitry Andric break; 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric case 'D': // discardable 1970b57cec5SDimitry Andric SecFlags |= Discardable; 1980b57cec5SDimitry Andric break; 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric case 'r': // read-only 2010b57cec5SDimitry Andric ReadOnlyRemoved = false; 2020b57cec5SDimitry Andric SecFlags |= NoWrite; 2030b57cec5SDimitry Andric if ((SecFlags & Code) == 0) 2040b57cec5SDimitry Andric SecFlags |= InitData; 2050b57cec5SDimitry Andric if ((SecFlags & NoLoad) == 0) 2060b57cec5SDimitry Andric SecFlags |= Load; 2070b57cec5SDimitry Andric break; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric case 's': // shared section 2100b57cec5SDimitry Andric SecFlags |= Shared | InitData; 2110b57cec5SDimitry Andric SecFlags &= ~NoWrite; 2120b57cec5SDimitry Andric if ((SecFlags & NoLoad) == 0) 2130b57cec5SDimitry Andric SecFlags |= Load; 2140b57cec5SDimitry Andric break; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric case 'w': // writable 2170b57cec5SDimitry Andric SecFlags &= ~NoWrite; 2180b57cec5SDimitry Andric ReadOnlyRemoved = true; 2190b57cec5SDimitry Andric break; 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric case 'x': // executable section 2220b57cec5SDimitry Andric SecFlags |= Code; 2230b57cec5SDimitry Andric if ((SecFlags & NoLoad) == 0) 2240b57cec5SDimitry Andric SecFlags |= Load; 2250b57cec5SDimitry Andric if (!ReadOnlyRemoved) 2260b57cec5SDimitry Andric SecFlags |= NoWrite; 2270b57cec5SDimitry Andric break; 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric case 'y': // not readable 2300b57cec5SDimitry Andric SecFlags |= NoRead | NoWrite; 2310b57cec5SDimitry Andric break; 2320b57cec5SDimitry Andric 233bdd1243dSDimitry Andric case 'i': // info 234bdd1243dSDimitry Andric SecFlags |= Info; 235bdd1243dSDimitry Andric break; 236bdd1243dSDimitry Andric 2370b57cec5SDimitry Andric default: 2380b57cec5SDimitry Andric return TokError("unknown flag"); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric *Flags = 0; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric if (SecFlags == None) 2450b57cec5SDimitry Andric SecFlags = InitData; 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric if (SecFlags & Code) 2480b57cec5SDimitry Andric *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE; 2490b57cec5SDimitry Andric if (SecFlags & InitData) 2500b57cec5SDimitry Andric *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; 2510b57cec5SDimitry Andric if ((SecFlags & Alloc) && (SecFlags & Load) == 0) 2520b57cec5SDimitry Andric *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; 2530b57cec5SDimitry Andric if (SecFlags & NoLoad) 2540b57cec5SDimitry Andric *Flags |= COFF::IMAGE_SCN_LNK_REMOVE; 2550b57cec5SDimitry Andric if ((SecFlags & Discardable) || 2560b57cec5SDimitry Andric MCSectionCOFF::isImplicitlyDiscardable(SectionName)) 2570b57cec5SDimitry Andric *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE; 2580b57cec5SDimitry Andric if ((SecFlags & NoRead) == 0) 2590b57cec5SDimitry Andric *Flags |= COFF::IMAGE_SCN_MEM_READ; 2600b57cec5SDimitry Andric if ((SecFlags & NoWrite) == 0) 2610b57cec5SDimitry Andric *Flags |= COFF::IMAGE_SCN_MEM_WRITE; 2620b57cec5SDimitry Andric if (SecFlags & Shared) 2630b57cec5SDimitry Andric *Flags |= COFF::IMAGE_SCN_MEM_SHARED; 264bdd1243dSDimitry Andric if (SecFlags & Info) 265bdd1243dSDimitry Andric *Flags |= COFF::IMAGE_SCN_LNK_INFO; 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric return false; 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric /// ParseDirectiveSymbolAttribute 2710b57cec5SDimitry Andric /// ::= { ".weak", ... } [ identifier ( , identifier )* ] 2720b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { 2730b57cec5SDimitry Andric MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive) 2740b57cec5SDimitry Andric .Case(".weak", MCSA_Weak) 27506c3fb27SDimitry Andric .Case(".weak_anti_dep", MCSA_WeakAntiDep) 2760b57cec5SDimitry Andric .Default(MCSA_Invalid); 2770b57cec5SDimitry Andric assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); 2780b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) { 2790b57cec5SDimitry Andric while (true) { 2800b57cec5SDimitry Andric StringRef Name; 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric if (getParser().parseIdentifier(Name)) 2830b57cec5SDimitry Andric return TokError("expected identifier in directive"); 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 2860b57cec5SDimitry Andric 2875ffd83dbSDimitry Andric getStreamer().emitSymbolAttribute(Sym, Attr); 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric if (getLexer().is(AsmToken::EndOfStatement)) 2900b57cec5SDimitry Andric break; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Comma)) 2930b57cec5SDimitry Andric return TokError("unexpected token in directive"); 2940b57cec5SDimitry Andric Lex(); 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric Lex(); 2990b57cec5SDimitry Andric return false; 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3025ffd83dbSDimitry Andric bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) { 3035ffd83dbSDimitry Andric return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc); 3045ffd83dbSDimitry Andric } 3055ffd83dbSDimitry Andric 3060b57cec5SDimitry Andric bool COFFAsmParser::ParseSectionSwitch(StringRef Section, 307*0fca6ea1SDimitry Andric unsigned Characteristics) { 308*0fca6ea1SDimitry Andric return ParseSectionSwitch(Section, Characteristics, "", (COFF::COMDATType)0); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric bool COFFAsmParser::ParseSectionSwitch(StringRef Section, 3120b57cec5SDimitry Andric unsigned Characteristics, 3130b57cec5SDimitry Andric StringRef COMDATSymName, 3140b57cec5SDimitry Andric COFF::COMDATType Type) { 3150b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 3160b57cec5SDimitry Andric return TokError("unexpected token in section switching directive"); 3170b57cec5SDimitry Andric Lex(); 3180b57cec5SDimitry Andric 31981ad6265SDimitry Andric getStreamer().switchSection(getContext().getCOFFSection( 320*0fca6ea1SDimitry Andric Section, Characteristics, COMDATSymName, Type)); 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric return false; 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric bool COFFAsmParser::ParseSectionName(StringRef &SectionName) { 3265ffd83dbSDimitry Andric if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String)) 3270b57cec5SDimitry Andric return true; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric SectionName = getTok().getIdentifier(); 3300b57cec5SDimitry Andric Lex(); 3310b57cec5SDimitry Andric return false; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 33406c3fb27SDimitry Andric bool COFFAsmParser::ParseDirectiveSection(StringRef directive, SMLoc loc) { 33506c3fb27SDimitry Andric return parseSectionArguments(directive, loc); 33606c3fb27SDimitry Andric } 33706c3fb27SDimitry Andric 3380b57cec5SDimitry Andric // .section name [, "flags"] [, identifier [ identifier ], identifier] 33906c3fb27SDimitry Andric // .pushsection <same as above> 3400b57cec5SDimitry Andric // 3410b57cec5SDimitry Andric // Supported flags: 3420b57cec5SDimitry Andric // a: Ignored. 3430b57cec5SDimitry Andric // b: BSS section (uninitialized data) 3440b57cec5SDimitry Andric // d: data section (initialized data) 3450b57cec5SDimitry Andric // n: "noload" section (removed by linker) 3460b57cec5SDimitry Andric // D: Discardable section 3470b57cec5SDimitry Andric // r: Readable section 3480b57cec5SDimitry Andric // s: Shared section 3490b57cec5SDimitry Andric // w: Writable section 3500b57cec5SDimitry Andric // x: Executable section 3510b57cec5SDimitry Andric // y: Not-readable section (clears 'r') 3520b57cec5SDimitry Andric // 3530b57cec5SDimitry Andric // Subsections are not supported. 35406c3fb27SDimitry Andric bool COFFAsmParser::parseSectionArguments(StringRef, SMLoc) { 3550b57cec5SDimitry Andric StringRef SectionName; 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric if (ParseSectionName(SectionName)) 3580b57cec5SDimitry Andric return TokError("expected identifier in directive"); 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 3610b57cec5SDimitry Andric COFF::IMAGE_SCN_MEM_READ | 3620b57cec5SDimitry Andric COFF::IMAGE_SCN_MEM_WRITE; 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric if (getLexer().is(AsmToken::Comma)) { 3650b57cec5SDimitry Andric Lex(); 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::String)) 3680b57cec5SDimitry Andric return TokError("expected string in directive"); 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric StringRef FlagsStr = getTok().getStringContents(); 3710b57cec5SDimitry Andric Lex(); 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric if (ParseSectionFlags(SectionName, FlagsStr, &Flags)) 3740b57cec5SDimitry Andric return true; 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric COFF::COMDATType Type = (COFF::COMDATType)0; 3780b57cec5SDimitry Andric StringRef COMDATSymName; 3790b57cec5SDimitry Andric if (getLexer().is(AsmToken::Comma)) { 3800b57cec5SDimitry Andric Type = COFF::IMAGE_COMDAT_SELECT_ANY; 3810b57cec5SDimitry Andric Lex(); 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric Flags |= COFF::IMAGE_SCN_LNK_COMDAT; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric if (!getLexer().is(AsmToken::Identifier)) 3860b57cec5SDimitry Andric return TokError("expected comdat type such as 'discard' or 'largest' " 3870b57cec5SDimitry Andric "after protection bits"); 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric if (parseCOMDATType(Type)) 3900b57cec5SDimitry Andric return true; 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Comma)) 3930b57cec5SDimitry Andric return TokError("expected comma in directive"); 3940b57cec5SDimitry Andric Lex(); 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric if (getParser().parseIdentifier(COMDATSymName)) 3970b57cec5SDimitry Andric return TokError("expected identifier in directive"); 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 4010b57cec5SDimitry Andric return TokError("unexpected token in directive"); 4020b57cec5SDimitry Andric 403*0fca6ea1SDimitry Andric if (Flags & COFF::IMAGE_SCN_CNT_CODE) { 404fe6060f1SDimitry Andric const Triple &T = getContext().getTargetTriple(); 4050b57cec5SDimitry Andric if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) 4060b57cec5SDimitry Andric Flags |= COFF::IMAGE_SCN_MEM_16BIT; 4070b57cec5SDimitry Andric } 408*0fca6ea1SDimitry Andric ParseSectionSwitch(SectionName, Flags, COMDATSymName, Type); 4090b57cec5SDimitry Andric return false; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 41206c3fb27SDimitry Andric bool COFFAsmParser::ParseDirectivePushSection(StringRef directive, SMLoc loc) { 41306c3fb27SDimitry Andric getStreamer().pushSection(); 41406c3fb27SDimitry Andric 41506c3fb27SDimitry Andric if (parseSectionArguments(directive, loc)) { 41606c3fb27SDimitry Andric getStreamer().popSection(); 41706c3fb27SDimitry Andric return true; 41806c3fb27SDimitry Andric } 41906c3fb27SDimitry Andric 42006c3fb27SDimitry Andric return false; 42106c3fb27SDimitry Andric } 42206c3fb27SDimitry Andric 42306c3fb27SDimitry Andric bool COFFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { 42406c3fb27SDimitry Andric if (!getStreamer().popSection()) 42506c3fb27SDimitry Andric return TokError(".popsection without corresponding .pushsection"); 42606c3fb27SDimitry Andric return false; 42706c3fb27SDimitry Andric } 42806c3fb27SDimitry Andric 4290b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { 4300b57cec5SDimitry Andric StringRef SymbolName; 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric if (getParser().parseIdentifier(SymbolName)) 4330b57cec5SDimitry Andric return TokError("expected identifier in directive"); 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName); 4360b57cec5SDimitry Andric 43781ad6265SDimitry Andric getStreamer().beginCOFFSymbolDef(Sym); 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric Lex(); 4400b57cec5SDimitry Andric return false; 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) { 4440b57cec5SDimitry Andric int64_t SymbolStorageClass; 4450b57cec5SDimitry Andric if (getParser().parseAbsoluteExpression(SymbolStorageClass)) 4460b57cec5SDimitry Andric return true; 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 4490b57cec5SDimitry Andric return TokError("unexpected token in directive"); 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric Lex(); 45281ad6265SDimitry Andric getStreamer().emitCOFFSymbolStorageClass(SymbolStorageClass); 4530b57cec5SDimitry Andric return false; 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) { 4570b57cec5SDimitry Andric int64_t Type; 4580b57cec5SDimitry Andric if (getParser().parseAbsoluteExpression(Type)) 4590b57cec5SDimitry Andric return true; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 4620b57cec5SDimitry Andric return TokError("unexpected token in directive"); 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric Lex(); 46581ad6265SDimitry Andric getStreamer().emitCOFFSymbolType(Type); 4660b57cec5SDimitry Andric return false; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { 4700b57cec5SDimitry Andric Lex(); 47181ad6265SDimitry Andric getStreamer().endCOFFSymbolDef(); 4720b57cec5SDimitry Andric return false; 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { 4760b57cec5SDimitry Andric StringRef SymbolID; 4770b57cec5SDimitry Andric if (getParser().parseIdentifier(SymbolID)) 4780b57cec5SDimitry Andric return TokError("expected identifier in directive"); 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric int64_t Offset = 0; 4810b57cec5SDimitry Andric SMLoc OffsetLoc; 4820b57cec5SDimitry Andric if (getLexer().is(AsmToken::Plus)) { 4830b57cec5SDimitry Andric OffsetLoc = getLexer().getLoc(); 4840b57cec5SDimitry Andric if (getParser().parseAbsoluteExpression(Offset)) 4850b57cec5SDimitry Andric return true; 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 4890b57cec5SDimitry Andric return TokError("unexpected token in directive"); 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max()) 4920b57cec5SDimitry Andric return Error( 4930b57cec5SDimitry Andric OffsetLoc, 4940b57cec5SDimitry Andric "invalid '.secrel32' directive offset, can't be less " 4950b57cec5SDimitry Andric "than zero or greater than std::numeric_limits<uint32_t>::max()"); 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric Lex(); 50081ad6265SDimitry Andric getStreamer().emitCOFFSecRel32(Symbol, Offset); 5010b57cec5SDimitry Andric return false; 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) { 5050b57cec5SDimitry Andric auto parseOp = [&]() -> bool { 5060b57cec5SDimitry Andric StringRef SymbolID; 5070b57cec5SDimitry Andric if (getParser().parseIdentifier(SymbolID)) 5080b57cec5SDimitry Andric return TokError("expected identifier in directive"); 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric int64_t Offset = 0; 5110b57cec5SDimitry Andric SMLoc OffsetLoc; 5120b57cec5SDimitry Andric if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) { 5130b57cec5SDimitry Andric OffsetLoc = getLexer().getLoc(); 5140b57cec5SDimitry Andric if (getParser().parseAbsoluteExpression(Offset)) 5150b57cec5SDimitry Andric return true; 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric if (Offset < std::numeric_limits<int32_t>::min() || 5190b57cec5SDimitry Andric Offset > std::numeric_limits<int32_t>::max()) 5200b57cec5SDimitry Andric return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less " 5210b57cec5SDimitry Andric "than -2147483648 or greater than " 5220b57cec5SDimitry Andric "2147483647"); 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 5250b57cec5SDimitry Andric 52681ad6265SDimitry Andric getStreamer().emitCOFFImgRel32(Symbol, Offset); 5270b57cec5SDimitry Andric return false; 5280b57cec5SDimitry Andric }; 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric if (getParser().parseMany(parseOp)) 5310b57cec5SDimitry Andric return addErrorSuffix(" in directive"); 5320b57cec5SDimitry Andric return false; 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) { 5360b57cec5SDimitry Andric StringRef SymbolID; 5370b57cec5SDimitry Andric if (getParser().parseIdentifier(SymbolID)) 5380b57cec5SDimitry Andric return TokError("expected identifier in directive"); 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 5410b57cec5SDimitry Andric return TokError("unexpected token in directive"); 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric Lex(); 54681ad6265SDimitry Andric getStreamer().emitCOFFSafeSEH(Symbol); 5470b57cec5SDimitry Andric return false; 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) { 5510b57cec5SDimitry Andric StringRef SymbolID; 5520b57cec5SDimitry Andric if (getParser().parseIdentifier(SymbolID)) 5530b57cec5SDimitry Andric return TokError("expected identifier in directive"); 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 5560b57cec5SDimitry Andric return TokError("unexpected token in directive"); 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric Lex(); 56181ad6265SDimitry Andric getStreamer().emitCOFFSectionIndex(Symbol); 5620b57cec5SDimitry Andric return false; 5630b57cec5SDimitry Andric } 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) { 5660b57cec5SDimitry Andric StringRef SymbolID; 5670b57cec5SDimitry Andric if (getParser().parseIdentifier(SymbolID)) 5680b57cec5SDimitry Andric return TokError("expected identifier in directive"); 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 5710b57cec5SDimitry Andric return TokError("unexpected token in directive"); 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric Lex(); 57681ad6265SDimitry Andric getStreamer().emitCOFFSymbolIndex(Symbol); 5770b57cec5SDimitry Andric return false; 5780b57cec5SDimitry Andric } 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric /// ::= [ identifier ] 5810b57cec5SDimitry Andric bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) { 5820b57cec5SDimitry Andric StringRef TypeId = getTok().getIdentifier(); 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric Type = StringSwitch<COFF::COMDATType>(TypeId) 5850b57cec5SDimitry Andric .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) 5860b57cec5SDimitry Andric .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY) 5870b57cec5SDimitry Andric .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE) 5880b57cec5SDimitry Andric .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH) 5890b57cec5SDimitry Andric .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) 5900b57cec5SDimitry Andric .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST) 5910b57cec5SDimitry Andric .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST) 5920b57cec5SDimitry Andric .Default((COFF::COMDATType)0); 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric if (Type == 0) 5950b57cec5SDimitry Andric return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'")); 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric Lex(); 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric return false; 6000b57cec5SDimitry Andric } 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric /// ParseDirectiveLinkOnce 6030b57cec5SDimitry Andric /// ::= .linkonce [ identifier ] 6040b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { 6050b57cec5SDimitry Andric COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY; 6060b57cec5SDimitry Andric if (getLexer().is(AsmToken::Identifier)) 6070b57cec5SDimitry Andric if (parseCOMDATType(Type)) 6080b57cec5SDimitry Andric return true; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric const MCSectionCOFF *Current = 6110b57cec5SDimitry Andric static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly()); 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) 6140b57cec5SDimitry Andric return Error(Loc, "cannot make section associative with .linkonce"); 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) 6175ffd83dbSDimitry Andric return Error(Loc, Twine("section '") + Current->getName() + 6180b57cec5SDimitry Andric "' is already linkonce"); 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric Current->setSelection(Type); 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 6230b57cec5SDimitry Andric return TokError("unexpected token in directive"); 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric return false; 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) { 6290b57cec5SDimitry Andric StringRef SymbolID; 6300b57cec5SDimitry Andric if (getParser().parseIdentifier(SymbolID)) 6310b57cec5SDimitry Andric return true; 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 6340b57cec5SDimitry Andric return TokError("unexpected token in directive"); 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric Lex(); 63981ad6265SDimitry Andric getStreamer().emitWinCFIStartProc(Symbol, Loc); 6400b57cec5SDimitry Andric return false; 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) { 6440b57cec5SDimitry Andric Lex(); 64581ad6265SDimitry Andric getStreamer().emitWinCFIEndProc(Loc); 6460b57cec5SDimitry Andric return false; 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric 649e8d8bef9SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc Loc) { 650e8d8bef9SDimitry Andric Lex(); 65181ad6265SDimitry Andric getStreamer().emitWinCFIFuncletOrFuncEnd(Loc); 652e8d8bef9SDimitry Andric return false; 653e8d8bef9SDimitry Andric } 654e8d8bef9SDimitry Andric 6550b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) { 6560b57cec5SDimitry Andric Lex(); 65781ad6265SDimitry Andric getStreamer().emitWinCFIStartChained(Loc); 6580b57cec5SDimitry Andric return false; 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) { 6620b57cec5SDimitry Andric Lex(); 66381ad6265SDimitry Andric getStreamer().emitWinCFIEndChained(Loc); 6640b57cec5SDimitry Andric return false; 6650b57cec5SDimitry Andric } 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) { 6680b57cec5SDimitry Andric StringRef SymbolID; 6690b57cec5SDimitry Andric if (getParser().parseIdentifier(SymbolID)) 6700b57cec5SDimitry Andric return true; 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Comma)) 6730b57cec5SDimitry Andric return TokError("you must specify one or both of @unwind or @except"); 6740b57cec5SDimitry Andric Lex(); 6750b57cec5SDimitry Andric bool unwind = false, except = false; 6760b57cec5SDimitry Andric if (ParseAtUnwindOrAtExcept(unwind, except)) 6770b57cec5SDimitry Andric return true; 6780b57cec5SDimitry Andric if (getLexer().is(AsmToken::Comma)) { 6790b57cec5SDimitry Andric Lex(); 6800b57cec5SDimitry Andric if (ParseAtUnwindOrAtExcept(unwind, except)) 6810b57cec5SDimitry Andric return true; 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 6840b57cec5SDimitry Andric return TokError("unexpected token in directive"); 6850b57cec5SDimitry Andric 6860b57cec5SDimitry Andric MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID); 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric Lex(); 68981ad6265SDimitry Andric getStreamer().emitWinEHHandler(handler, unwind, except, Loc); 6900b57cec5SDimitry Andric return false; 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) { 6940b57cec5SDimitry Andric Lex(); 69581ad6265SDimitry Andric getStreamer().emitWinEHHandlerData(); 6960b57cec5SDimitry Andric return false; 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) { 7000b57cec5SDimitry Andric int64_t Size; 7010b57cec5SDimitry Andric if (getParser().parseAbsoluteExpression(Size)) 7020b57cec5SDimitry Andric return true; 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 7050b57cec5SDimitry Andric return TokError("unexpected token in directive"); 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric Lex(); 70881ad6265SDimitry Andric getStreamer().emitWinCFIAllocStack(Size, Loc); 7090b57cec5SDimitry Andric return false; 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) { 7130b57cec5SDimitry Andric Lex(); 71481ad6265SDimitry Andric getStreamer().emitWinCFIEndProlog(Loc); 7150b57cec5SDimitry Andric return false; 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { 7190b57cec5SDimitry Andric StringRef identifier; 72081ad6265SDimitry Andric if (getLexer().isNot(AsmToken::At) && getLexer().isNot(AsmToken::Percent)) 72181ad6265SDimitry Andric return TokError("a handler attribute must begin with '@' or '%'"); 7220b57cec5SDimitry Andric SMLoc startLoc = getLexer().getLoc(); 7230b57cec5SDimitry Andric Lex(); 7240b57cec5SDimitry Andric if (getParser().parseIdentifier(identifier)) 7250b57cec5SDimitry Andric return Error(startLoc, "expected @unwind or @except"); 7260b57cec5SDimitry Andric if (identifier == "unwind") 7270b57cec5SDimitry Andric unwind = true; 7280b57cec5SDimitry Andric else if (identifier == "except") 7290b57cec5SDimitry Andric except = true; 7300b57cec5SDimitry Andric else 7310b57cec5SDimitry Andric return Error(startLoc, "expected @unwind or @except"); 7320b57cec5SDimitry Andric return false; 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric namespace llvm { 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric MCAsmParserExtension *createCOFFAsmParser() { 7380b57cec5SDimitry Andric return new COFFAsmParser; 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric } // end namespace llvm 742