mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-13 08:26:02 +00:00
[ms-inline asm] Move most of the AsmParsing logic in clang back into the MC
layer. Add the ParseMSInlineAsm() function, which is the new interface to clang. Also expose the new MCAsmParserSemaCallback interface, which is used by the back-end to do name lookup in Sema. Finally, remove the now defunct APIs introduced in r165946. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166183 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -20,6 +20,8 @@ class MCAsmLexer;
|
|||||||
class MCAsmParserExtension;
|
class MCAsmParserExtension;
|
||||||
class MCContext;
|
class MCContext;
|
||||||
class MCExpr;
|
class MCExpr;
|
||||||
|
class MCInstPrinter;
|
||||||
|
class MCInstrInfo;
|
||||||
class MCParsedAsmOperand;
|
class MCParsedAsmOperand;
|
||||||
class MCStreamer;
|
class MCStreamer;
|
||||||
class MCTargetAsmParser;
|
class MCTargetAsmParser;
|
||||||
@@ -29,6 +31,13 @@ class SourceMgr;
|
|||||||
class StringRef;
|
class StringRef;
|
||||||
class Twine;
|
class Twine;
|
||||||
|
|
||||||
|
/// MCAsmParserSemaCallback - Generic Sema callback for assembly parser.
|
||||||
|
class MCAsmParserSemaCallback {
|
||||||
|
public:
|
||||||
|
virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc,
|
||||||
|
void **IdentifierInfoPtr) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
/// MCAsmParser - Generic assembler parser interface, for use by target specific
|
/// MCAsmParser - Generic assembler parser interface, for use by target specific
|
||||||
/// assembly parsers.
|
/// assembly parsers.
|
||||||
class MCAsmParser {
|
class MCAsmParser {
|
||||||
@@ -77,25 +86,20 @@ public:
|
|||||||
virtual void setParsingInlineAsm(bool V) = 0;
|
virtual void setParsingInlineAsm(bool V) = 0;
|
||||||
virtual bool isParsingInlineAsm() = 0;
|
virtual bool isParsingInlineAsm() = 0;
|
||||||
|
|
||||||
|
/// ParseMSInlineAsm - Parse ms-style inline assembly.
|
||||||
|
virtual bool ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||||
|
unsigned &NumOutputs, unsigned &NumInputs,
|
||||||
|
SmallVectorImpl<void *> &Names,
|
||||||
|
SmallVectorImpl<std::string> &Constraints,
|
||||||
|
SmallVectorImpl<void *> &Exprs,
|
||||||
|
SmallVectorImpl<std::string> &Clobbers,
|
||||||
|
const MCInstrInfo *MII,
|
||||||
|
const MCInstPrinter *IP,
|
||||||
|
MCAsmParserSemaCallback &SI) = 0;
|
||||||
|
|
||||||
/// ParseStatement - Parse the next statement.
|
/// ParseStatement - Parse the next statement.
|
||||||
virtual bool ParseStatement() = 0;
|
virtual bool ParseStatement() = 0;
|
||||||
|
|
||||||
/// getNumParsedOperands - Returns the number of MCAsmParsedOperands from the
|
|
||||||
/// previously parsed statement.
|
|
||||||
virtual unsigned getNumParsedOperands() = 0;
|
|
||||||
|
|
||||||
/// getParsedOperand - Get a MCAsmParsedOperand.
|
|
||||||
virtual MCParsedAsmOperand &getParsedOperand(unsigned OpNum) = 0;
|
|
||||||
|
|
||||||
/// freeParsedOperands - Free the MCAsmParsedOperands.
|
|
||||||
virtual void freeParsedOperands() = 0;
|
|
||||||
|
|
||||||
/// isInstruction - Was the previously parsed statement an instruction?
|
|
||||||
virtual bool isInstruction() = 0;
|
|
||||||
|
|
||||||
/// getOpcode - Get the opcode from the previously parsed instruction.
|
|
||||||
virtual unsigned getOpcode() = 0;
|
|
||||||
|
|
||||||
/// Warning - Emit a warning at the location \p L, with the message \p Msg.
|
/// Warning - Emit a warning at the location \p L, with the message \p Msg.
|
||||||
///
|
///
|
||||||
/// \return The return value is true, if warnings are fatal.
|
/// \return The return value is true, if warnings are fatal.
|
||||||
|
@@ -19,6 +19,8 @@
|
|||||||
#include "llvm/MC/MCContext.h"
|
#include "llvm/MC/MCContext.h"
|
||||||
#include "llvm/MC/MCDwarf.h"
|
#include "llvm/MC/MCDwarf.h"
|
||||||
#include "llvm/MC/MCExpr.h"
|
#include "llvm/MC/MCExpr.h"
|
||||||
|
#include "llvm/MC/MCInstPrinter.h"
|
||||||
|
#include "llvm/MC/MCInstrInfo.h"
|
||||||
#include "llvm/MC/MCParser/AsmCond.h"
|
#include "llvm/MC/MCParser/AsmCond.h"
|
||||||
#include "llvm/MC/MCParser/AsmLexer.h"
|
#include "llvm/MC/MCParser/AsmLexer.h"
|
||||||
#include "llvm/MC/MCParser/MCAsmParser.h"
|
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||||
@@ -35,6 +37,8 @@
|
|||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@@ -139,7 +143,8 @@ private:
|
|||||||
/// ParsedOperands - The parsed operands from the last parsed statement.
|
/// ParsedOperands - The parsed operands from the last parsed statement.
|
||||||
SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
|
SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
|
||||||
|
|
||||||
/// Opcode - The opcode from the last parsed instruction.
|
/// Opcode - The opcode from the last parsed instruction. This is MS-style
|
||||||
|
/// inline asm specific.
|
||||||
unsigned Opcode;
|
unsigned Opcode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -180,21 +185,18 @@ public:
|
|||||||
|
|
||||||
virtual const AsmToken &Lex();
|
virtual const AsmToken &Lex();
|
||||||
|
|
||||||
bool ParseStatement();
|
|
||||||
void setParsingInlineAsm(bool V) { ParsingInlineAsm = V; }
|
void setParsingInlineAsm(bool V) { ParsingInlineAsm = V; }
|
||||||
bool isParsingInlineAsm() { return ParsingInlineAsm; }
|
bool isParsingInlineAsm() { return ParsingInlineAsm; }
|
||||||
unsigned getNumParsedOperands() { return ParsedOperands.size(); }
|
|
||||||
MCParsedAsmOperand &getParsedOperand(unsigned OpNum) {
|
bool ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||||
assert (ParsedOperands.size() > OpNum);
|
unsigned &NumOutputs, unsigned &NumInputs,
|
||||||
return *ParsedOperands[OpNum];
|
SmallVectorImpl<void *> &Names,
|
||||||
}
|
SmallVectorImpl<std::string> &Constraints,
|
||||||
void freeParsedOperands() {
|
SmallVectorImpl<void *> &Exprs,
|
||||||
for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
|
SmallVectorImpl<std::string> &Clobbers,
|
||||||
delete ParsedOperands[i];
|
const MCInstrInfo *MII,
|
||||||
ParsedOperands.clear();
|
const MCInstPrinter *IP,
|
||||||
}
|
MCAsmParserSemaCallback &SI);
|
||||||
bool isInstruction() { return Opcode != (unsigned)~0x0; }
|
|
||||||
unsigned getOpcode() { return Opcode; }
|
|
||||||
|
|
||||||
bool ParseExpression(const MCExpr *&Res);
|
bool ParseExpression(const MCExpr *&Res);
|
||||||
virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc);
|
virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc);
|
||||||
@@ -206,6 +208,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void CheckForValidSection();
|
void CheckForValidSection();
|
||||||
|
|
||||||
|
bool ParseStatement();
|
||||||
void EatToEndOfLine();
|
void EatToEndOfLine();
|
||||||
bool ParseCppHashLineFilenameComment(const SMLoc &L);
|
bool ParseCppHashLineFilenameComment(const SMLoc &L);
|
||||||
|
|
||||||
@@ -311,6 +314,10 @@ private:
|
|||||||
bool ParseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
|
bool ParseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
|
||||||
bool ParseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
|
bool ParseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
|
||||||
bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
|
bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
|
||||||
|
|
||||||
|
// MS-style inline assembly parsing.
|
||||||
|
bool isInstruction() { return Opcode != (unsigned)~0x0; }
|
||||||
|
unsigned getOpcode() { return Opcode; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Generic implementations of directive handling, etc. which is shared
|
/// \brief Generic implementations of directive handling, etc. which is shared
|
||||||
@@ -1378,10 +1385,13 @@ bool AsmParser::ParseStatement() {
|
|||||||
ParsingInlineAsm);
|
ParsingInlineAsm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free any parsed operands. If parsing ms-style inline assembly it is the
|
// Free any parsed operands. If parsing ms-style inline assembly the operands
|
||||||
// responsibility of the caller (i.e., clang) to free the parsed operands.
|
// will be freed by the ParseMSInlineAsm() function.
|
||||||
if (!ParsingInlineAsm)
|
if (!ParsingInlineAsm) {
|
||||||
freeParsedOperands();
|
for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
|
||||||
|
delete ParsedOperands[i];
|
||||||
|
ParsedOperands.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Don't skip the rest of the line, the instruction parser is responsible for
|
// Don't skip the rest of the line, the instruction parser is responsible for
|
||||||
// that.
|
// that.
|
||||||
@@ -3562,6 +3572,179 @@ bool AsmParser::ParseDirectiveEndr(SMLoc DirectiveLoc) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
enum AsmOpRewriteKind {
|
||||||
|
AOK_Imm,
|
||||||
|
AOK_Input,
|
||||||
|
AOK_Output
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AsmOpRewrite {
|
||||||
|
AsmOpRewriteKind Kind;
|
||||||
|
SMLoc Loc;
|
||||||
|
unsigned Len;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsmOpRewrite(AsmOpRewriteKind kind, SMLoc loc, unsigned len)
|
||||||
|
: Kind(kind), Loc(loc), Len(len) { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||||
|
unsigned &NumOutputs, unsigned &NumInputs,
|
||||||
|
SmallVectorImpl<void *> &Names,
|
||||||
|
SmallVectorImpl<std::string> &Constraints,
|
||||||
|
SmallVectorImpl<void *> &Exprs,
|
||||||
|
SmallVectorImpl<std::string> &Clobbers,
|
||||||
|
const MCInstrInfo *MII,
|
||||||
|
const MCInstPrinter *IP,
|
||||||
|
MCAsmParserSemaCallback &SI) {
|
||||||
|
SmallVector<void*, 4> Inputs;
|
||||||
|
SmallVector<void*, 4> Outputs;
|
||||||
|
SmallVector<std::string, 4> InputConstraints;
|
||||||
|
SmallVector<std::string, 4> OutputConstraints;
|
||||||
|
SmallVector<void*, 4> InputExprs;
|
||||||
|
SmallVector<void*, 4> OutputExprs;
|
||||||
|
std::set<std::string> ClobberRegs;
|
||||||
|
|
||||||
|
SmallVector<struct AsmOpRewrite, 4> AsmStrRewrites;
|
||||||
|
|
||||||
|
// Prime the lexer.
|
||||||
|
Lex();
|
||||||
|
|
||||||
|
// While we have input, parse each statement.
|
||||||
|
unsigned InputIdx = 0;
|
||||||
|
unsigned OutputIdx = 0;
|
||||||
|
while (getLexer().isNot(AsmToken::Eof)) {
|
||||||
|
if (ParseStatement()) return true;
|
||||||
|
|
||||||
|
if (isInstruction()) {
|
||||||
|
const MCInstrDesc &Desc = MII->get(getOpcode());
|
||||||
|
|
||||||
|
// Build the list of clobbers, outputs and inputs.
|
||||||
|
for (unsigned i = 1, e = ParsedOperands.size(); i != e; ++i) {
|
||||||
|
MCParsedAsmOperand *Operand = ParsedOperands[i];
|
||||||
|
|
||||||
|
// Immediate.
|
||||||
|
if (Operand->isImm()) {
|
||||||
|
AsmStrRewrites.push_back(AsmOpRewrite(AOK_Imm,
|
||||||
|
Operand->getStartLoc(),
|
||||||
|
Operand->getNameLen()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register operand.
|
||||||
|
if (Operand->isReg()) {
|
||||||
|
unsigned NumDefs = Desc.getNumDefs();
|
||||||
|
// Clobber.
|
||||||
|
if (NumDefs && Operand->getMCOperandNum() < NumDefs) {
|
||||||
|
std::string Reg;
|
||||||
|
raw_string_ostream OS(Reg);
|
||||||
|
IP->printRegName(OS, Operand->getReg());
|
||||||
|
ClobberRegs.insert(StringRef(OS.str()));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expr/Input or Output.
|
||||||
|
void *II;
|
||||||
|
void *ExprResult = SI.LookupInlineAsmIdentifier(Operand->getName(),
|
||||||
|
AsmLoc, &II);
|
||||||
|
if (ExprResult) {
|
||||||
|
bool isOutput = (i == 1) && Desc.mayStore();
|
||||||
|
if (isOutput) {
|
||||||
|
std::string Constraint = "=";
|
||||||
|
++InputIdx;
|
||||||
|
Outputs.push_back(II);
|
||||||
|
OutputExprs.push_back(ExprResult);
|
||||||
|
Constraint += Operand->getConstraint().str();
|
||||||
|
OutputConstraints.push_back(Constraint);
|
||||||
|
AsmStrRewrites.push_back(AsmOpRewrite(AOK_Output,
|
||||||
|
Operand->getStartLoc(),
|
||||||
|
Operand->getNameLen()));
|
||||||
|
} else {
|
||||||
|
Inputs.push_back(II);
|
||||||
|
InputExprs.push_back(ExprResult);
|
||||||
|
InputConstraints.push_back(Operand->getConstraint().str());
|
||||||
|
AsmStrRewrites.push_back(AsmOpRewrite(AOK_Input,
|
||||||
|
Operand->getStartLoc(),
|
||||||
|
Operand->getNameLen()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Free any parsed operands.
|
||||||
|
for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
|
||||||
|
delete ParsedOperands[i];
|
||||||
|
ParsedOperands.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the number of Outputs and Inputs.
|
||||||
|
NumOutputs = Outputs.size();
|
||||||
|
NumInputs = Inputs.size();
|
||||||
|
|
||||||
|
// Set the unique clobbers.
|
||||||
|
for (std::set<std::string>::iterator I = ClobberRegs.begin(),
|
||||||
|
E = ClobberRegs.end(); I != E; ++I)
|
||||||
|
Clobbers.push_back(*I);
|
||||||
|
|
||||||
|
// Merge the various outputs and inputs. Output are expected first.
|
||||||
|
if (NumOutputs || NumInputs) {
|
||||||
|
unsigned NumExprs = NumOutputs + NumInputs;
|
||||||
|
Names.resize(NumExprs);
|
||||||
|
Constraints.resize(NumExprs);
|
||||||
|
Exprs.resize(NumExprs);
|
||||||
|
for (unsigned i = 0; i < NumOutputs; ++i) {
|
||||||
|
Names[i] = Outputs[i];
|
||||||
|
Constraints[i] = OutputConstraints[i];
|
||||||
|
Exprs[i] = OutputExprs[i];
|
||||||
|
}
|
||||||
|
for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
|
||||||
|
Names[j] = Inputs[i];
|
||||||
|
Constraints[j] = InputConstraints[i];
|
||||||
|
Exprs[j] = InputExprs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the IR assembly string.
|
||||||
|
std::string AsmStringIR;
|
||||||
|
raw_string_ostream OS(AsmStringIR);
|
||||||
|
const char *Start = SrcMgr.getMemoryBuffer(0)->getBufferStart();
|
||||||
|
for (SmallVectorImpl<struct AsmOpRewrite>::iterator
|
||||||
|
I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
|
||||||
|
const char *Loc = (*I).Loc.getPointer();
|
||||||
|
|
||||||
|
// Emit everything up to the immediate/expression.
|
||||||
|
OS << StringRef(Start, Loc - Start);
|
||||||
|
|
||||||
|
// Rewrite expressions in $N notation.
|
||||||
|
switch ((*I).Kind) {
|
||||||
|
case AOK_Imm:
|
||||||
|
OS << Twine("$$") + StringRef(Loc, (*I).Len);
|
||||||
|
break;
|
||||||
|
case AOK_Input:
|
||||||
|
OS << '$';
|
||||||
|
OS << InputIdx++;
|
||||||
|
break;
|
||||||
|
case AOK_Output:
|
||||||
|
OS << '$';
|
||||||
|
OS << OutputIdx++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the original expression.
|
||||||
|
Start = Loc + (*I).Len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit the remainder of the asm string.
|
||||||
|
const char *AsmEnd = SrcMgr.getMemoryBuffer(0)->getBufferEnd();
|
||||||
|
if (Start != AsmEnd)
|
||||||
|
OS << StringRef(Start, AsmEnd - Start);
|
||||||
|
|
||||||
|
AsmString = OS.str();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Create an MCAsmParser instance.
|
/// \brief Create an MCAsmParser instance.
|
||||||
MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM,
|
MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM,
|
||||||
MCContext &C, MCStreamer &Out,
|
MCContext &C, MCStreamer &Out,
|
||||||
|
Reference in New Issue
Block a user