mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-10-25 10:27:04 +00:00
[ms-inline asm] Have the TargetParser callback to Sema to determine the size of
a memory operand. Retain this information and then add the sizing directives to the IR. This allows the backend to do proper instruction selection. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166316 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -57,12 +57,17 @@ public:
|
|||||||
|
|
||||||
/// isMem - Is this a memory operand?
|
/// isMem - Is this a memory operand?
|
||||||
virtual bool isMem() const = 0;
|
virtual bool isMem() const = 0;
|
||||||
|
virtual unsigned getMemSize() const { return 0; }
|
||||||
|
|
||||||
/// getStartLoc - Get the location of the first token of this operand.
|
/// getStartLoc - Get the location of the first token of this operand.
|
||||||
virtual SMLoc getStartLoc() const = 0;
|
virtual SMLoc getStartLoc() const = 0;
|
||||||
/// getEndLoc - Get the location of the last token of this operand.
|
/// getEndLoc - Get the location of the last token of this operand.
|
||||||
virtual SMLoc getEndLoc() const = 0;
|
virtual SMLoc getEndLoc() const = 0;
|
||||||
|
|
||||||
|
/// needSizeDirective - Do we need to emit a sizing directive for this
|
||||||
|
/// operand? Only valid when parsing MS-style inline assembly.
|
||||||
|
virtual bool needSizeDirective() const { return false; }
|
||||||
|
|
||||||
/// print - Print a debug representation of the operand to the given stream.
|
/// print - Print a debug representation of the operand to the given stream.
|
||||||
virtual void print(raw_ostream &OS) const = 0;
|
virtual void print(raw_ostream &OS) const = 0;
|
||||||
/// dump - Print to the debug stream.
|
/// dump - Print to the debug stream.
|
||||||
|
|||||||
@@ -3577,17 +3577,18 @@ namespace {
|
|||||||
enum AsmOpRewriteKind {
|
enum AsmOpRewriteKind {
|
||||||
AOK_Imm,
|
AOK_Imm,
|
||||||
AOK_Input,
|
AOK_Input,
|
||||||
AOK_Output
|
AOK_Output,
|
||||||
|
AOK_SizeDirective
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AsmOpRewrite {
|
struct AsmOpRewrite {
|
||||||
AsmOpRewriteKind Kind;
|
AsmOpRewriteKind Kind;
|
||||||
SMLoc Loc;
|
SMLoc Loc;
|
||||||
unsigned Len;
|
unsigned Len;
|
||||||
|
unsigned Size;
|
||||||
public:
|
public:
|
||||||
AsmOpRewrite(AsmOpRewriteKind kind, SMLoc loc, unsigned len)
|
AsmOpRewrite(AsmOpRewriteKind kind, SMLoc loc, unsigned len, unsigned size = 0)
|
||||||
: Kind(kind), Loc(loc), Len(len) { }
|
: Kind(kind), Loc(loc), Len(len), Size(size) { }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3650,6 +3651,11 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
Size);
|
Size);
|
||||||
if (OpDecl) {
|
if (OpDecl) {
|
||||||
bool isOutput = (i == 1) && Desc.mayStore();
|
bool isOutput = (i == 1) && Desc.mayStore();
|
||||||
|
if (Operand->needSizeDirective())
|
||||||
|
AsmStrRewrites.push_back(AsmOpRewrite(AOK_SizeDirective,
|
||||||
|
Operand->getStartLoc(), 0,
|
||||||
|
Operand->getMemSize()));
|
||||||
|
|
||||||
if (isOutput) {
|
if (isOutput) {
|
||||||
std::string Constraint = "=";
|
std::string Constraint = "=";
|
||||||
++InputIdx;
|
++InputIdx;
|
||||||
@@ -3701,17 +3707,23 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
|
|
||||||
// Build the IR assembly string.
|
// Build the IR assembly string.
|
||||||
std::string AsmStringIR;
|
std::string AsmStringIR;
|
||||||
|
AsmOpRewriteKind PrevKind = AOK_Imm;
|
||||||
raw_string_ostream OS(AsmStringIR);
|
raw_string_ostream OS(AsmStringIR);
|
||||||
const char *Start = SrcMgr.getMemoryBuffer(0)->getBufferStart();
|
const char *Start = SrcMgr.getMemoryBuffer(0)->getBufferStart();
|
||||||
for (SmallVectorImpl<struct AsmOpRewrite>::iterator
|
for (SmallVectorImpl<struct AsmOpRewrite>::iterator
|
||||||
I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
|
I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
|
||||||
const char *Loc = (*I).Loc.getPointer();
|
const char *Loc = (*I).Loc.getPointer();
|
||||||
|
|
||||||
// Emit everything up to the immediate/expression.
|
AsmOpRewriteKind Kind = (*I).Kind;
|
||||||
OS << StringRef(Start, Loc - Start);
|
|
||||||
|
// Emit everything up to the immediate/expression. If the previous rewrite
|
||||||
|
// was a size directive, then this has already been done.
|
||||||
|
if (PrevKind != AOK_SizeDirective)
|
||||||
|
OS << StringRef(Start, Loc - Start);
|
||||||
|
PrevKind = Kind;
|
||||||
|
|
||||||
// Rewrite expressions in $N notation.
|
// Rewrite expressions in $N notation.
|
||||||
switch ((*I).Kind) {
|
switch (Kind) {
|
||||||
case AOK_Imm:
|
case AOK_Imm:
|
||||||
OS << Twine("$$") + StringRef(Loc, (*I).Len);
|
OS << Twine("$$") + StringRef(Loc, (*I).Len);
|
||||||
break;
|
break;
|
||||||
@@ -3723,10 +3735,22 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
OS << '$';
|
OS << '$';
|
||||||
OS << OutputIdx++;
|
OS << OutputIdx++;
|
||||||
break;
|
break;
|
||||||
|
case AOK_SizeDirective:
|
||||||
|
switch((*I).Size) {
|
||||||
|
default: break;
|
||||||
|
case 8: OS << "byte ptr "; break;
|
||||||
|
case 16: OS << "word ptr "; break;
|
||||||
|
case 32: OS << "dword ptr "; break;
|
||||||
|
case 64: OS << "qword ptr "; break;
|
||||||
|
case 80: OS << "xword ptr "; break;
|
||||||
|
case 128: OS << "xmmword ptr "; break;
|
||||||
|
case 256: OS << "ymmword ptr "; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip the original expression.
|
// Skip the original expression.
|
||||||
Start = Loc + (*I).Len;
|
if (Kind != AOK_SizeDirective)
|
||||||
|
Start = Loc + (*I).Len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit the remainder of the asm string.
|
// Emit the remainder of the asm string.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "llvm/MC/MCTargetAsmParser.h"
|
#include "llvm/MC/MCTargetAsmParser.h"
|
||||||
#include "llvm/MC/MCStreamer.h"
|
#include "llvm/MC/MCStreamer.h"
|
||||||
#include "llvm/MC/MCExpr.h"
|
#include "llvm/MC/MCExpr.h"
|
||||||
|
#include "llvm/MC/MCSymbol.h"
|
||||||
#include "llvm/MC/MCInst.h"
|
#include "llvm/MC/MCInst.h"
|
||||||
#include "llvm/MC/MCRegisterInfo.h"
|
#include "llvm/MC/MCRegisterInfo.h"
|
||||||
#include "llvm/MC/MCSubtargetInfo.h"
|
#include "llvm/MC/MCSubtargetInfo.h"
|
||||||
@@ -180,6 +181,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
unsigned IndexReg;
|
unsigned IndexReg;
|
||||||
unsigned Scale;
|
unsigned Scale;
|
||||||
unsigned Size;
|
unsigned Size;
|
||||||
|
bool NeedSizeDir;
|
||||||
} Mem;
|
} Mem;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -312,6 +314,16 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
return isImmSExti64i32Value(CE->getValue());
|
return isImmSExti64i32Value(CE->getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned getMemSize() const {
|
||||||
|
assert(Kind == Memory && "Invalid access!");
|
||||||
|
return Mem.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needSizeDirective() const {
|
||||||
|
assert(Kind == Memory && "Invalid access!");
|
||||||
|
return Mem.NeedSizeDir;
|
||||||
|
}
|
||||||
|
|
||||||
bool isMem() const { return Kind == Memory; }
|
bool isMem() const { return Kind == Memory; }
|
||||||
bool isMem8() const {
|
bool isMem8() const {
|
||||||
return Kind == Memory && (!Mem.Size || Mem.Size == 8);
|
return Kind == Memory && (!Mem.Size || Mem.Size == 8);
|
||||||
@@ -451,7 +463,8 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
|
|
||||||
/// Create an absolute memory operand.
|
/// Create an absolute memory operand.
|
||||||
static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
|
static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
|
||||||
SMLoc EndLoc, unsigned Size = 0) {
|
SMLoc EndLoc, unsigned Size = 0,
|
||||||
|
bool NeedSizeDir = false) {
|
||||||
X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
|
X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
|
||||||
Res->Mem.SegReg = 0;
|
Res->Mem.SegReg = 0;
|
||||||
Res->Mem.Disp = Disp;
|
Res->Mem.Disp = Disp;
|
||||||
@@ -459,6 +472,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
Res->Mem.IndexReg = 0;
|
Res->Mem.IndexReg = 0;
|
||||||
Res->Mem.Scale = 1;
|
Res->Mem.Scale = 1;
|
||||||
Res->Mem.Size = Size;
|
Res->Mem.Size = Size;
|
||||||
|
Res->Mem.NeedSizeDir = NeedSizeDir;
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,7 +480,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
|
static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
|
||||||
unsigned BaseReg, unsigned IndexReg,
|
unsigned BaseReg, unsigned IndexReg,
|
||||||
unsigned Scale, SMLoc StartLoc, SMLoc EndLoc,
|
unsigned Scale, SMLoc StartLoc, SMLoc EndLoc,
|
||||||
unsigned Size = 0) {
|
unsigned Size = 0, bool NeedSizeDir = false) {
|
||||||
// We should never just have a displacement, that should be parsed as an
|
// We should never just have a displacement, that should be parsed as an
|
||||||
// absolute memory operand.
|
// absolute memory operand.
|
||||||
assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
|
assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
|
||||||
@@ -481,6 +495,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
Res->Mem.IndexReg = IndexReg;
|
Res->Mem.IndexReg = IndexReg;
|
||||||
Res->Mem.Scale = Scale;
|
Res->Mem.Scale = Scale;
|
||||||
Res->Mem.Size = Size;
|
Res->Mem.Size = Size;
|
||||||
|
Res->Mem.NeedSizeDir = NeedSizeDir;
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -753,7 +768,19 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
|
|||||||
const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
|
const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
|
||||||
if (getParser().ParseExpression(Disp, End)) return 0;
|
if (getParser().ParseExpression(Disp, End)) return 0;
|
||||||
End = Parser.getTok().getLoc();
|
End = Parser.getTok().getLoc();
|
||||||
return X86Operand::CreateMem(Disp, Start, End, Size);
|
|
||||||
|
bool NeedSizeDir = false;
|
||||||
|
if (!Size && isParsingInlineAsm()) {
|
||||||
|
if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Disp)) {
|
||||||
|
const MCSymbol &Sym = SymRef->getSymbol();
|
||||||
|
// FIXME: The SemaLookup will fail if the name is anything other then an
|
||||||
|
// identifier.
|
||||||
|
// FIXME: Pass a valid SMLoc.
|
||||||
|
SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Size);
|
||||||
|
NeedSizeDir = Size > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return X86Operand::CreateMem(Disp, Start, End, Size, NeedSizeDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
X86Operand *X86AsmParser::ParseIntelOperand() {
|
X86Operand *X86AsmParser::ParseIntelOperand() {
|
||||||
|
|||||||
Reference in New Issue
Block a user