[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:
Chad Rosier 2012-10-24 17:22:29 +00:00
parent 2f87640b86
commit c0a14b86f7
2 changed files with 47 additions and 42 deletions

View File

@ -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()));

View File

@ -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)) {