aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-01-30 01:02:48 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-01-30 01:02:48 +0000
commitb834f5d13d824dc4da2ce0df2aa8dffb697b8974 (patch)
treea6f35042b4ea7e7b7ff4c92a573391867796695b
parenta2f5e00347641d1b46ce4f65bf9378fecce9be14 (diff)
MC/X86 AsmParser: Handle absolute memory operands correctly. We were doing
something totally broken and parsing them as immediates, but the .td file also had the wrong match class so things sortof worked. Except, that is, that we would parse movl $0, %eax as movl 0, %eax Feel free to guess how well that worked. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94869 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/AsmParser/X86AsmParser.cpp32
-rw-r--r--lib/Target/X86/X86InstrInfo.td7
-rw-r--r--test/MC/AsmParser/X86/x86_instructions.s6
-rw-r--r--test/MC/AsmParser/labels.s2
4 files changed, 40 insertions, 7 deletions
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index cc4498b4d9..65e498117f 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -172,6 +172,11 @@ struct X86Operand : public MCParsedAsmOperand {
bool isMem() const { return Kind == Memory; }
+ bool isAbsMem() const {
+ return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
+ !getMemIndexReg() && !getMemScale();
+ }
+
bool isNoSegMem() const {
return Kind == Memory && !getMemSegReg();
}
@@ -196,7 +201,6 @@ struct X86Operand : public MCParsedAsmOperand {
void addMemOperands(MCInst &Inst, unsigned N) const {
assert((N == 5) && "Invalid number of operands!");
-
Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
Inst.addOperand(MCOperand::CreateImm(getMemScale()));
Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
@@ -204,9 +208,13 @@ struct X86Operand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
}
+ void addAbsMemOperands(MCInst &Inst, unsigned N) const {
+ assert((N == 1) && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
+ }
+
void addNoSegMemOperands(MCInst &Inst, unsigned N) const {
assert((N == 4) && "Invalid number of operands!");
-
Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
Inst.addOperand(MCOperand::CreateImm(getMemScale()));
Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
@@ -232,10 +240,24 @@ struct X86Operand : public MCParsedAsmOperand {
return Res;
}
+ /// Create an absolute memory operand.
+ static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
+ SMLoc EndLoc) {
+ X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
+ Res->Mem.SegReg = 0;
+ Res->Mem.Disp = Disp;
+ Res->Mem.BaseReg = 0;
+ Res->Mem.IndexReg = 0;
+ Res->Mem.Scale = 0;
+ return Res;
+ }
+
+ /// Create a generalized memory operand.
static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
unsigned BaseReg, unsigned IndexReg,
unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
- // We should never just have a displacement, that would be an immediate.
+ // We should never just have a displacement, that should be parsed as an
+ // absolute memory operand.
assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
// The scale should always be one of {1,2,4,8}.
@@ -322,7 +344,7 @@ X86Operand *X86ATTAsmParser::ParseMemOperand() {
if (getLexer().isNot(AsmToken::LParen)) {
// Unless we have a segment register, treat this as an immediate.
if (SegReg == 0)
- return X86Operand::CreateImm(Disp, MemStart, ExprEnd);
+ return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
}
@@ -349,7 +371,7 @@ X86Operand *X86ATTAsmParser::ParseMemOperand() {
if (getLexer().isNot(AsmToken::LParen)) {
// Unless we have a segment register, treat this as an immediate.
if (SegReg == 0)
- return X86Operand::CreateImm(Disp, LParenLoc, ExprEnd);
+ return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
}
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 5041263a61..b6f9e162db 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -192,6 +192,10 @@ def X86MemAsmOperand : AsmOperandClass {
let Name = "Mem";
let SuperClass = ?;
}
+def X86AbsMemAsmOperand : AsmOperandClass {
+ let Name = "AbsMem";
+ let SuperClass = X86MemAsmOperand;
+}
def X86NoSegMemAsmOperand : AsmOperandClass {
let Name = "NoSegMem";
let SuperClass = X86MemAsmOperand;
@@ -233,7 +237,8 @@ def lea32mem : Operand<i32> {
let ParserMatchClass = X86NoSegMemAsmOperand;
}
-let PrintMethod = "print_pcrel_imm" in {
+let ParserMatchClass = X86AbsMemAsmOperand,
+ PrintMethod = "print_pcrel_imm" in {
def i32imm_pcrel : Operand<i32>;
def offset8 : Operand<i64>;
diff --git a/test/MC/AsmParser/X86/x86_instructions.s b/test/MC/AsmParser/X86/x86_instructions.s
index ed806ee734..314fc1add1 100644
--- a/test/MC/AsmParser/X86/x86_instructions.s
+++ b/test/MC/AsmParser/X86/x86_instructions.s
@@ -16,6 +16,12 @@
movl %eax, 10(%ebp, %ebx, 4)
// CHECK: movl %eax, 10(,%ebx,4)
movl %eax, 10(, %ebx, 4)
+
+// CHECK: movl 0, %eax
+ movl 0, %eax
+// CHECK: movl $0, %eax
+ movl $0, %eax
+
// CHECK: ret
ret
diff --git a/test/MC/AsmParser/labels.s b/test/MC/AsmParser/labels.s
index 456d61f060..3bc7e630ce 100644
--- a/test/MC/AsmParser/labels.s
+++ b/test/MC/AsmParser/labels.s
@@ -21,7 +21,7 @@ foo:
// CHECK: b$c = 10
"b$c" = 10
// CHECK: addl $10, %eax
- addl "b$c", %eax
+ addl $"b$c", %eax
// CHECK: "a 0" = 11
.set "a 0", 11