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/Triple.h" 115ffd83dbSDimitry Andric #include "llvm/ADT/Twine.h" 125ffd83dbSDimitry Andric #include "llvm/BinaryFormat/COFF.h" 135ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 145ffd83dbSDimitry Andric #include "llvm/MC/MCDirectives.h" 155ffd83dbSDimitry Andric #include "llvm/MC/MCObjectFileInfo.h" 165ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 175ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h" 185ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserUtils.h" 195ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h" 205ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 215ffd83dbSDimitry Andric #include "llvm/MC/MCSectionCOFF.h" 225ffd83dbSDimitry Andric #include "llvm/MC/MCStreamer.h" 23*e8d8bef9SDimitry Andric #include "llvm/MC/MCSymbolCOFF.h" 245ffd83dbSDimitry Andric #include "llvm/MC/SectionKind.h" 255ffd83dbSDimitry Andric #include "llvm/Support/SMLoc.h" 265ffd83dbSDimitry Andric #include <cassert> 275ffd83dbSDimitry Andric #include <cstdint> 285ffd83dbSDimitry Andric #include <limits> 295ffd83dbSDimitry Andric #include <utility> 305ffd83dbSDimitry Andric 315ffd83dbSDimitry Andric using namespace llvm; 325ffd83dbSDimitry Andric 335ffd83dbSDimitry Andric namespace { 345ffd83dbSDimitry Andric 355ffd83dbSDimitry Andric class COFFMasmParser : public MCAsmParserExtension { 365ffd83dbSDimitry Andric template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)> 375ffd83dbSDimitry Andric void addDirectiveHandler(StringRef Directive) { 385ffd83dbSDimitry Andric MCAsmParser::ExtensionDirectiveHandler Handler = 395ffd83dbSDimitry Andric std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>); 405ffd83dbSDimitry Andric getParser().addDirectiveHandler(Directive, Handler); 415ffd83dbSDimitry Andric } 425ffd83dbSDimitry Andric 435ffd83dbSDimitry Andric bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 445ffd83dbSDimitry Andric SectionKind Kind); 455ffd83dbSDimitry Andric 465ffd83dbSDimitry Andric bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 475ffd83dbSDimitry Andric SectionKind Kind, StringRef COMDATSymName, 485ffd83dbSDimitry Andric COFF::COMDATType Type); 495ffd83dbSDimitry Andric 505ffd83dbSDimitry Andric bool ParseDirectiveProc(StringRef, SMLoc); 515ffd83dbSDimitry Andric bool ParseDirectiveEndProc(StringRef, SMLoc); 525ffd83dbSDimitry Andric bool ParseDirectiveSegment(StringRef, SMLoc); 535ffd83dbSDimitry Andric bool ParseDirectiveSegmentEnd(StringRef, SMLoc); 545ffd83dbSDimitry Andric bool ParseDirectiveIncludelib(StringRef, SMLoc); 555ffd83dbSDimitry Andric 56*e8d8bef9SDimitry Andric bool ParseDirectiveAlias(StringRef, SMLoc); 57*e8d8bef9SDimitry Andric 58*e8d8bef9SDimitry Andric bool ParseSEHDirectiveAllocStack(StringRef, SMLoc); 59*e8d8bef9SDimitry Andric bool ParseSEHDirectiveEndProlog(StringRef, SMLoc); 60*e8d8bef9SDimitry Andric 615ffd83dbSDimitry Andric bool IgnoreDirective(StringRef, SMLoc) { 625ffd83dbSDimitry Andric while (!getLexer().is(AsmToken::EndOfStatement)) { 635ffd83dbSDimitry Andric Lex(); 645ffd83dbSDimitry Andric } 655ffd83dbSDimitry Andric return false; 665ffd83dbSDimitry Andric } 675ffd83dbSDimitry Andric 685ffd83dbSDimitry Andric void Initialize(MCAsmParser &Parser) override { 695ffd83dbSDimitry Andric // Call the base implementation. 705ffd83dbSDimitry Andric MCAsmParserExtension::Initialize(Parser); 715ffd83dbSDimitry Andric 725ffd83dbSDimitry Andric // x64 directives 73*e8d8bef9SDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveAllocStack>( 74*e8d8bef9SDimitry Andric ".allocstack"); 75*e8d8bef9SDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveEndProlog>( 76*e8d8bef9SDimitry Andric ".endprolog"); 775ffd83dbSDimitry Andric 785ffd83dbSDimitry Andric // Code label directives 795ffd83dbSDimitry Andric // label 805ffd83dbSDimitry Andric // org 815ffd83dbSDimitry Andric 825ffd83dbSDimitry Andric // Conditional control flow directives 835ffd83dbSDimitry Andric // .break 845ffd83dbSDimitry Andric // .continue 855ffd83dbSDimitry Andric // .else 865ffd83dbSDimitry Andric // .elseif 875ffd83dbSDimitry Andric // .endif 885ffd83dbSDimitry Andric // .endw 895ffd83dbSDimitry Andric // .if 905ffd83dbSDimitry Andric // .repeat 915ffd83dbSDimitry Andric // .until 925ffd83dbSDimitry Andric // .untilcxz 935ffd83dbSDimitry Andric // .while 945ffd83dbSDimitry Andric 955ffd83dbSDimitry Andric // Data allocation directives 965ffd83dbSDimitry Andric // align 975ffd83dbSDimitry Andric // even 98*e8d8bef9SDimitry Andric // mmword 995ffd83dbSDimitry Andric // tbyte 100*e8d8bef9SDimitry Andric // xmmword 101*e8d8bef9SDimitry Andric // ymmword 1025ffd83dbSDimitry Andric 1035ffd83dbSDimitry Andric // Listing control directives 1045ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref"); 1055ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list"); 1065ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall"); 1075ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif"); 1085ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro"); 1095ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall"); 1105ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref"); 1115ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist"); 1125ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif"); 1135ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro"); 1145ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page"); 1155ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle"); 1165ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond"); 1175ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title"); 1185ffd83dbSDimitry Andric 1195ffd83dbSDimitry Andric // Macro directives 1205ffd83dbSDimitry Andric // goto 1215ffd83dbSDimitry Andric 1225ffd83dbSDimitry Andric // Miscellaneous directives 123*e8d8bef9SDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveAlias>("alias"); 1245ffd83dbSDimitry Andric // assume 1255ffd83dbSDimitry Andric // .fpo 1265ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>( 1275ffd83dbSDimitry Andric "includelib"); 1285ffd83dbSDimitry Andric // option 1295ffd83dbSDimitry Andric // popcontext 1305ffd83dbSDimitry Andric // pushcontext 1315ffd83dbSDimitry Andric // .safeseh 1325ffd83dbSDimitry Andric 1335ffd83dbSDimitry Andric // Procedure directives 1345ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp"); 1355ffd83dbSDimitry Andric // invoke (32-bit only) 1365ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc"); 1375ffd83dbSDimitry Andric // proto 1385ffd83dbSDimitry Andric 139*e8d8bef9SDimitry Andric // Processor directives; all ignored 1405ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386"); 1415ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P"); 1425ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387"); 1435ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486"); 1445ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486P"); 1455ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586"); 1465ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586P"); 1475ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686"); 1485ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686P"); 1495ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d"); 1505ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx"); 1515ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm"); 1525ffd83dbSDimitry Andric 1535ffd83dbSDimitry Andric // Scope directives 1545ffd83dbSDimitry Andric // comm 1555ffd83dbSDimitry Andric // externdef 1565ffd83dbSDimitry Andric 1575ffd83dbSDimitry Andric // Segment directives 1585ffd83dbSDimitry Andric // .alpha (32-bit only, order segments alphabetically) 1595ffd83dbSDimitry Andric // .dosseg (32-bit only, order segments in DOS convention) 1605ffd83dbSDimitry Andric // .seq (32-bit only, order segments sequentially) 1615ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends"); 1625ffd83dbSDimitry Andric // group (32-bit only) 1635ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment"); 1645ffd83dbSDimitry Andric 1655ffd83dbSDimitry Andric // Simplified segment directives 1665ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code"); 1675ffd83dbSDimitry Andric // .const 1685ffd83dbSDimitry Andric addDirectiveHandler< 1695ffd83dbSDimitry Andric &COFFMasmParser::ParseSectionDirectiveInitializedData>(".data"); 1705ffd83dbSDimitry Andric addDirectiveHandler< 1715ffd83dbSDimitry Andric &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?"); 1725ffd83dbSDimitry Andric // .exit 1735ffd83dbSDimitry Andric // .fardata 1745ffd83dbSDimitry Andric // .fardata? 1755ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model"); 1765ffd83dbSDimitry Andric // .stack 1775ffd83dbSDimitry Andric // .startup 1785ffd83dbSDimitry Andric 1795ffd83dbSDimitry Andric // String directives, written <name> <directive> <params> 1805ffd83dbSDimitry Andric // catstr (equivalent to <name> TEXTEQU <params>) 1815ffd83dbSDimitry Andric // instr (equivalent to <name> = @InStr(<params>)) 1825ffd83dbSDimitry Andric // sizestr (equivalent to <name> = @SizeStr(<params>)) 1835ffd83dbSDimitry Andric // substr (equivalent to <name> TEXTEQU @SubStr(<params>)) 1845ffd83dbSDimitry Andric 1855ffd83dbSDimitry Andric // Structure and record directives 1865ffd83dbSDimitry Andric // record 1875ffd83dbSDimitry Andric // typedef 1885ffd83dbSDimitry Andric } 1895ffd83dbSDimitry Andric 1905ffd83dbSDimitry Andric bool ParseSectionDirectiveCode(StringRef, SMLoc) { 1915ffd83dbSDimitry Andric return ParseSectionSwitch(".text", 1925ffd83dbSDimitry Andric COFF::IMAGE_SCN_CNT_CODE 1935ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_EXECUTE 1945ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_READ, 1955ffd83dbSDimitry Andric SectionKind::getText()); 1965ffd83dbSDimitry Andric } 1975ffd83dbSDimitry Andric 1985ffd83dbSDimitry Andric bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) { 1995ffd83dbSDimitry Andric return ParseSectionSwitch(".data", 2005ffd83dbSDimitry Andric COFF::IMAGE_SCN_CNT_INITIALIZED_DATA 2015ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_READ 2025ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_WRITE, 2035ffd83dbSDimitry Andric SectionKind::getData()); 2045ffd83dbSDimitry Andric } 2055ffd83dbSDimitry Andric 2065ffd83dbSDimitry Andric bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) { 2075ffd83dbSDimitry Andric return ParseSectionSwitch(".bss", 2085ffd83dbSDimitry Andric COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA 2095ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_READ 2105ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_WRITE, 2115ffd83dbSDimitry Andric SectionKind::getBSS()); 2125ffd83dbSDimitry Andric } 2135ffd83dbSDimitry Andric 2145ffd83dbSDimitry Andric StringRef CurrentProcedure; 215*e8d8bef9SDimitry Andric bool CurrentProcedureFramed; 2165ffd83dbSDimitry Andric 2175ffd83dbSDimitry Andric public: 2185ffd83dbSDimitry Andric COFFMasmParser() = default; 2195ffd83dbSDimitry Andric }; 2205ffd83dbSDimitry Andric 2215ffd83dbSDimitry Andric } // end anonymous namespace. 2225ffd83dbSDimitry Andric 2235ffd83dbSDimitry Andric static SectionKind computeSectionKind(unsigned Flags) { 2245ffd83dbSDimitry Andric if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) 2255ffd83dbSDimitry Andric return SectionKind::getText(); 2265ffd83dbSDimitry Andric if (Flags & COFF::IMAGE_SCN_MEM_READ && 2275ffd83dbSDimitry Andric (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) 2285ffd83dbSDimitry Andric return SectionKind::getReadOnly(); 2295ffd83dbSDimitry Andric return SectionKind::getData(); 2305ffd83dbSDimitry Andric } 2315ffd83dbSDimitry Andric 2325ffd83dbSDimitry Andric bool COFFMasmParser::ParseSectionSwitch(StringRef Section, 2335ffd83dbSDimitry Andric unsigned Characteristics, 2345ffd83dbSDimitry Andric SectionKind Kind) { 2355ffd83dbSDimitry Andric return ParseSectionSwitch(Section, Characteristics, Kind, "", 2365ffd83dbSDimitry Andric (COFF::COMDATType)0); 2375ffd83dbSDimitry Andric } 2385ffd83dbSDimitry Andric 2395ffd83dbSDimitry Andric bool COFFMasmParser::ParseSectionSwitch(StringRef Section, 2405ffd83dbSDimitry Andric unsigned Characteristics, 2415ffd83dbSDimitry Andric SectionKind Kind, 2425ffd83dbSDimitry Andric StringRef COMDATSymName, 2435ffd83dbSDimitry Andric COFF::COMDATType Type) { 2445ffd83dbSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 2455ffd83dbSDimitry Andric return TokError("unexpected token in section switching directive"); 2465ffd83dbSDimitry Andric Lex(); 2475ffd83dbSDimitry Andric 2485ffd83dbSDimitry Andric getStreamer().SwitchSection(getContext().getCOFFSection( 2495ffd83dbSDimitry Andric Section, Characteristics, Kind, COMDATSymName, Type)); 2505ffd83dbSDimitry Andric 2515ffd83dbSDimitry Andric return false; 2525ffd83dbSDimitry Andric } 2535ffd83dbSDimitry Andric 2545ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) { 2555ffd83dbSDimitry Andric StringRef SegmentName; 2565ffd83dbSDimitry Andric if (!getLexer().is(AsmToken::Identifier)) 2575ffd83dbSDimitry Andric return TokError("expected identifier in directive"); 2585ffd83dbSDimitry Andric SegmentName = getTok().getIdentifier(); 2595ffd83dbSDimitry Andric Lex(); 2605ffd83dbSDimitry Andric 2615ffd83dbSDimitry Andric StringRef SectionName = SegmentName; 2625ffd83dbSDimitry Andric SmallVector<char, 247> SectionNameVector; 2635ffd83dbSDimitry Andric unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 2645ffd83dbSDimitry Andric COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; 2655ffd83dbSDimitry Andric if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) { 2665ffd83dbSDimitry Andric if (SegmentName.size() == 5) { 2675ffd83dbSDimitry Andric SectionName = ".text"; 2685ffd83dbSDimitry Andric } else { 2695ffd83dbSDimitry Andric SectionName = 2705ffd83dbSDimitry Andric (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector); 2715ffd83dbSDimitry Andric } 2725ffd83dbSDimitry Andric Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE | 2735ffd83dbSDimitry Andric COFF::IMAGE_SCN_MEM_READ; 2745ffd83dbSDimitry Andric } 2755ffd83dbSDimitry Andric SectionKind Kind = computeSectionKind(Flags); 2765ffd83dbSDimitry Andric getStreamer().SwitchSection(getContext().getCOFFSection( 2775ffd83dbSDimitry Andric SectionName, Flags, Kind, "", (COFF::COMDATType)(0))); 2785ffd83dbSDimitry Andric return false; 2795ffd83dbSDimitry Andric } 2805ffd83dbSDimitry Andric 2815ffd83dbSDimitry Andric /// ParseDirectiveSegmentEnd 2825ffd83dbSDimitry Andric /// ::= identifier "ends" 2835ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) { 2845ffd83dbSDimitry Andric StringRef SegmentName; 2855ffd83dbSDimitry Andric if (!getLexer().is(AsmToken::Identifier)) 2865ffd83dbSDimitry Andric return TokError("expected identifier in directive"); 2875ffd83dbSDimitry Andric SegmentName = getTok().getIdentifier(); 2885ffd83dbSDimitry Andric 2895ffd83dbSDimitry Andric // Ignore; no action necessary. 2905ffd83dbSDimitry Andric Lex(); 2915ffd83dbSDimitry Andric return false; 2925ffd83dbSDimitry Andric } 2935ffd83dbSDimitry Andric 2945ffd83dbSDimitry Andric /// ParseDirectiveIncludelib 2955ffd83dbSDimitry Andric /// ::= "includelib" identifier 2965ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) { 2975ffd83dbSDimitry Andric StringRef Lib; 2985ffd83dbSDimitry Andric if (getParser().parseIdentifier(Lib)) 2995ffd83dbSDimitry Andric return TokError("expected identifier in includelib directive"); 3005ffd83dbSDimitry Andric 3015ffd83dbSDimitry Andric unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT; 3025ffd83dbSDimitry Andric SectionKind Kind = computeSectionKind(Flags); 3035ffd83dbSDimitry Andric getStreamer().PushSection(); 3045ffd83dbSDimitry Andric getStreamer().SwitchSection(getContext().getCOFFSection( 3055ffd83dbSDimitry Andric ".drectve", Flags, Kind, "", (COFF::COMDATType)(0))); 3065ffd83dbSDimitry Andric getStreamer().emitBytes("/DEFAULTLIB:"); 3075ffd83dbSDimitry Andric getStreamer().emitBytes(Lib); 3085ffd83dbSDimitry Andric getStreamer().emitBytes(" "); 3095ffd83dbSDimitry Andric getStreamer().PopSection(); 3105ffd83dbSDimitry Andric return false; 3115ffd83dbSDimitry Andric } 3125ffd83dbSDimitry Andric 3135ffd83dbSDimitry Andric /// ParseDirectiveProc 3145ffd83dbSDimitry Andric /// TODO(epastor): Implement parameters and other attributes. 3155ffd83dbSDimitry Andric /// ::= label "proc" [[distance]] 3165ffd83dbSDimitry Andric /// statements 3175ffd83dbSDimitry Andric /// label "endproc" 3185ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) { 3195ffd83dbSDimitry Andric StringRef Label; 3205ffd83dbSDimitry Andric if (getParser().parseIdentifier(Label)) 3215ffd83dbSDimitry Andric return Error(Loc, "expected identifier for procedure"); 3225ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Identifier)) { 3235ffd83dbSDimitry Andric StringRef nextVal = getTok().getString(); 3245ffd83dbSDimitry Andric SMLoc nextLoc = getTok().getLoc(); 3255ffd83dbSDimitry Andric if (nextVal.equals_lower("far")) { 3265ffd83dbSDimitry Andric // TODO(epastor): Handle far procedure definitions. 3275ffd83dbSDimitry Andric Lex(); 3285ffd83dbSDimitry Andric return Error(nextLoc, "far procedure definitions not yet supported"); 3295ffd83dbSDimitry Andric } else if (nextVal.equals_lower("near")) { 3305ffd83dbSDimitry Andric Lex(); 3315ffd83dbSDimitry Andric nextVal = getTok().getString(); 3325ffd83dbSDimitry Andric nextLoc = getTok().getLoc(); 3335ffd83dbSDimitry Andric } 3345ffd83dbSDimitry Andric } 335*e8d8bef9SDimitry Andric MCSymbolCOFF *Sym = cast<MCSymbolCOFF>(getContext().getOrCreateSymbol(Label)); 3365ffd83dbSDimitry Andric 337*e8d8bef9SDimitry Andric // Define symbol as simple external function 338*e8d8bef9SDimitry Andric Sym->setExternal(true); 339*e8d8bef9SDimitry Andric Sym->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT); 3405ffd83dbSDimitry Andric 341*e8d8bef9SDimitry Andric bool Framed = false; 342*e8d8bef9SDimitry Andric if (getLexer().is(AsmToken::Identifier) && 343*e8d8bef9SDimitry Andric getTok().getString().equals_lower("frame")) { 344*e8d8bef9SDimitry Andric Lex(); 345*e8d8bef9SDimitry Andric Framed = true; 346*e8d8bef9SDimitry Andric getStreamer().EmitWinCFIStartProc(Sym, Loc); 347*e8d8bef9SDimitry Andric } 3485ffd83dbSDimitry Andric getStreamer().emitLabel(Sym, Loc); 349*e8d8bef9SDimitry Andric 3505ffd83dbSDimitry Andric CurrentProcedure = Label; 351*e8d8bef9SDimitry Andric CurrentProcedureFramed = Framed; 3525ffd83dbSDimitry Andric return false; 3535ffd83dbSDimitry Andric } 3545ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) { 3555ffd83dbSDimitry Andric StringRef Label; 3565ffd83dbSDimitry Andric SMLoc LabelLoc = getTok().getLoc(); 3575ffd83dbSDimitry Andric if (getParser().parseIdentifier(Label)) 3585ffd83dbSDimitry Andric return Error(LabelLoc, "expected identifier for procedure end"); 3595ffd83dbSDimitry Andric 3605ffd83dbSDimitry Andric if (CurrentProcedure.empty()) 3615ffd83dbSDimitry Andric return Error(Loc, "endp outside of procedure block"); 3625ffd83dbSDimitry Andric else if (CurrentProcedure != Label) 3635ffd83dbSDimitry Andric return Error(LabelLoc, "endp does not match current procedure '" + 3645ffd83dbSDimitry Andric CurrentProcedure + "'"); 365*e8d8bef9SDimitry Andric 366*e8d8bef9SDimitry Andric if (CurrentProcedureFramed) { 367*e8d8bef9SDimitry Andric getStreamer().EmitWinCFIEndProc(Loc); 368*e8d8bef9SDimitry Andric } 369*e8d8bef9SDimitry Andric CurrentProcedure = ""; 370*e8d8bef9SDimitry Andric CurrentProcedureFramed = false; 371*e8d8bef9SDimitry Andric return false; 372*e8d8bef9SDimitry Andric } 373*e8d8bef9SDimitry Andric 374*e8d8bef9SDimitry Andric bool COFFMasmParser::ParseDirectiveAlias(StringRef Directive, SMLoc Loc) { 375*e8d8bef9SDimitry Andric std::string AliasName, ActualName; 376*e8d8bef9SDimitry Andric if (getTok().isNot(AsmToken::Less) || 377*e8d8bef9SDimitry Andric getParser().parseAngleBracketString(AliasName)) 378*e8d8bef9SDimitry Andric return Error(getTok().getLoc(), "expected <aliasName>"); 379*e8d8bef9SDimitry Andric if (getParser().parseToken(AsmToken::Equal)) 380*e8d8bef9SDimitry Andric return addErrorSuffix(" in " + Directive + " directive"); 381*e8d8bef9SDimitry Andric if (getTok().isNot(AsmToken::Less) || 382*e8d8bef9SDimitry Andric getParser().parseAngleBracketString(ActualName)) 383*e8d8bef9SDimitry Andric return Error(getTok().getLoc(), "expected <actualName>"); 384*e8d8bef9SDimitry Andric 385*e8d8bef9SDimitry Andric MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); 386*e8d8bef9SDimitry Andric MCSymbol *Actual = getContext().getOrCreateSymbol(ActualName); 387*e8d8bef9SDimitry Andric 388*e8d8bef9SDimitry Andric getStreamer().emitWeakReference(Alias, Actual); 389*e8d8bef9SDimitry Andric 390*e8d8bef9SDimitry Andric return false; 391*e8d8bef9SDimitry Andric } 392*e8d8bef9SDimitry Andric 393*e8d8bef9SDimitry Andric bool COFFMasmParser::ParseSEHDirectiveAllocStack(StringRef Directive, 394*e8d8bef9SDimitry Andric SMLoc Loc) { 395*e8d8bef9SDimitry Andric int64_t Size; 396*e8d8bef9SDimitry Andric SMLoc SizeLoc = getTok().getLoc(); 397*e8d8bef9SDimitry Andric if (getParser().parseAbsoluteExpression(Size)) 398*e8d8bef9SDimitry Andric return Error(SizeLoc, "expected integer size"); 399*e8d8bef9SDimitry Andric if (Size % 8 != 0) 400*e8d8bef9SDimitry Andric return Error(SizeLoc, "stack size must be a multiple of 8"); 401*e8d8bef9SDimitry Andric getStreamer().EmitWinCFIAllocStack(static_cast<unsigned>(Size), Loc); 402*e8d8bef9SDimitry Andric return false; 403*e8d8bef9SDimitry Andric } 404*e8d8bef9SDimitry Andric 405*e8d8bef9SDimitry Andric bool COFFMasmParser::ParseSEHDirectiveEndProlog(StringRef Directive, 406*e8d8bef9SDimitry Andric SMLoc Loc) { 407*e8d8bef9SDimitry Andric getStreamer().EmitWinCFIEndProlog(Loc); 4085ffd83dbSDimitry Andric return false; 4095ffd83dbSDimitry Andric } 4105ffd83dbSDimitry Andric 4115ffd83dbSDimitry Andric namespace llvm { 4125ffd83dbSDimitry Andric 4135ffd83dbSDimitry Andric MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; } 4145ffd83dbSDimitry Andric 4155ffd83dbSDimitry Andric } // end namespace llvm 416