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