mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-22 19:38:40 +00:00
[ms-inline asm] Create a register operand, rather than a memory operand when we
see the offsetof operator. Previously, we were matching something like MOVrm in the front-end and later matching MOVrr in the back-end. This change makes things more consistent. It also fixes cases where we can't match against a memory operand as the source (test cases coming). Part of rdar://12470317 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166592 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2f87640b86
commit
c0a14b86f7
@ -3665,7 +3665,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register operand.
|
// Register operand.
|
||||||
if (Operand->isReg()) {
|
if (Operand->isReg() && !Operand->isOffsetOf()) {
|
||||||
unsigned NumDefs = Desc.getNumDefs();
|
unsigned NumDefs = Desc.getNumDefs();
|
||||||
// Clobber.
|
// Clobber.
|
||||||
if (NumDefs && Operand->getMCOperandNum() < NumDefs) {
|
if (NumDefs && Operand->getMCOperandNum() < NumDefs) {
|
||||||
@ -3683,7 +3683,7 @@ 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() && !Operand->isOffsetOf())
|
if (!Operand->isOffsetOf() && Operand->needSizeDirective())
|
||||||
AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective,
|
AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective,
|
||||||
Operand->getStartLoc(), 0,
|
Operand->getStartLoc(), 0,
|
||||||
Operand->getMemSize()));
|
Operand->getMemSize()));
|
||||||
|
@ -54,6 +54,7 @@ private:
|
|||||||
X86Operand *ParseOperand();
|
X86Operand *ParseOperand();
|
||||||
X86Operand *ParseATTOperand();
|
X86Operand *ParseATTOperand();
|
||||||
X86Operand *ParseIntelOperand();
|
X86Operand *ParseIntelOperand();
|
||||||
|
X86Operand *ParseIntelOffsetOfOperator(SMLoc StartLoc);
|
||||||
X86Operand *ParseIntelMemOperand(unsigned SegReg, SMLoc StartLoc);
|
X86Operand *ParseIntelMemOperand(unsigned SegReg, SMLoc StartLoc);
|
||||||
X86Operand *ParseIntelBracExpression(unsigned SegReg, unsigned Size);
|
X86Operand *ParseIntelBracExpression(unsigned SegReg, unsigned Size);
|
||||||
X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
|
X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
|
||||||
@ -182,7 +183,6 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
unsigned IndexReg;
|
unsigned IndexReg;
|
||||||
unsigned Scale;
|
unsigned Scale;
|
||||||
unsigned Size;
|
unsigned Size;
|
||||||
bool OffsetOf;
|
|
||||||
bool NeedSizeDir;
|
bool NeedSizeDir;
|
||||||
} Mem;
|
} Mem;
|
||||||
};
|
};
|
||||||
@ -324,8 +324,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isOffsetOf() const {
|
bool isOffsetOf() const {
|
||||||
assert(Kind == Memory && "Invalid access!");
|
return OffsetOfLoc.getPointer();
|
||||||
return Mem.OffsetOf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needSizeDirective() const {
|
bool needSizeDirective() const {
|
||||||
@ -458,9 +457,11 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
|
static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
|
||||||
|
SMLoc OffsetOfLoc = SMLoc()) {
|
||||||
X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
|
X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
|
||||||
Res->Reg.RegNo = RegNo;
|
Res->Reg.RegNo = RegNo;
|
||||||
|
Res->OffsetOfLoc = OffsetOfLoc;
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,8 +473,7 @@ 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, SMLoc OffsetOfLoc = SMLoc(),
|
SMLoc EndLoc, unsigned Size = 0,
|
||||||
unsigned Size = 0, bool OffsetOf = false,
|
|
||||||
bool NeedSizeDir = false){
|
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;
|
||||||
@ -482,8 +482,6 @@ 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.OffsetOf = OffsetOf;
|
|
||||||
Res->OffsetOfLoc = OffsetOfLoc;
|
|
||||||
Res->Mem.NeedSizeDir = NeedSizeDir;
|
Res->Mem.NeedSizeDir = NeedSizeDir;
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
@ -492,8 +490,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,
|
||||||
SMLoc OffsetOfLoc = SMLoc(), unsigned Size = 0,
|
unsigned Size = 0, bool NeedSizeDir = false) {
|
||||||
bool OffsetOf = false, 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!");
|
||||||
@ -508,8 +505,6 @@ 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.OffsetOf = OffsetOf;
|
|
||||||
Res->OffsetOfLoc = OffsetOfLoc;
|
|
||||||
Res->Mem.NeedSizeDir = NeedSizeDir;
|
Res->Mem.NeedSizeDir = NeedSizeDir;
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
@ -667,7 +662,7 @@ static unsigned getIntelMemOperandSize(StringRef OpStr) {
|
|||||||
X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
|
X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
|
||||||
unsigned Size) {
|
unsigned Size) {
|
||||||
unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
|
unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
|
||||||
SMLoc Start = Parser.getTok().getLoc(), End, OffsetOfLoc;
|
SMLoc Start = Parser.getTok().getLoc(), End;
|
||||||
|
|
||||||
const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
|
const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
|
||||||
// Parse [ BaseReg + Scale*IndexReg + Disp ] or [ symbol ]
|
// Parse [ BaseReg + Scale*IndexReg + Disp ] or [ symbol ]
|
||||||
@ -685,7 +680,7 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
|
|||||||
if (getLexer().isNot(AsmToken::RBrac))
|
if (getLexer().isNot(AsmToken::RBrac))
|
||||||
return ErrorOperand(Start, "Expected ']' token!");
|
return ErrorOperand(Start, "Expected ']' token!");
|
||||||
Parser.Lex();
|
Parser.Lex();
|
||||||
return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size);
|
return X86Operand::CreateMem(Disp, Start, End, Size);
|
||||||
}
|
}
|
||||||
} else if (getLexer().is(AsmToken::Integer)) {
|
} else if (getLexer().is(AsmToken::Integer)) {
|
||||||
int64_t Val = Parser.getTok().getIntVal();
|
int64_t Val = Parser.getTok().getIntVal();
|
||||||
@ -697,8 +692,8 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
|
|||||||
const MCExpr *Disp = MCConstantExpr::Create(Val, getContext());
|
const MCExpr *Disp = MCConstantExpr::Create(Val, getContext());
|
||||||
if (SegReg)
|
if (SegReg)
|
||||||
return X86Operand::CreateMem(SegReg, Disp, 0, 0, Scale,
|
return X86Operand::CreateMem(SegReg, Disp, 0, 0, Scale,
|
||||||
Start, End, OffsetOfLoc, Size);
|
Start, End, Size);
|
||||||
return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size);
|
return X86Operand::CreateMem(Disp, Start, End, Size);
|
||||||
} else if (getLexer().is(AsmToken::Star)) {
|
} else if (getLexer().is(AsmToken::Star)) {
|
||||||
// Handle '[' Scale*IndexReg ']'
|
// Handle '[' Scale*IndexReg ']'
|
||||||
Parser.Lex();
|
Parser.Lex();
|
||||||
@ -748,16 +743,16 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
|
|||||||
|
|
||||||
// handle [-42]
|
// handle [-42]
|
||||||
if (!BaseReg && !IndexReg)
|
if (!BaseReg && !IndexReg)
|
||||||
return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size);
|
return X86Operand::CreateMem(Disp, Start, End, Size);
|
||||||
|
|
||||||
return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
|
return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
|
||||||
Start, End, OffsetOfLoc, Size);
|
Start, End, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseIntelMemOperand - Parse intel style memory operand.
|
/// ParseIntelMemOperand - Parse intel style memory operand.
|
||||||
X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
|
X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
|
||||||
const AsmToken &Tok = Parser.getTok();
|
const AsmToken &Tok = Parser.getTok();
|
||||||
SMLoc End, OffsetOfLoc;
|
SMLoc End;
|
||||||
|
|
||||||
unsigned Size = getIntelMemOperandSize(Tok.getString());
|
unsigned Size = getIntelMemOperandSize(Tok.getString());
|
||||||
if (Size) {
|
if (Size) {
|
||||||
@ -767,27 +762,10 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
|
|||||||
Parser.Lex();
|
Parser.Lex();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the 'offset' operator. This operator is used to specify the
|
if (getLexer().is(AsmToken::LBrac))
|
||||||
// location rather then the content of a variable.
|
|
||||||
bool OffsetOf = false;
|
|
||||||
if(isParsingInlineAsm() && (Tok.getString() == "offset" ||
|
|
||||||
Tok.getString() == "OFFSET")) {
|
|
||||||
OffsetOf = true;
|
|
||||||
OffsetOfLoc = Parser.getTok().getLoc();
|
|
||||||
|
|
||||||
// Size is based on the size of a pointer, not the size of the variable.
|
|
||||||
assert (!Size && "Unexpected size!");
|
|
||||||
Size = is64BitMode() ? 64 : 32;
|
|
||||||
Parser.Lex(); // Eat offset.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getLexer().is(AsmToken::LBrac)) {
|
|
||||||
assert (!OffsetOf && "Unexpected offset operator!");
|
|
||||||
return ParseIntelBracExpression(SegReg, Size);
|
return ParseIntelBracExpression(SegReg, Size);
|
||||||
}
|
|
||||||
|
|
||||||
if (!ParseRegister(SegReg, Start, End)) {
|
if (!ParseRegister(SegReg, Start, End)) {
|
||||||
assert (!OffsetOf && "Unexpected offset operator!");
|
|
||||||
// Handel SegReg : [ ... ]
|
// Handel SegReg : [ ... ]
|
||||||
if (getLexer().isNot(AsmToken::Colon))
|
if (getLexer().isNot(AsmToken::Colon))
|
||||||
return ErrorOperand(Start, "Expected ':' token!");
|
return ErrorOperand(Start, "Expected ':' token!");
|
||||||
@ -813,19 +791,46 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isParsingInlineAsm())
|
if (!isParsingInlineAsm())
|
||||||
return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size);
|
return X86Operand::CreateMem(Disp, Start, End, Size);
|
||||||
else
|
else
|
||||||
// When parsing inline assembly we set the base register to a non-zero value
|
// When parsing inline assembly we set the base register to a non-zero value
|
||||||
// as we don't know the actual value at this time. This is necessary to
|
// as we don't know the actual value at this time. This is necessary to
|
||||||
// get the matching correct in some cases.
|
// get the matching correct in some cases.
|
||||||
return X86Operand::CreateMem(/*SegReg*/0, Disp, /*BaseReg*/1, /*IndexReg*/0,
|
return X86Operand::CreateMem(/*SegReg*/0, Disp, /*BaseReg*/1, /*IndexReg*/0,
|
||||||
/*Scale*/1, Start, End, OffsetOfLoc, Size,
|
/*Scale*/1, Start, End, Size, NeedSizeDir);
|
||||||
OffsetOf, NeedSizeDir);
|
}
|
||||||
|
|
||||||
|
/// Parse the 'offset' operator. This operator is used to specify the
|
||||||
|
/// location rather then the content of a variable.
|
||||||
|
X86Operand *X86AsmParser::ParseIntelOffsetOfOperator(SMLoc Start) {
|
||||||
|
SMLoc OffsetOfLoc = Start;
|
||||||
|
Parser.Lex(); // Eat offset.
|
||||||
|
Start = Parser.getTok().getLoc();
|
||||||
|
assert (Parser.getTok().is(AsmToken::Identifier) && "Expected an identifier");
|
||||||
|
|
||||||
|
SMLoc End;
|
||||||
|
const MCExpr *Val;
|
||||||
|
if (getParser().ParseExpression(Val, End))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
End = Parser.getTok().getLoc();
|
||||||
|
|
||||||
|
// The offset operator will have an 'r' constraint, thus we need to create
|
||||||
|
// register operand to ensure proper matching. Just pick a GPR based on
|
||||||
|
// the size of a pointer.
|
||||||
|
unsigned RegNo = is64BitMode() ? X86::RBX : X86::EBX;
|
||||||
|
return X86Operand::CreateReg(RegNo, Start, End, OffsetOfLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
X86Operand *X86AsmParser::ParseIntelOperand() {
|
X86Operand *X86AsmParser::ParseIntelOperand() {
|
||||||
SMLoc Start = Parser.getTok().getLoc(), End;
|
SMLoc Start = Parser.getTok().getLoc(), End;
|
||||||
|
|
||||||
|
// offset operator.
|
||||||
|
const AsmToken &Tok = Parser.getTok();
|
||||||
|
if ((Tok.getString() == "offset" || Tok.getString() == "OFFSET") &&
|
||||||
|
isParsingInlineAsm())
|
||||||
|
return ParseIntelOffsetOfOperator(Start);
|
||||||
|
|
||||||
// immediate.
|
// immediate.
|
||||||
if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Real) ||
|
if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Real) ||
|
||||||
getLexer().is(AsmToken::Minus)) {
|
getLexer().is(AsmToken::Minus)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user