mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-25 00:33:15 +00:00
[ms-inline asm] Add an implementation of the offset operator. This is a follow
on patch to r166433. rdar://12470317 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166488 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a7554630e9
commit
5a719fcb5e
@ -90,7 +90,7 @@ public:
|
||||
/// ParseMSInlineAsm - Parse ms-style inline assembly.
|
||||
virtual bool ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||
unsigned &NumOutputs, unsigned &NumInputs,
|
||||
SmallVectorImpl<void *> &OpDecls,
|
||||
SmallVectorImpl<std::pair<void *, bool> > &OpDecls,
|
||||
SmallVectorImpl<std::string> &Constraints,
|
||||
SmallVectorImpl<std::string> &Clobbers,
|
||||
const MCInstrInfo *MII,
|
||||
|
@ -69,6 +69,9 @@ public:
|
||||
/// inline assembly.
|
||||
virtual bool isOffsetOf() const { return false; }
|
||||
|
||||
/// getOffsetOfLoc - Get the location of the offset operator.
|
||||
virtual SMLoc getOffsetOfLoc() const { return SMLoc(); }
|
||||
|
||||
/// 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; }
|
||||
|
@ -207,7 +207,7 @@ public:
|
||||
|
||||
bool ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||
unsigned &NumOutputs, unsigned &NumInputs,
|
||||
SmallVectorImpl<void *> &OpDecls,
|
||||
SmallVectorImpl<std::pair<void *,bool> > &OpDecls,
|
||||
SmallVectorImpl<std::string> &Constraints,
|
||||
SmallVectorImpl<std::string> &Clobbers,
|
||||
const MCInstrInfo *MII,
|
||||
@ -3589,7 +3589,8 @@ enum AsmRewriteKind {
|
||||
AOK_Input,
|
||||
AOK_Output,
|
||||
AOK_SizeDirective,
|
||||
AOK_Emit
|
||||
AOK_Emit,
|
||||
AOK_Skip
|
||||
};
|
||||
|
||||
struct AsmRewrite {
|
||||
@ -3621,14 +3622,16 @@ bool AsmParser::ParseDirectiveEmit(SMLoc IDLoc, ParseStatementInfo &Info) {
|
||||
|
||||
bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||
unsigned &NumOutputs, unsigned &NumInputs,
|
||||
SmallVectorImpl<void *> &OpDecls,
|
||||
SmallVectorImpl<std::pair<void *, bool> > &OpDecls,
|
||||
SmallVectorImpl<std::string> &Constraints,
|
||||
SmallVectorImpl<std::string> &Clobbers,
|
||||
const MCInstrInfo *MII,
|
||||
const MCInstPrinter *IP,
|
||||
MCAsmParserSemaCallback &SI) {
|
||||
SmallVector<void*, 4> InputDecls;
|
||||
SmallVector<void*, 4> OutputDecls;
|
||||
SmallVector<void *, 4> InputDecls;
|
||||
SmallVector<void *, 4> OutputDecls;
|
||||
SmallVector<bool, 4> InputDeclsOffsetOf;
|
||||
SmallVector<bool, 4> OutputDeclsOffsetOf;
|
||||
SmallVector<std::string, 4> InputConstraints;
|
||||
SmallVector<std::string, 4> OutputConstraints;
|
||||
std::set<std::string> ClobberRegs;
|
||||
@ -3656,8 +3659,8 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||
// Immediate.
|
||||
if (Operand->isImm()) {
|
||||
AsmStrRewrites.push_back(AsmRewrite(AOK_Imm,
|
||||
Operand->getStartLoc(),
|
||||
Operand->getNameLen()));
|
||||
Operand->getStartLoc(),
|
||||
Operand->getNameLen()));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3680,26 +3683,33 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||
Size);
|
||||
if (OpDecl) {
|
||||
bool isOutput = (i == 1) && Desc.mayStore();
|
||||
if (Operand->needSizeDirective())
|
||||
if (Operand->needSizeDirective() && !Operand->isOffsetOf())
|
||||
AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective,
|
||||
Operand->getStartLoc(), 0,
|
||||
Operand->getMemSize()));
|
||||
|
||||
Operand->getStartLoc(), 0,
|
||||
Operand->getMemSize()));
|
||||
|
||||
// Don't emit the offset directive.
|
||||
if (Operand->isOffsetOf())
|
||||
AsmStrRewrites.push_back(AsmRewrite(AOK_Skip,
|
||||
Operand->getOffsetOfLoc(), 7));
|
||||
|
||||
if (isOutput) {
|
||||
std::string Constraint = "=";
|
||||
++InputIdx;
|
||||
OutputDecls.push_back(OpDecl);
|
||||
OutputDeclsOffsetOf.push_back(Operand->isOffsetOf());
|
||||
Constraint += Operand->getConstraint().str();
|
||||
OutputConstraints.push_back(Constraint);
|
||||
AsmStrRewrites.push_back(AsmRewrite(AOK_Output,
|
||||
Operand->getStartLoc(),
|
||||
Operand->getNameLen()));
|
||||
Operand->getStartLoc(),
|
||||
Operand->getNameLen()));
|
||||
} else {
|
||||
InputDecls.push_back(OpDecl);
|
||||
InputDeclsOffsetOf.push_back(Operand->isOffsetOf());
|
||||
InputConstraints.push_back(Operand->getConstraint().str());
|
||||
AsmStrRewrites.push_back(AsmRewrite(AOK_Input,
|
||||
Operand->getStartLoc(),
|
||||
Operand->getNameLen()));
|
||||
Operand->getStartLoc(),
|
||||
Operand->getNameLen()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3720,13 +3730,15 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||
unsigned NumExprs = NumOutputs + NumInputs;
|
||||
OpDecls.resize(NumExprs);
|
||||
Constraints.resize(NumExprs);
|
||||
// FIXME: Constraints are hard coded to 'm', but we need an 'r'
|
||||
// constraint for offsetof. This needs to be cleaned up!
|
||||
for (unsigned i = 0; i < NumOutputs; ++i) {
|
||||
OpDecls[i] = OutputDecls[i];
|
||||
Constraints[i] = OutputConstraints[i];
|
||||
OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsOffsetOf[i]);
|
||||
Constraints[i] = OutputDeclsOffsetOf[i] ? "=r" : OutputConstraints[i];
|
||||
}
|
||||
for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
|
||||
OpDecls[j] = InputDecls[i];
|
||||
Constraints[j] = InputConstraints[i];
|
||||
OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsOffsetOf[i]);
|
||||
Constraints[j] = InputDeclsOffsetOf[i] ? "r" : InputConstraints[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -3747,8 +3759,15 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
||||
OS << StringRef(Start, Loc - Start);
|
||||
PrevKind = Kind;
|
||||
|
||||
// Skip the original expression.
|
||||
if (Kind == AOK_Skip) {
|
||||
Start = Loc + (*I).Len;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Rewrite expressions in $N notation.
|
||||
switch (Kind) {
|
||||
default: break;
|
||||
case AOK_Imm:
|
||||
OS << Twine("$$") + StringRef(Loc, (*I).Len);
|
||||
break;
|
||||
|
@ -159,6 +159,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
} Kind;
|
||||
|
||||
SMLoc StartLoc, EndLoc;
|
||||
SMLoc OffsetOfLoc;
|
||||
|
||||
union {
|
||||
struct {
|
||||
@ -196,6 +197,8 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
/// getLocRange - Get the range between the first and last token of this
|
||||
/// operand.
|
||||
SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
|
||||
/// getOffsetOfLoc - Get the location of the offset operator.
|
||||
SMLoc getOffsetOfLoc() const { return OffsetOfLoc; }
|
||||
|
||||
virtual void print(raw_ostream &OS) const {}
|
||||
|
||||
@ -469,8 +472,9 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
|
||||
/// Create an absolute memory operand.
|
||||
static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
|
||||
SMLoc EndLoc, unsigned Size = 0,
|
||||
bool OffsetOf = false, bool NeedSizeDir = false){
|
||||
SMLoc EndLoc, SMLoc OffsetOfLoc = SMLoc(),
|
||||
unsigned Size = 0, bool OffsetOf = false,
|
||||
bool NeedSizeDir = false){
|
||||
X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
|
||||
Res->Mem.SegReg = 0;
|
||||
Res->Mem.Disp = Disp;
|
||||
@ -479,6 +483,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
Res->Mem.Scale = 1;
|
||||
Res->Mem.Size = Size;
|
||||
Res->Mem.OffsetOf = OffsetOf;
|
||||
Res->OffsetOfLoc = OffsetOfLoc;
|
||||
Res->Mem.NeedSizeDir = NeedSizeDir;
|
||||
return Res;
|
||||
}
|
||||
@ -487,8 +492,8 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
|
||||
unsigned BaseReg, unsigned IndexReg,
|
||||
unsigned Scale, SMLoc StartLoc, SMLoc EndLoc,
|
||||
unsigned Size = 0, bool OffsetOf = false,
|
||||
bool NeedSizeDir = false) {
|
||||
SMLoc OffsetOfLoc = SMLoc(), unsigned Size = 0,
|
||||
bool OffsetOf = false, bool NeedSizeDir = false){
|
||||
// We should never just have a displacement, that should be parsed as an
|
||||
// absolute memory operand.
|
||||
assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
|
||||
@ -504,6 +509,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
||||
Res->Mem.Scale = Scale;
|
||||
Res->Mem.Size = Size;
|
||||
Res->Mem.OffsetOf = OffsetOf;
|
||||
Res->OffsetOfLoc = OffsetOfLoc;
|
||||
Res->Mem.NeedSizeDir = NeedSizeDir;
|
||||
return Res;
|
||||
}
|
||||
@ -661,7 +667,7 @@ static unsigned getIntelMemOperandSize(StringRef OpStr) {
|
||||
X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
|
||||
unsigned Size) {
|
||||
unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
|
||||
SMLoc Start = Parser.getTok().getLoc(), End;
|
||||
SMLoc Start = Parser.getTok().getLoc(), End, OffsetOfLoc;
|
||||
|
||||
const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
|
||||
// Parse [ BaseReg + Scale*IndexReg + Disp ] or [ symbol ]
|
||||
@ -679,7 +685,7 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
|
||||
if (getLexer().isNot(AsmToken::RBrac))
|
||||
return ErrorOperand(Start, "Expected ']' token!");
|
||||
Parser.Lex();
|
||||
return X86Operand::CreateMem(Disp, Start, End, Size);
|
||||
return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size);
|
||||
}
|
||||
} else if (getLexer().is(AsmToken::Integer)) {
|
||||
int64_t Val = Parser.getTok().getIntVal();
|
||||
@ -691,8 +697,8 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
|
||||
const MCExpr *Disp = MCConstantExpr::Create(Val, getContext());
|
||||
if (SegReg)
|
||||
return X86Operand::CreateMem(SegReg, Disp, 0, 0, Scale,
|
||||
Start, End, Size);
|
||||
return X86Operand::CreateMem(Disp, Start, End, Size);
|
||||
Start, End, OffsetOfLoc, Size);
|
||||
return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size);
|
||||
} else if (getLexer().is(AsmToken::Star)) {
|
||||
// Handle '[' Scale*IndexReg ']'
|
||||
Parser.Lex();
|
||||
@ -742,16 +748,16 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
|
||||
|
||||
// handle [-42]
|
||||
if (!BaseReg && !IndexReg)
|
||||
return X86Operand::CreateMem(Disp, Start, End, Size);
|
||||
return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size);
|
||||
|
||||
return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
|
||||
Start, End, Size);
|
||||
Start, End, OffsetOfLoc, Size);
|
||||
}
|
||||
|
||||
/// ParseIntelMemOperand - Parse intel style memory operand.
|
||||
X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
|
||||
const AsmToken &Tok = Parser.getTok();
|
||||
SMLoc End;
|
||||
SMLoc End, OffsetOfLoc;
|
||||
|
||||
unsigned Size = getIntelMemOperandSize(Tok.getString());
|
||||
if (Size) {
|
||||
@ -767,6 +773,7 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
|
||||
if(isParsingInlineAsm() && (Tok.getString() == "offset" ||
|
||||
Tok.getString() == "OFFSET")) {
|
||||
OffsetOf = true;
|
||||
OffsetOfLoc = Parser.getTok().getLoc();
|
||||
Parser.Lex(); // Eat offset.
|
||||
}
|
||||
|
||||
@ -801,7 +808,8 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
|
||||
NeedSizeDir = Size > 0;
|
||||
}
|
||||
}
|
||||
return X86Operand::CreateMem(Disp, Start, End, Size, OffsetOf, NeedSizeDir);
|
||||
return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size, OffsetOf,
|
||||
NeedSizeDir);
|
||||
}
|
||||
|
||||
X86Operand *X86AsmParser::ParseIntelOperand() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user