1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[ms] [llvm-ml] Add a draft MASM parser

Summary:
Many directives are unavailable, and support for others may be limited.

This first draft has preliminary support for:
    - conditional directives (including errors),
    - data allocation (unsigned types up to 8 bytes, and ALIGN),
    - equates/variables (numeric and text),
    - and procedure directives (without parameters),
as well as COMMENT, ECHO, INCLUDE, INCLUDELIB, PUBLIC, and EXTERN. Text variables (aka text macros) are expanded in-place wherever the identifier occurs.

We deliberately ignore all ml.exe processor directives.

Prominent features not yet supported:
    - structs
    - macros (both procedures and functions)
    - procedures (with specified parameters)
    - substitution & expansion operators

Conditional directives are complicated by the fact that "ifdef rax" is a valid way to check if a file is being assembled for a 64-bit x86 processor; we add support for "ifdef <register>" in general, which requires adding a tryParseRegister method to all MCTargetAsmParsers. (Some targets require backtracking in the non-register case.)

Reviewers: rnk, thakis

Reviewed By: thakis

Subscribers: kerbowa, merge_guards_bot, wuzish, arsenm, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, mgorny, sbc100, jgravelle-google, hiraditya, aheejin, kbarton, fedor.sergeev, asb, rbar, johnrusso, simoncook, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, jsji, Jim, s.egerton, pzheng, sameer.abuasal, apazos, luismarques, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D72680
This commit is contained in:
Eric Astor 2020-02-16 12:29:51 -05:00
parent 8b20125228
commit ca668acee6
19 changed files with 6055 additions and 21 deletions

View File

@ -156,6 +156,10 @@ protected:
/// Defaults to false.
bool AllowAtInName = false;
/// This is true if the assembler allows $ @ ? characters at the start of
/// symbol names. Defaults to false.
bool AllowSymbolAtNameStart = false;
/// If this is true, symbol names with invalid characters will be printed in
/// quotes.
bool SupportsQuotedNames = true;
@ -537,6 +541,7 @@ public:
const char *getCode64Directive() const { return Code64Directive; }
unsigned getAssemblerDialect() const { return AssemblerDialect; }
bool doesAllowAtInName() const { return AllowAtInName; }
bool doesAllowSymbolAtNameStart() const { return AllowSymbolAtNameStart; }
bool supportsNameQuoting() const { return SupportsQuotedNames; }
bool doesSupportDataRegionDirectives() const {

View File

@ -30,6 +30,7 @@ class AsmLexer : public MCAsmLexer {
bool IsAtStartOfLine = true;
bool IsAtStartOfStatement = true;
bool IsPeeking = false;
bool EndStatementAtEOF = true;
protected:
/// LexToken - Read the next token and return its code.
@ -41,7 +42,8 @@ public:
AsmLexer &operator=(const AsmLexer &) = delete;
~AsmLexer() override;
void setBuffer(StringRef Buf, const char *ptr = nullptr);
void setBuffer(StringRef Buf, const char *ptr = nullptr,
bool EndStatementAtEOF = true);
StringRef LexUntilEndOfStatement() override;

View File

@ -250,6 +250,10 @@ public:
/// characters and return the string contents.
virtual bool parseEscapedString(std::string &Data) = 0;
/// Parse an angle-bracket delimited string at the current position if one is
/// present, returning the string contents.
virtual bool parseAngleBracketString(std::string &Data) = 0;
/// Skip to the end of the current statement, for error recovery.
virtual void eatToEndOfStatement() = 0;
@ -300,10 +304,14 @@ public:
SMLoc &EndLoc) = 0;
};
/// Create an MCAsmParser instance.
/// Create an MCAsmParser instance for parsing assembly similar to gas syntax
MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &,
const MCAsmInfo &, unsigned CB = 0);
/// Create an MCAsmParser instance for parsing Microsoft MASM-style assembly
MCAsmParser *createMCMasmParser(SourceMgr &, MCContext &, MCStreamer &,
const MCAsmInfo &, unsigned CB = 0);
} // end namespace llvm
#endif // LLVM_MC_MCPARSER_MCASMPARSER_H

View File

@ -399,7 +399,7 @@ public:
--I;
MCSectionSubPair NewSection = I->first;
if (OldSection != NewSection)
if (NewSection.first && OldSection != NewSection)
ChangeSection(NewSection.first, NewSection.second);
SectionStack.pop_back();
return true;

View File

@ -56,6 +56,7 @@ public:
int DwarfVersion = 0;
std::string ABIName;
std::string AssemblyLanguage;
std::string SplitDwarfFile;
/// Additional paths to search for `.include` directives when using the
@ -68,6 +69,11 @@ public:
/// textual name of the ABI that we want the backend to use, e.g. o32, or
/// aapcs-linux.
StringRef getABIName() const;
/// getAssemblyLanguage - If this returns a non-empty string this represents
/// the textual name of the assembly language that we will use for this
/// target, e.g. masm.
StringRef getAssemblyLanguage() const;
};
} // end namespace llvm

View File

@ -36,7 +36,8 @@ AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
AsmLexer::~AsmLexer() = default;
void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
void AsmLexer::setBuffer(StringRef Buf, const char *ptr,
bool EndStatementAtEOF) {
CurBuf = Buf;
if (ptr)
@ -45,6 +46,7 @@ void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
CurPtr = CurBuf.begin();
TokStart = nullptr;
this->EndStatementAtEOF = EndStatementAtEOF;
}
/// ReturnError - Set the error to the specified string at the specified
@ -584,7 +586,7 @@ AsmToken AsmLexer::LexToken() {
// If we're missing a newline at EOF, make sure we still get an
// EndOfStatement token before the Eof token.
if (CurChar == EOF && !IsAtStartOfStatement) {
if (CurChar == EOF && !IsAtStartOfStatement && EndStatementAtEOF) {
IsAtStartOfLine = true;
IsAtStartOfStatement = true;
return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
@ -594,15 +596,24 @@ AsmToken AsmLexer::LexToken() {
IsAtStartOfStatement = false;
switch (CurChar) {
default:
// Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
return LexIdentifier();
if (MAI.doesAllowSymbolAtNameStart()) {
// Handle Microsoft-style identifier: [a-zA-Z_$.@?][a-zA-Z0-9_$.@?]*
if (!isDigit(CurChar) &&
IsIdentifierChar(CurChar, MAI.doesAllowAtInName()))
return LexIdentifier();
} else {
// Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
return LexIdentifier();
}
// Unknown character, emit an error.
return ReturnError(TokStart, "invalid character in input");
case EOF:
IsAtStartOfLine = true;
IsAtStartOfStatement = true;
if (EndStatementAtEOF) {
IsAtStartOfLine = true;
IsAtStartOfStatement = true;
}
return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
case 0:
case ' ':

View File

@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
// This class implements the parser for assembly files.
// This class implements a parser for assembly files similar to gas syntax.
//
//===----------------------------------------------------------------------===//
@ -74,9 +74,7 @@ using namespace llvm;
MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
static cl::opt<unsigned> AsmMacroMaxNestingDepth(
"asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
cl::desc("The maximum nesting depth allowed for assembly macros."));
extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
namespace {
@ -645,6 +643,7 @@ private:
bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
bool parseEscapedString(std::string &Data) override;
bool parseAngleBracketString(std::string &Data) override;
const MCExpr *applyModifierToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind Variant);
@ -1365,7 +1364,7 @@ AsmParser::applyModifierToExpr(const MCExpr *E,
/// implementation. GCC does not fully support this feature and so we will not
/// support it.
/// TODO: Adding single quote as a string.
static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
assert((StrLoc.getPointer() != nullptr) &&
"Argument to the function cannot be a NULL value");
const char *CharPtr = StrLoc.getPointer();
@ -1383,7 +1382,7 @@ static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
}
/// creating a string without the escape characters '!'.
static std::string altMacroString(StringRef AltMacroStr) {
static std::string angleBracketString(StringRef AltMacroStr) {
std::string Res;
for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
if (AltMacroStr[Pos] == '!')
@ -2497,7 +2496,7 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
// is considered altMacroString!!!
else if (AltMacroMode && Token.getString().front() == '<' &&
Token.is(AsmToken::String)) {
OS << altMacroString(Token.getStringContents());
OS << angleBracketString(Token.getStringContents());
}
// We expect no quotes around the string's contents when
// parsing for varargs.
@ -2690,7 +2689,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
StringRef(StrChar, EndChar - StrChar), Value);
FA.Value.push_back(newToken);
} else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
isAltmacroString(StrLoc, EndLoc)) {
isAngleBracketString(StrLoc, EndLoc)) {
const char *StrChar = StrLoc.getPointer();
const char *EndChar = EndLoc.getPointer();
jumpToLoc(EndLoc, CurBuffer);
@ -2969,6 +2968,21 @@ bool AsmParser::parseEscapedString(std::string &Data) {
return false;
}
bool AsmParser::parseAngleBracketString(std::string &Data) {
SMLoc EndLoc, StartLoc = getTok().getLoc();
if (isAngleBracketString(StartLoc, EndLoc)) {
const char *StartChar = StartLoc.getPointer() + 1;
const char *EndChar = EndLoc.getPointer() - 1;
jumpToLoc(EndLoc, CurBuffer);
/// Eat from '<' to '>'
Lex();
Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
return false;
}
return true;
}
/// parseDirectiveAscii:
/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {

View File

@ -2,12 +2,14 @@ add_llvm_component_library(LLVMMCParser
AsmLexer.cpp
AsmParser.cpp
COFFAsmParser.cpp
COFFMasmParser.cpp
DarwinAsmParser.cpp
ELFAsmParser.cpp
MCAsmLexer.cpp
MCAsmParser.cpp
MCAsmParserExtension.cpp
MCTargetAsmParser.cpp
MasmParser.cpp
WasmAsmParser.cpp
ADDITIONAL_HEADER_DIRS

View File

@ -0,0 +1,386 @@
//===- COFFMasmParser.cpp - COFF MASM Assembly Parser ---------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
#include "llvm/MC/MCParser/MCAsmParserUtils.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/SMLoc.h"
#include <cassert>
#include <cstdint>
#include <limits>
#include <utility>
using namespace llvm;
namespace {
class COFFMasmParser : public MCAsmParserExtension {
template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)>
void addDirectiveHandler(StringRef Directive) {
MCAsmParser::ExtensionDirectiveHandler Handler =
std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>);
getParser().addDirectiveHandler(Directive, Handler);
}
bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
SectionKind Kind);
bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
SectionKind Kind, StringRef COMDATSymName,
COFF::COMDATType Type);
bool ParseDirectiveProc(StringRef, SMLoc);
bool ParseDirectiveEndProc(StringRef, SMLoc);
bool ParseDirectiveSegment(StringRef, SMLoc);
bool ParseDirectiveSegmentEnd(StringRef, SMLoc);
bool ParseDirectiveIncludelib(StringRef, SMLoc);
bool IgnoreDirective(StringRef, SMLoc) {
while (!getLexer().is(AsmToken::EndOfStatement)) {
Lex();
}
return false;
}
void Initialize(MCAsmParser &Parser) override {
// Call the base implementation.
MCAsmParserExtension::Initialize(Parser);
// x64 directives
// .allocstack
// .endprolog
// .pushframe
// .pushreg
// .savereg
// .savexmm128
// .setframe
// Code label directives
// label
// org
// Conditional control flow directives
// .break
// .continue
// .else
// .elseif
// .endif
// .endw
// .if
// .repeat
// .until
// .untilcxz
// .while
// Data allocation directives
// align
// byte/sbyte
// dword/sdword
// even
// fword
// qword
// real4
// real8
// real10
// tbyte
// word/sword
// Listing control directives
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title");
// Macro directives
// endm
// exitm
// goto
// local
// macro
// purge
// Miscellaneous directives
// alias
// assume
// .fpo
addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>(
"includelib");
// mmword
// option
// popcontext
// pushcontext
// .radix
// .safeseh
// xmmword
// ymmword
// Procedure directives
addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp");
// invoke (32-bit only)
addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc");
// proto
// Processor directives
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486P");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586P");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686P");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx");
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm");
// Repeat blocks directives
// for
// forc
// goto
// repeat
// while
// Scope directives
// comm
// externdef
// Segment directives
// .alpha (32-bit only, order segments alphabetically)
// .dosseg (32-bit only, order segments in DOS convention)
// .seq (32-bit only, order segments sequentially)
addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends");
// group (32-bit only)
addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment");
// Simplified segment directives
addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code");
// .const
addDirectiveHandler<
&COFFMasmParser::ParseSectionDirectiveInitializedData>(".data");
addDirectiveHandler<
&COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?");
// .exit
// .fardata
// .fardata?
addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model");
// .stack
// .startup
// String directives, written <name> <directive> <params>
// catstr (equivalent to <name> TEXTEQU <params>)
// instr (equivalent to <name> = @InStr(<params>))
// sizestr (equivalent to <name> = @SizeStr(<params>))
// substr (equivalent to <name> TEXTEQU @SubStr(<params>))
// Structure and record directives
// ends
// record
// struct
// typedef
// union
}
bool ParseSectionDirectiveCode(StringRef, SMLoc) {
return ParseSectionSwitch(".text",
COFF::IMAGE_SCN_CNT_CODE
| COFF::IMAGE_SCN_MEM_EXECUTE
| COFF::IMAGE_SCN_MEM_READ,
SectionKind::getText());
}
bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) {
return ParseSectionSwitch(".data",
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
| COFF::IMAGE_SCN_MEM_READ
| COFF::IMAGE_SCN_MEM_WRITE,
SectionKind::getData());
}
bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) {
return ParseSectionSwitch(".bss",
COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
| COFF::IMAGE_SCN_MEM_READ
| COFF::IMAGE_SCN_MEM_WRITE,
SectionKind::getBSS());
}
StringRef CurrentProcedure;
public:
COFFMasmParser() = default;
};
} // end anonymous namespace.
static SectionKind computeSectionKind(unsigned Flags) {
if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
return SectionKind::getText();
if (Flags & COFF::IMAGE_SCN_MEM_READ &&
(Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
return SectionKind::getReadOnly();
return SectionKind::getData();
}
bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
unsigned Characteristics,
SectionKind Kind) {
return ParseSectionSwitch(Section, Characteristics, Kind, "",
(COFF::COMDATType)0);
}
bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
unsigned Characteristics,
SectionKind Kind,
StringRef COMDATSymName,
COFF::COMDATType Type) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in section switching directive");
Lex();
getStreamer().SwitchSection(getContext().getCOFFSection(
Section, Characteristics, Kind, COMDATSymName, Type));
return false;
}
bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) {
StringRef SegmentName;
if (!getLexer().is(AsmToken::Identifier))
return TokError("expected identifier in directive");
SegmentName = getTok().getIdentifier();
Lex();
StringRef SectionName = SegmentName;
SmallVector<char, 247> SectionNameVector;
unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE;
if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) {
if (SegmentName.size() == 5) {
SectionName = ".text";
} else {
SectionName =
(".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector);
}
Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE |
COFF::IMAGE_SCN_MEM_READ;
}
SectionKind Kind = computeSectionKind(Flags);
getStreamer().SwitchSection(getContext().getCOFFSection(
SectionName, Flags, Kind, "", (COFF::COMDATType)(0)));
return false;
}
/// ParseDirectiveSegmentEnd
/// ::= identifier "ends"
bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) {
StringRef SegmentName;
if (!getLexer().is(AsmToken::Identifier))
return TokError("expected identifier in directive");
SegmentName = getTok().getIdentifier();
// Ignore; no action necessary.
Lex();
return false;
}
/// ParseDirectiveIncludelib
/// ::= "includelib" identifier
bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) {
StringRef Lib;
if (getParser().parseIdentifier(Lib))
return TokError("expected identifier in includelib directive");
unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT;
SectionKind Kind = computeSectionKind(Flags);
getStreamer().PushSection();
getStreamer().SwitchSection(getContext().getCOFFSection(
".drectve", Flags, Kind, "", (COFF::COMDATType)(0)));
getStreamer().emitBytes("/DEFAULTLIB:");
getStreamer().emitBytes(Lib);
getStreamer().emitBytes(" ");
getStreamer().PopSection();
return false;
}
/// ParseDirectiveProc
/// TODO(epastor): Implement parameters and other attributes.
/// ::= label "proc" [[distance]]
/// statements
/// label "endproc"
bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
StringRef Label;
if (getParser().parseIdentifier(Label))
return Error(Loc, "expected identifier for procedure");
if (getLexer().is(AsmToken::Identifier)) {
StringRef nextVal = getTok().getString();
SMLoc nextLoc = getTok().getLoc();
if (nextVal.equals_lower("far")) {
// TODO(epastor): Handle far procedure definitions.
Lex();
return Error(nextLoc, "far procedure definitions not yet supported");
} else if (nextVal.equals_lower("near")) {
Lex();
nextVal = getTok().getString();
nextLoc = getTok().getLoc();
}
}
MCSymbol *Sym = getContext().getOrCreateSymbol(Label);
// Define symbol as simple function
getStreamer().BeginCOFFSymbolDef(Sym);
getStreamer().EmitCOFFSymbolStorageClass(2);
getStreamer().EmitCOFFSymbolType(0x20);
getStreamer().EndCOFFSymbolDef();
getStreamer().emitLabel(Sym, Loc);
CurrentProcedure = Label;
return false;
}
bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
StringRef Label;
SMLoc LabelLoc = getTok().getLoc();
if (getParser().parseIdentifier(Label))
return Error(LabelLoc, "expected identifier for procedure end");
if (CurrentProcedure.empty())
return Error(Loc, "endp outside of procedure block");
else if (CurrentProcedure != Label)
return Error(LabelLoc, "endp does not match current procedure '" +
CurrentProcedure + "'");
return false;
}
namespace llvm {
MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; }
} // end namespace llvm

View File

@ -13,6 +13,7 @@
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/raw_ostream.h"
@ -20,6 +21,10 @@
using namespace llvm;
cl::opt<unsigned> AsmMacroMaxNestingDepth(
"asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
cl::desc("The maximum nesting depth allowed for assembly macros."));
MCAsmParser::MCAsmParser() {}
MCAsmParser::~MCAsmParser() = default;

File diff suppressed because it is too large Load Diff

View File

@ -21,3 +21,7 @@ MCTargetOptions::MCTargetOptions()
StringRef MCTargetOptions::getABIName() const {
return ABIName;
}
StringRef MCTargetOptions::getAssemblyLanguage() const {
return AssemblyLanguage;
}

View File

@ -145,6 +145,16 @@ X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple &Triple) {
UseIntegratedAssembler = true;
}
void X86MCAsmInfoMicrosoftMASM::anchor() { }
X86MCAsmInfoMicrosoftMASM::X86MCAsmInfoMicrosoftMASM(const Triple &Triple)
: X86MCAsmInfoMicrosoft(Triple) {
DollarIsPC = true;
SeparatorString = "\n";
CommentString = ";";
AllowSymbolAtNameStart = true;
}
void X86MCAsmInfoGNUCOFF::anchor() { }
X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) {

View File

@ -49,6 +49,13 @@ public:
explicit X86MCAsmInfoMicrosoft(const Triple &Triple);
};
class X86MCAsmInfoMicrosoftMASM : public X86MCAsmInfoMicrosoft {
void anchor() override;
public:
explicit X86MCAsmInfoMicrosoftMASM(const Triple &Triple);
};
class X86MCAsmInfoGNUCOFF : public MCAsmInfoGNUCOFF {
void anchor() override;

View File

@ -335,7 +335,10 @@ static MCAsmInfo *createX86MCAsmInfo(const MCRegisterInfo &MRI,
MAI = new X86ELFMCAsmInfo(TheTriple);
} else if (TheTriple.isWindowsMSVCEnvironment() ||
TheTriple.isWindowsCoreCLREnvironment()) {
MAI = new X86MCAsmInfoMicrosoft(TheTriple);
if (Options.getAssemblyLanguage().equals_lower("masm"))
MAI = new X86MCAsmInfoMicrosoftMASM(TheTriple);
else
MAI = new X86MCAsmInfoMicrosoft(TheTriple);
} else if (TheTriple.isOSCygMing() ||
TheTriple.isWindowsItaniumEnvironment()) {
MAI = new X86MCAsmInfoGNUCOFF(TheTriple);

View File

@ -1,4 +1,3 @@
# REQUIRES: x86-registered-target
# RUN: not llvm-ml %t.blah -o /dev/null 2>&1 | FileCheck --check-prefix=ENOENT %s
# ENOENT: {{.*}}.blah: {{[Nn]}}o such file or directory

View File

@ -0,0 +1,3 @@
if not ('X86' in config.root.targets):
# We need support for X86.
config.unsupported = True

View File

@ -189,7 +189,8 @@ static int AssembleInput(const char *ProgName, const Target *TheTarget,
SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str,
MCAsmInfo &MAI, MCSubtargetInfo &STI,
MCInstrInfo &MCII, MCTargetOptions &MCOptions) {
std::unique_ptr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, Str, MAI));
std::unique_ptr<MCAsmParser> Parser(
createMCMasmParser(SrcMgr, Ctx, Str, MAI));
std::unique_ptr<MCTargetAsmParser> TAP(
TheTarget->createMCAsmParser(STI, *Parser, MCII, MCOptions));
@ -222,6 +223,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
MCOptions.AssemblyLanguage = "masm";
const char *ProgName = argv[0];
const Target *TheTarget = GetTarget(ProgName);

View File

@ -14,6 +14,7 @@ static_library("MCParser") {
"MCAsmLexer.cpp",
"MCAsmParser.cpp",
"MCAsmParserExtension.cpp",
"MasmParser.cpp",
"MCTargetAsmParser.cpp",
"WasmAsmParser.cpp",
]