15ffd83dbSDimitry Andric //===- COFFMasmParser.cpp - COFF MASM Assembly Parser ---------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h" 105ffd83dbSDimitry Andric #include "llvm/ADT/Twine.h" 115ffd83dbSDimitry Andric #include "llvm/BinaryFormat/COFF.h" 125ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 135ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 145ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h" 155ffd83dbSDimitry Andric #include "llvm/MC/MCSectionCOFF.h" 165ffd83dbSDimitry Andric #include "llvm/MC/MCStreamer.h" 17e8d8bef9SDimitry Andric #include "llvm/MC/MCSymbolCOFF.h" 185ffd83dbSDimitry Andric #include "llvm/MC/SectionKind.h" 19*81ad6265SDimitry Andric #include "llvm/Support/Casting.h" 205ffd83dbSDimitry Andric #include "llvm/Support/SMLoc.h" 215ffd83dbSDimitry Andric #include <cstdint> 225ffd83dbSDimitry Andric #include <utility> 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric using namespace llvm; 255ffd83dbSDimitry Andric 265ffd83dbSDimitry Andric namespace { 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric class COFFMasmParser : public MCAsmParserExtension { 295ffd83dbSDimitry Andric template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)> 305ffd83dbSDimitry Andric void addDirectiveHandler(StringRef Directive) { 315ffd83dbSDimitry Andric MCAsmParser::ExtensionDirectiveHandler Handler = 325ffd83dbSDimitry Andric std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>); 335ffd83dbSDimitry Andric getParser().addDirectiveHandler(Directive, Handler); 345ffd83dbSDimitry Andric } 355ffd83dbSDimitry Andric 365ffd83dbSDimitry Andric bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 375ffd83dbSDimitry Andric SectionKind Kind); 385ffd83dbSDimitry Andric 395ffd83dbSDimitry Andric bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 405ffd83dbSDimitry Andric SectionKind Kind, StringRef COMDATSymName, 415ffd83dbSDimitry Andric COFF::COMDATType Type); 425ffd83dbSDimitry Andric 435ffd83dbSDimitry Andric bool ParseDirectiveProc(StringRef, SMLoc); 445ffd83dbSDimitry Andric bool ParseDirectiveEndProc(StringRef, SMLoc); 455ffd83dbSDimitry Andric bool ParseDirectiveSegment(StringRef, SMLoc); 465ffd83dbSDimitry Andric bool ParseDirectiveSegmentEnd(StringRef, SMLoc); 475ffd83dbSDimitry Andric bool ParseDirectiveIncludelib(StringRef, SMLoc); 485ffd83dbSDimitry Andric 49e8d8bef9SDimitry Andric bool ParseDirectiveAlias(StringRef, SMLoc); 50e8d8bef9SDimitry Andric 51e8d8bef9SDimitry Andric bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); 52e8d8bef9SDimitry Andric bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); 53e8d8bef9SDimitry Andric 545ffd83dbSDimitry Andric bool IgnoreDirective(StringRef, SMLoc) { 555ffd83dbSDimitry Andric while (!getLexer().is(AsmToken::EndOfStatement)) { 565ffd83dbSDimitry Andric Lex(); 575ffd83dbSDimitry Andric } 585ffd83dbSDimitry Andric return false; 595ffd83dbSDimitry Andric } 605ffd83dbSDimitry Andric 615ffd83dbSDimitry Andric void Initialize(MCAsmParser &Parser) override { 625ffd83dbSDimitry Andric // Call the base implementation. 635ffd83dbSDimitry Andric MCAsmParserExtension::Initialize(Parser); 645ffd83dbSDimitry Andric 655ffd83dbSDimitry Andric // x64 directives 66e8d8bef9SDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveAllocStack>( 67e8d8bef9SDimitry Andric ".allocstack"); 68e8d8bef9SDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveEndProlog>( 69e8d8bef9SDimitry Andric ".endprolog"); 705ffd83dbSDimitry Andric 715ffd83dbSDimitry Andric // Code label directives 725ffd83dbSDimitry Andric // label 735ffd83dbSDimitry Andric // org 745ffd83dbSDimitry Andric 755ffd83dbSDimitry Andric // Conditional control flow directives 765ffd83dbSDimitry Andric // .break 775ffd83dbSDimitry Andric // .continue 785ffd83dbSDimitry Andric // .else 795ffd83dbSDimitry Andric // .elseif 805ffd83dbSDimitry Andric // .endif 815ffd83dbSDimitry Andric // .endw 825ffd83dbSDimitry Andric // .if 835ffd83dbSDimitry Andric // .repeat 845ffd83dbSDimitry Andric // .until 855ffd83dbSDimitry Andric // .untilcxz 865ffd83dbSDimitry Andric // .while 875ffd83dbSDimitry Andric 885ffd83dbSDimitry Andric // Data allocation directives 895ffd83dbSDimitry Andric // align 905ffd83dbSDimitry Andric // even 91e8d8bef9SDimitry Andric // mmword 925ffd83dbSDimitry Andric // tbyte 93e8d8bef9SDimitry Andric // xmmword 94e8d8bef9SDimitry Andric // ymmword 955ffd83dbSDimitry Andric 965ffd83dbSDimitry Andric // Listing control directives 975ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref"); 985ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list"); 995ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall"); 1005ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif"); 1015ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro"); 1025ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall"); 1035ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref"); 1045ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist"); 1055ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif"); 1065ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro"); 1075ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page"); 1085ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle"); 1095ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond"); 1105ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title"); 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric // Macro directives 1135ffd83dbSDimitry Andric // goto 1145ffd83dbSDimitry Andric 1155ffd83dbSDimitry Andric // Miscellaneous directives 116e8d8bef9SDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveAlias>("alias"); 1175ffd83dbSDimitry Andric // assume 1185ffd83dbSDimitry Andric // .fpo 1195ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>( 1205ffd83dbSDimitry Andric "includelib"); 1215ffd83dbSDimitry Andric // option 1225ffd83dbSDimitry Andric // popcontext 1235ffd83dbSDimitry Andric // pushcontext 1245ffd83dbSDimitry Andric // .safeseh 1255ffd83dbSDimitry Andric 1265ffd83dbSDimitry Andric // Procedure directives 1275ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp"); 1285ffd83dbSDimitry Andric // invoke (32-bit only) 1295ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc"); 1305ffd83dbSDimitry Andric // proto 1315ffd83dbSDimitry Andric 132e8d8bef9SDimitry Andric // Processor directives; all ignored 1335ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386"); 134fe6060f1SDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386p"); 1355ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387"); 1365ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486"); 137fe6060f1SDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486p"); 1385ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586"); 139fe6060f1SDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586p"); 1405ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686"); 141fe6060f1SDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686p"); 1425ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d"); 1435ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx"); 1445ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm"); 1455ffd83dbSDimitry Andric 1465ffd83dbSDimitry Andric // Scope directives 1475ffd83dbSDimitry Andric // comm 1485ffd83dbSDimitry Andric // externdef 1495ffd83dbSDimitry Andric 1505ffd83dbSDimitry Andric // Segment directives 1515ffd83dbSDimitry Andric // .alpha (32-bit only, order segments alphabetically) 1525ffd83dbSDimitry Andric // .dosseg (32-bit only, order segments in DOS convention) 1535ffd83dbSDimitry Andric // .seq (32-bit only, order segments sequentially) 1545ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends"); 1555ffd83dbSDimitry Andric // group (32-bit only) 1565ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment"); 1575ffd83dbSDimitry Andric 1585ffd83dbSDimitry Andric // Simplified segment directives 1595ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code"); 1605ffd83dbSDimitry Andric // .const 1615ffd83dbSDimitry Andric addDirectiveHandler< 1625ffd83dbSDimitry Andric &COFFMasmParser::ParseSectionDirectiveInitializedData>(".data"); 1635ffd83dbSDimitry Andric addDirectiveHandler< 1645ffd83dbSDimitry Andric &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?"); 1655ffd83dbSDimitry Andric // .exit 1665ffd83dbSDimitry Andric // .fardata 1675ffd83dbSDimitry Andric // .fardata? 1685ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model"); 1695ffd83dbSDimitry Andric // .stack 1705ffd83dbSDimitry Andric // .startup 1715ffd83dbSDimitry Andric 1725ffd83dbSDimitry Andric // String directives, written <name> <directive> <params> 1735ffd83dbSDimitry Andric // catstr (equivalent to <name> TEXTEQU <params>) 1745ffd83dbSDimitry Andric // instr (equivalent to <name> = @InStr(<params>)) 1755ffd83dbSDimitry Andric // sizestr (equivalent to <name> = @SizeStr(<params>)) 1765ffd83dbSDimitry Andric // substr (equivalent to <name> TEXTEQU @SubStr(<params>)) 1775ffd83dbSDimitry Andric 1785ffd83dbSDimitry Andric // Structure and record directives 1795ffd83dbSDimitry Andric // record 1805ffd83dbSDimitry Andric // typedef 1815ffd83dbSDimitry Andric } 1825ffd83dbSDimitry Andric 1835ffd83dbSDimitry Andric bool ParseSectionDirectiveCode(StringRef, SMLoc) { 1845ffd83dbSDimitry Andric return ParseSectionSwitch(".text", 1855ffd83dbSDimitry Andric COFF::IMAGE_SCN_CNT_CODE 1865ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_EXECUTE 1875ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_READ, 1885ffd83dbSDimitry Andric SectionKind::getText()); 1895ffd83dbSDimitry Andric } 1905ffd83dbSDimitry Andric 1915ffd83dbSDimitry Andric bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) { 1925ffd83dbSDimitry Andric return ParseSectionSwitch(".data", 1935ffd83dbSDimitry Andric COFF::IMAGE_SCN_CNT_INITIALIZED_DATA 1945ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_READ 1955ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_WRITE, 1965ffd83dbSDimitry Andric SectionKind::getData()); 1975ffd83dbSDimitry Andric } 1985ffd83dbSDimitry Andric 1995ffd83dbSDimitry Andric bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) { 2005ffd83dbSDimitry Andric return ParseSectionSwitch(".bss", 2015ffd83dbSDimitry Andric COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA 2025ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_READ 2035ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_WRITE, 2045ffd83dbSDimitry Andric SectionKind::getBSS()); 2055ffd83dbSDimitry Andric } 2065ffd83dbSDimitry Andric 2075ffd83dbSDimitry Andric StringRef CurrentProcedure; 208e8d8bef9SDimitry Andric bool CurrentProcedureFramed; 2095ffd83dbSDimitry Andric 2105ffd83dbSDimitry Andric public: 2115ffd83dbSDimitry Andric COFFMasmParser() = default; 2125ffd83dbSDimitry Andric }; 2135ffd83dbSDimitry Andric 2145ffd83dbSDimitry Andric } // end anonymous namespace. 2155ffd83dbSDimitry Andric 2165ffd83dbSDimitry Andric static SectionKind computeSectionKind(unsigned Flags) { 2175ffd83dbSDimitry Andric if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) 2185ffd83dbSDimitry Andric return SectionKind::getText(); 2195ffd83dbSDimitry Andric if (Flags & COFF::IMAGE_SCN_MEM_READ && 2205ffd83dbSDimitry Andric (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) 2215ffd83dbSDimitry Andric return SectionKind::getReadOnly(); 2225ffd83dbSDimitry Andric return SectionKind::getData(); 2235ffd83dbSDimitry Andric } 2245ffd83dbSDimitry Andric 2255ffd83dbSDimitry Andric bool COFFMasmParser::ParseSectionSwitch(StringRef Section, 2265ffd83dbSDimitry Andric unsigned Characteristics, 2275ffd83dbSDimitry Andric SectionKind Kind) { 2285ffd83dbSDimitry Andric return ParseSectionSwitch(Section, Characteristics, Kind, "", 2295ffd83dbSDimitry Andric (COFF::COMDATType)0); 2305ffd83dbSDimitry Andric } 2315ffd83dbSDimitry Andric 2325ffd83dbSDimitry Andric bool COFFMasmParser::ParseSectionSwitch(StringRef Section, 2335ffd83dbSDimitry Andric unsigned Characteristics, 2345ffd83dbSDimitry Andric SectionKind Kind, 2355ffd83dbSDimitry Andric StringRef COMDATSymName, 2365ffd83dbSDimitry Andric COFF::COMDATType Type) { 2375ffd83dbSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 2385ffd83dbSDimitry Andric return TokError("unexpected token in section switching directive"); 2395ffd83dbSDimitry Andric Lex(); 2405ffd83dbSDimitry Andric 241*81ad6265SDimitry Andric getStreamer().switchSection(getContext().getCOFFSection( 2425ffd83dbSDimitry Andric Section, Characteristics, Kind, COMDATSymName, Type)); 2435ffd83dbSDimitry Andric 2445ffd83dbSDimitry Andric return false; 2455ffd83dbSDimitry Andric } 2465ffd83dbSDimitry Andric 2475ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) { 2485ffd83dbSDimitry Andric StringRef SegmentName; 2495ffd83dbSDimitry Andric if (!getLexer().is(AsmToken::Identifier)) 2505ffd83dbSDimitry Andric return TokError("expected identifier in directive"); 2515ffd83dbSDimitry Andric SegmentName = getTok().getIdentifier(); 2525ffd83dbSDimitry Andric Lex(); 2535ffd83dbSDimitry Andric 2545ffd83dbSDimitry Andric StringRef SectionName = SegmentName; 2555ffd83dbSDimitry Andric SmallVector<char, 247> SectionNameVector; 2565ffd83dbSDimitry Andric unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 2575ffd83dbSDimitry Andric COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; 2585ffd83dbSDimitry Andric if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) { 2595ffd83dbSDimitry Andric if (SegmentName.size() == 5) { 2605ffd83dbSDimitry Andric SectionName = ".text"; 2615ffd83dbSDimitry Andric } else { 2625ffd83dbSDimitry Andric SectionName = 2635ffd83dbSDimitry Andric (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector); 2645ffd83dbSDimitry Andric } 2655ffd83dbSDimitry Andric Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE | 2665ffd83dbSDimitry Andric COFF::IMAGE_SCN_MEM_READ; 2675ffd83dbSDimitry Andric } 2685ffd83dbSDimitry Andric SectionKind Kind = computeSectionKind(Flags); 269*81ad6265SDimitry Andric getStreamer().switchSection(getContext().getCOFFSection( 2705ffd83dbSDimitry Andric SectionName, Flags, Kind, "", (COFF::COMDATType)(0))); 2715ffd83dbSDimitry Andric return false; 2725ffd83dbSDimitry Andric } 2735ffd83dbSDimitry Andric 2745ffd83dbSDimitry Andric /// ParseDirectiveSegmentEnd 2755ffd83dbSDimitry Andric /// ::= identifier "ends" 2765ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) { 2775ffd83dbSDimitry Andric StringRef SegmentName; 2785ffd83dbSDimitry Andric if (!getLexer().is(AsmToken::Identifier)) 2795ffd83dbSDimitry Andric return TokError("expected identifier in directive"); 2805ffd83dbSDimitry Andric SegmentName = getTok().getIdentifier(); 2815ffd83dbSDimitry Andric 2825ffd83dbSDimitry Andric // Ignore; no action necessary. 2835ffd83dbSDimitry Andric Lex(); 2845ffd83dbSDimitry Andric return false; 2855ffd83dbSDimitry Andric } 2865ffd83dbSDimitry Andric 2875ffd83dbSDimitry Andric /// ParseDirectiveIncludelib 2885ffd83dbSDimitry Andric /// ::= "includelib" identifier 2895ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) { 2905ffd83dbSDimitry Andric StringRef Lib; 2915ffd83dbSDimitry Andric if (getParser().parseIdentifier(Lib)) 2925ffd83dbSDimitry Andric return TokError("expected identifier in includelib directive"); 2935ffd83dbSDimitry Andric 2945ffd83dbSDimitry Andric unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT; 2955ffd83dbSDimitry Andric SectionKind Kind = computeSectionKind(Flags); 296*81ad6265SDimitry Andric getStreamer().pushSection(); 297*81ad6265SDimitry Andric getStreamer().switchSection(getContext().getCOFFSection( 2985ffd83dbSDimitry Andric ".drectve", Flags, Kind, "", (COFF::COMDATType)(0))); 2995ffd83dbSDimitry Andric getStreamer().emitBytes("/DEFAULTLIB:"); 3005ffd83dbSDimitry Andric getStreamer().emitBytes(Lib); 3015ffd83dbSDimitry Andric getStreamer().emitBytes(" "); 302*81ad6265SDimitry Andric getStreamer().popSection(); 3035ffd83dbSDimitry Andric return false; 3045ffd83dbSDimitry Andric } 3055ffd83dbSDimitry Andric 3065ffd83dbSDimitry Andric /// ParseDirectiveProc 3075ffd83dbSDimitry Andric /// TODO(epastor): Implement parameters and other attributes. 3085ffd83dbSDimitry Andric /// ::= label "proc" [[distance]] 3095ffd83dbSDimitry Andric /// statements 3105ffd83dbSDimitry Andric /// label "endproc" 3115ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) { 3125ffd83dbSDimitry Andric StringRef Label; 3135ffd83dbSDimitry Andric if (getParser().parseIdentifier(Label)) 3145ffd83dbSDimitry Andric return Error(Loc, "expected identifier for procedure"); 3155ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Identifier)) { 3165ffd83dbSDimitry Andric StringRef nextVal = getTok().getString(); 3175ffd83dbSDimitry Andric SMLoc nextLoc = getTok().getLoc(); 318fe6060f1SDimitry Andric if (nextVal.equals_insensitive("far")) { 3195ffd83dbSDimitry Andric // TODO(epastor): Handle far procedure definitions. 3205ffd83dbSDimitry Andric Lex(); 3215ffd83dbSDimitry Andric return Error(nextLoc, "far procedure definitions not yet supported"); 322fe6060f1SDimitry Andric } else if (nextVal.equals_insensitive("near")) { 3235ffd83dbSDimitry Andric Lex(); 3245ffd83dbSDimitry Andric nextVal = getTok().getString(); 3255ffd83dbSDimitry Andric nextLoc = getTok().getLoc(); 3265ffd83dbSDimitry Andric } 3275ffd83dbSDimitry Andric } 328e8d8bef9SDimitry Andric MCSymbolCOFF *Sym = cast<MCSymbolCOFF>(getContext().getOrCreateSymbol(Label)); 3295ffd83dbSDimitry Andric 330e8d8bef9SDimitry Andric // Define symbol as simple external function 331e8d8bef9SDimitry Andric Sym->setExternal(true); 332e8d8bef9SDimitry Andric Sym->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT); 3335ffd83dbSDimitry Andric 334e8d8bef9SDimitry Andric bool Framed = false; 335e8d8bef9SDimitry Andric if (getLexer().is(AsmToken::Identifier) && 336fe6060f1SDimitry Andric getTok().getString().equals_insensitive("frame")) { 337e8d8bef9SDimitry Andric Lex(); 338e8d8bef9SDimitry Andric Framed = true; 339*81ad6265SDimitry Andric getStreamer().emitWinCFIStartProc(Sym, Loc); 340e8d8bef9SDimitry Andric } 3415ffd83dbSDimitry Andric getStreamer().emitLabel(Sym, Loc); 342e8d8bef9SDimitry Andric 3435ffd83dbSDimitry Andric CurrentProcedure = Label; 344e8d8bef9SDimitry Andric CurrentProcedureFramed = Framed; 3455ffd83dbSDimitry Andric return false; 3465ffd83dbSDimitry Andric } 3475ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) { 3485ffd83dbSDimitry Andric StringRef Label; 3495ffd83dbSDimitry Andric SMLoc LabelLoc = getTok().getLoc(); 3505ffd83dbSDimitry Andric if (getParser().parseIdentifier(Label)) 3515ffd83dbSDimitry Andric return Error(LabelLoc, "expected identifier for procedure end"); 3525ffd83dbSDimitry Andric 3535ffd83dbSDimitry Andric if (CurrentProcedure.empty()) 3545ffd83dbSDimitry Andric return Error(Loc, "endp outside of procedure block"); 3555ffd83dbSDimitry Andric else if (CurrentProcedure != Label) 3565ffd83dbSDimitry Andric return Error(LabelLoc, "endp does not match current procedure '" + 3575ffd83dbSDimitry Andric CurrentProcedure + "'"); 358e8d8bef9SDimitry Andric 359e8d8bef9SDimitry Andric if (CurrentProcedureFramed) { 360*81ad6265SDimitry Andric getStreamer().emitWinCFIEndProc(Loc); 361e8d8bef9SDimitry Andric } 362e8d8bef9SDimitry Andric CurrentProcedure = ""; 363e8d8bef9SDimitry Andric CurrentProcedureFramed = false; 364e8d8bef9SDimitry Andric return false; 365e8d8bef9SDimitry Andric } 366e8d8bef9SDimitry Andric 367e8d8bef9SDimitry Andric bool COFFMasmParser::ParseDirectiveAlias(StringRef Directive, SMLoc Loc) { 368e8d8bef9SDimitry Andric std::string AliasName, ActualName; 369e8d8bef9SDimitry Andric if (getTok().isNot(AsmToken::Less) || 370e8d8bef9SDimitry Andric getParser().parseAngleBracketString(AliasName)) 371e8d8bef9SDimitry Andric return Error(getTok().getLoc(), "expected <aliasName>"); 372e8d8bef9SDimitry Andric if (getParser().parseToken(AsmToken::Equal)) 373e8d8bef9SDimitry Andric return addErrorSuffix(" in " + Directive + " directive"); 374e8d8bef9SDimitry Andric if (getTok().isNot(AsmToken::Less) || 375e8d8bef9SDimitry Andric getParser().parseAngleBracketString(ActualName)) 376e8d8bef9SDimitry Andric return Error(getTok().getLoc(), "expected <actualName>"); 377e8d8bef9SDimitry Andric 378e8d8bef9SDimitry Andric MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); 379e8d8bef9SDimitry Andric MCSymbol *Actual = getContext().getOrCreateSymbol(ActualName); 380e8d8bef9SDimitry Andric 381e8d8bef9SDimitry Andric getStreamer().emitWeakReference(Alias, Actual); 382e8d8bef9SDimitry Andric 383e8d8bef9SDimitry Andric return false; 384e8d8bef9SDimitry Andric } 385e8d8bef9SDimitry Andric 386e8d8bef9SDimitry Andric bool COFFMasmParser::ParseSEHDirectiveAllocStack(StringRef Directive, 387e8d8bef9SDimitry Andric SMLoc Loc) { 388e8d8bef9SDimitry Andric int64_t Size; 389e8d8bef9SDimitry Andric SMLoc SizeLoc = getTok().getLoc(); 390e8d8bef9SDimitry Andric if (getParser().parseAbsoluteExpression(Size)) 391e8d8bef9SDimitry Andric return Error(SizeLoc, "expected integer size"); 392e8d8bef9SDimitry Andric if (Size % 8 != 0) 393e8d8bef9SDimitry Andric return Error(SizeLoc, "stack size must be a multiple of 8"); 394*81ad6265SDimitry Andric getStreamer().emitWinCFIAllocStack(static_cast<unsigned>(Size), Loc); 395e8d8bef9SDimitry Andric return false; 396e8d8bef9SDimitry Andric } 397e8d8bef9SDimitry Andric 398e8d8bef9SDimitry Andric bool COFFMasmParser::ParseSEHDirectiveEndProlog(StringRef Directive, 399e8d8bef9SDimitry Andric SMLoc Loc) { 400*81ad6265SDimitry Andric getStreamer().emitWinCFIEndProlog(Loc); 4015ffd83dbSDimitry Andric return false; 4025ffd83dbSDimitry Andric } 4035ffd83dbSDimitry Andric 4045ffd83dbSDimitry Andric namespace llvm { 4055ffd83dbSDimitry Andric 4065ffd83dbSDimitry Andric MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; } 4075ffd83dbSDimitry Andric 4085ffd83dbSDimitry Andric } // end namespace llvm 409