xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCParser/COFFMasmParser.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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