summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2014-01-30 22:20:41 +0000
committerDavid Woodhouse <dwmw2@infradead.org>2014-01-30 22:20:41 +0000
commit93f81d9b33bf5f01c113b1558962a5112b987092 (patch)
treef657e60d87fa49884d00e5c89594aead726a3863
parentfe7fa28084172f73aa0a29a65bf09152dc47a3ac (diff)
downloadllvm-93f81d9b33bf5f01c113b1558962a5112b987092.tar.gz
llvm-93f81d9b33bf5f01c113b1558962a5112b987092.tar.bz2
llvm-93f81d9b33bf5f01c113b1558962a5112b987092.tar.xz
[x86] Fix signed relocations for i64i32imm operands
These should end up (in ELF) as R_X86_64_32S relocs, not R_X86_64_32. Kill the horrid and incomplete special case and FIXME in EncodeInstruction() and set things up so it can infer the signedness from the ImmType just like it can the size and whether it's PC-relative. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200495 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/MCTargetDesc/X86BaseInfo.h27
-rw-r--r--lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp17
-rw-r--r--lib/Target/X86/X86InstrArithmetic.td18
-rw-r--r--lib/Target/X86/X86InstrFormats.td62
-rw-r--r--lib/Target/X86/X86InstrInfo.td15
-rw-r--r--test/MC/X86/x86_64-signed-reloc.s16
6 files changed, 100 insertions, 55 deletions
diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index 49d8b11658..c085f14781 100644
--- a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -395,20 +395,21 @@ namespace X86II {
// This three-bit field describes the size of an immediate operand. Zero is
// unused so that we can tell if we forgot to set a value.
ImmShift = REXShift + 1,
- ImmMask = 7 << ImmShift,
+ ImmMask = 15 << ImmShift,
Imm8 = 1 << ImmShift,
Imm8PCRel = 2 << ImmShift,
Imm16 = 3 << ImmShift,
Imm16PCRel = 4 << ImmShift,
Imm32 = 5 << ImmShift,
Imm32PCRel = 6 << ImmShift,
- Imm64 = 7 << ImmShift,
+ Imm32S = 7 << ImmShift,
+ Imm64 = 8 << ImmShift,
//===------------------------------------------------------------------===//
// FP Instruction Classification... Zero is non-fp instruction.
// FPTypeMask - Mask for all of the FP types...
- FPTypeShift = ImmShift + 3,
+ FPTypeShift = ImmShift + 4,
FPTypeMask = 7 << FPTypeShift,
// NotFP - The default, set for instructions that do not use FP registers.
@@ -557,6 +558,7 @@ namespace X86II {
case X86II::Imm16:
case X86II::Imm16PCRel: return 2;
case X86II::Imm32:
+ case X86II::Imm32S:
case X86II::Imm32PCRel: return 4;
case X86II::Imm64: return 8;
}
@@ -574,6 +576,25 @@ namespace X86II {
case X86II::Imm8:
case X86II::Imm16:
case X86II::Imm32:
+ case X86II::Imm32S:
+ case X86II::Imm64:
+ return false;
+ }
+ }
+
+ /// isImmSigned - Return true if the immediate of the specified instruction's
+ /// TSFlags indicates that it is signed.
+ inline unsigned isImmSigned(uint64_t TSFlags) {
+ switch (TSFlags & X86II::ImmMask) {
+ default: llvm_unreachable("Unknown immediate signedness");
+ case X86II::Imm32S:
+ return true;
+ case X86II::Imm8:
+ case X86II::Imm8PCRel:
+ case X86II::Imm16:
+ case X86II::Imm16PCRel:
+ case X86II::Imm32:
+ case X86II::Imm32PCRel:
case X86II::Imm64:
return false;
}
diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 1c6a0b2da6..52d6d14a8f 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -233,6 +233,12 @@ static MCFixupKind getImmFixupKind(uint64_t TSFlags) {
unsigned Size = X86II::getSizeOfImm(TSFlags);
bool isPCRel = X86II::isImmPCRel(TSFlags);
+ if (X86II::isImmSigned(TSFlags)) {
+ switch (Size) {
+ default: llvm_unreachable("Unsupported signed fixup size!");
+ case 4: return MCFixupKind(X86::reloc_signed_4byte);
+ }
+ }
return MCFixup::getKindForSize(Size, isPCRel);
}
@@ -1566,17 +1572,8 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
EmitImmediate(MCOperand::CreateImm(RegNum), MI.getLoc(), 1, FK_Data_1,
CurByte, OS, Fixups);
} else {
- unsigned FixupKind;
- // FIXME: Is there a better way to know that we need a signed relocation?
- if (MI.getOpcode() == X86::ADD64ri32 ||
- MI.getOpcode() == X86::MOV64ri32 ||
- MI.getOpcode() == X86::MOV64mi32 ||
- MI.getOpcode() == X86::PUSH64i32)
- FixupKind = X86::reloc_signed_4byte;
- else
- FixupKind = getImmFixupKind(TSFlags);
EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(),
- X86II::getSizeOfImm(TSFlags), MCFixupKind(FixupKind),
+ X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags),
CurByte, OS, Fixups);
}
}
diff --git a/lib/Target/X86/X86InstrArithmetic.td b/lib/Target/X86/X86InstrArithmetic.td
index 184e1ce418..cbc00abaf3 100644
--- a/lib/Target/X86/X86InstrArithmetic.td
+++ b/lib/Target/X86/X86InstrArithmetic.td
@@ -229,10 +229,10 @@ def IMUL32rri8 : Ii8<0x6B, MRMSrcReg, // GR32 = GR32*I8
[(set GR32:$dst, EFLAGS,
(X86smul_flag GR32:$src1, i32immSExt8:$src2))],
IIC_IMUL32_RRI>, OpSize16;
-def IMUL64rri32 : RIi32<0x69, MRMSrcReg, // GR64 = GR64*I32
- (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2),
- "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set GR64:$dst, EFLAGS,
+def IMUL64rri32 : RIi32S<0x69, MRMSrcReg, // GR64 = GR64*I32
+ (outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2),
+ "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set GR64:$dst, EFLAGS,
(X86smul_flag GR64:$src1, i64immSExt32:$src2))],
IIC_IMUL64_RRI>;
def IMUL64rri8 : RIi8<0x6B, MRMSrcReg, // GR64 = GR64*I8
@@ -272,10 +272,10 @@ def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // GR32 = [mem32]*I8
(X86smul_flag (load addr:$src1),
i32immSExt8:$src2))],
IIC_IMUL32_RMI>, OpSize16;
-def IMUL64rmi32 : RIi32<0x69, MRMSrcMem, // GR64 = [mem64]*I32
- (outs GR64:$dst), (ins i64mem:$src1, i64i32imm:$src2),
- "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
- [(set GR64:$dst, EFLAGS,
+def IMUL64rmi32 : RIi32S<0x69, MRMSrcMem, // GR64 = [mem64]*I32
+ (outs GR64:$dst), (ins i64mem:$src1, i64i32imm:$src2),
+ "imul{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set GR64:$dst, EFLAGS,
(X86smul_flag (load addr:$src1),
i64immSExt32:$src2))],
IIC_IMUL64_RMI>;
@@ -681,7 +681,7 @@ def Xi32 : X86TypeInfo<i32, "l", GR32, loadi32, i32mem,
Imm32, i32imm, imm, i32i8imm, i32immSExt8,
1, 0, 1, 0>;
def Xi64 : X86TypeInfo<i64, "q", GR64, loadi64, i64mem,
- Imm32, i64i32imm, i64immSExt32, i64i8imm, i64immSExt8,
+ Imm32S, i64i32imm, i64immSExt32, i64i8imm, i64immSExt8,
1, 0, 0, 1>;
/// ITy - This instruction base class takes the type info for the instruction.
diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td
index adc24e2318..ded1d90337 100644
--- a/lib/Target/X86/X86InstrFormats.td
+++ b/lib/Target/X86/X86InstrFormats.td
@@ -61,8 +61,8 @@ def MRM_DF : Format<59>;
// ImmType - This specifies the immediate type used by an instruction. This is
// part of the ad-hoc solution used to emit machine instruction encodings by our
// machine code emitter.
-class ImmType<bits<3> val> {
- bits<3> Value = val;
+class ImmType<bits<4> val> {
+ bits<4> Value = val;
}
def NoImm : ImmType<0>;
def Imm8 : ImmType<1>;
@@ -71,7 +71,8 @@ def Imm16 : ImmType<3>;
def Imm16PCRel : ImmType<4>;
def Imm32 : ImmType<5>;
def Imm32PCRel : ImmType<6>;
-def Imm64 : ImmType<7>;
+def Imm32S : ImmType<7>;
+def Imm64 : ImmType<8>;
// FPFormat - This specifies what form this FP instruction has. This is used by
// the Floating-Point stackifier pass.
@@ -232,29 +233,29 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
let TSFlags{8} = hasAdSizePrefix;
let TSFlags{13-9} = Prefix;
let TSFlags{14} = hasREX_WPrefix;
- let TSFlags{17-15} = ImmT.Value;
- let TSFlags{20-18} = FPForm.Value;
- let TSFlags{21} = hasLockPrefix;
- let TSFlags{23-22} = ExeDomain.Value;
- let TSFlags{31-24} = Opcode;
- let TSFlags{32} = hasVEXPrefix;
- let TSFlags{33} = hasVEX_WPrefix;
- let TSFlags{34} = hasVEX_4VPrefix;
- let TSFlags{35} = hasVEX_4VOp3Prefix;
- let TSFlags{36} = hasVEX_i8ImmReg;
- let TSFlags{37} = hasVEX_L;
- let TSFlags{38} = ignoresVEX_L;
- let TSFlags{39} = hasEVEXPrefix;
- let TSFlags{40} = hasEVEX_K;
- let TSFlags{41} = hasEVEX_Z;
- let TSFlags{42} = hasEVEX_L2;
- let TSFlags{43} = hasEVEX_B;
- let TSFlags{45-44} = EVEX_CD8E;
- let TSFlags{48-46} = EVEX_CD8V;
- let TSFlags{49} = has3DNow0F0FOpcode;
- let TSFlags{50} = hasMemOp4Prefix;
- let TSFlags{51} = hasXOP_Prefix;
- let TSFlags{52} = hasEVEX_RC;
+ let TSFlags{18-15} = ImmT.Value;
+ let TSFlags{21-19} = FPForm.Value;
+ let TSFlags{22} = hasLockPrefix;
+ let TSFlags{24-23} = ExeDomain.Value;
+ let TSFlags{32-25} = Opcode;
+ let TSFlags{33} = hasVEXPrefix;
+ let TSFlags{34} = hasVEX_WPrefix;
+ let TSFlags{35} = hasVEX_4VPrefix;
+ let TSFlags{36} = hasVEX_4VOp3Prefix;
+ let TSFlags{37} = hasVEX_i8ImmReg;
+ let TSFlags{38} = hasVEX_L;
+ let TSFlags{39} = ignoresVEX_L;
+ let TSFlags{40} = hasEVEXPrefix;
+ let TSFlags{41} = hasEVEX_K;
+ let TSFlags{42} = hasEVEX_Z;
+ let TSFlags{43} = hasEVEX_L2;
+ let TSFlags{44} = hasEVEX_B;
+ let TSFlags{46-45} = EVEX_CD8E;
+ let TSFlags{49-47} = EVEX_CD8V;
+ let TSFlags{50} = has3DNow0F0FOpcode;
+ let TSFlags{51} = hasMemOp4Prefix;
+ let TSFlags{52} = hasXOP_Prefix;
+ let TSFlags{53} = hasEVEX_RC;
}
class PseudoI<dag oops, dag iops, list<dag> pattern>
@@ -294,6 +295,12 @@ class Ii32<bits<8> o, Format f, dag outs, dag ins, string asm,
let Pattern = pattern;
let CodeSize = 3;
}
+class Ii32S<bits<8> o, Format f, dag outs, dag ins, string asm,
+ list<dag> pattern, InstrItinClass itin = NoItinerary>
+ : X86Inst<o, f, Imm32S, outs, ins, asm, itin> {
+ let Pattern = pattern;
+ let CodeSize = 3;
+}
class Ii16PCRel<bits<8> o, Format f, dag outs, dag ins, string asm,
list<dag> pattern, InstrItinClass itin = NoItinerary>
@@ -743,6 +750,9 @@ class RIi16 <bits<8> o, Format F, dag outs, dag ins, string asm,
class RIi32 <bits<8> o, Format F, dag outs, dag ins, string asm,
list<dag> pattern, InstrItinClass itin = NoItinerary>
: Ii32<o, F, outs, ins, asm, pattern, itin>, REX_W;
+class RIi32S <bits<8> o, Format F, dag outs, dag ins, string asm,
+ list<dag> pattern, InstrItinClass itin = NoItinerary>
+ : Ii32S<o, F, outs, ins, asm, pattern, itin>, REX_W;
class RIi64<bits<8> o, Format f, dag outs, dag ins, string asm,
list<dag> pattern, InstrItinClass itin = NoItinerary>
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 2885bb54fc..35709133a2 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -1039,7 +1039,7 @@ def PUSH64i8 : Ii8<0x6a, RawFrm, (outs), (ins i64i8imm:$imm),
def PUSH64i16 : Ii16<0x68, RawFrm, (outs), (ins i16imm:$imm),
"push{w}\t$imm", [], IIC_PUSH_IMM>, OpSize,
Requires<[In64BitMode]>;
-def PUSH64i32 : Ii32<0x68, RawFrm, (outs), (ins i64i32imm:$imm),
+def PUSH64i32 : Ii32S<0x68, RawFrm, (outs), (ins i64i32imm:$imm),
"push{q}\t$imm", [], IIC_PUSH_IMM>, Requires<[In64BitMode]>;
}
@@ -1208,9 +1208,9 @@ def MOV32ri : Ii32<0xB8, AddRegFrm, (outs GR32:$dst), (ins i32imm:$src),
def MOV64ri : RIi64<0xB8, AddRegFrm, (outs GR64:$dst), (ins i64imm:$src),
"movabs{q}\t{$src, $dst|$dst, $src}",
[(set GR64:$dst, imm:$src)], IIC_MOV>;
-def MOV64ri32 : RIi32<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src),
- "mov{q}\t{$src, $dst|$dst, $src}",
- [(set GR64:$dst, i64immSExt32:$src)], IIC_MOV>;
+def MOV64ri32 : RIi32S<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src),
+ "mov{q}\t{$src, $dst|$dst, $src}",
+ [(set GR64:$dst, i64immSExt32:$src)], IIC_MOV>;
}
} // SchedRW
@@ -1224,9 +1224,9 @@ def MOV16mi : Ii16<0xC7, MRM0m, (outs), (ins i16mem:$dst, i16imm:$src),
def MOV32mi : Ii32<0xC7, MRM0m, (outs), (ins i32mem:$dst, i32imm:$src),
"mov{l}\t{$src, $dst|$dst, $src}",
[(store (i32 imm:$src), addr:$dst)], IIC_MOV_MEM>, OpSize16;
-def MOV64mi32 : RIi32<0xC7, MRM0m, (outs), (ins i64mem:$dst, i64i32imm:$src),
- "mov{q}\t{$src, $dst|$dst, $src}",
- [(store i64immSExt32:$src, addr:$dst)], IIC_MOV_MEM>;
+def MOV64mi32 : RIi32S<0xC7, MRM0m, (outs), (ins i64mem:$dst, i64i32imm:$src),
+ "mov{q}\t{$src, $dst|$dst, $src}",
+ [(store i64immSExt32:$src, addr:$dst)], IIC_MOV_MEM>;
} // SchedRW
let hasSideEffects = 0 in {
@@ -2100,6 +2100,7 @@ multiclass tbm_ternary_imm_intr<bits<8> opc, RegisterClass RC, string OpcodeStr,
defm BEXTRI32 : tbm_ternary_imm_intr<0x10, GR32, "bextr", i32mem, loadi32,
int_x86_tbm_bextri_u32, i32imm, imm>;
+let ImmT = Imm32S in
defm BEXTRI64 : tbm_ternary_imm_intr<0x10, GR64, "bextr", i64mem, loadi64,
int_x86_tbm_bextri_u64, i64i32imm,
i64immSExt32>, VEX_W;
diff --git a/test/MC/X86/x86_64-signed-reloc.s b/test/MC/X86/x86_64-signed-reloc.s
new file mode 100644
index 0000000000..e8a2720df1
--- /dev/null
+++ b/test/MC/X86/x86_64-signed-reloc.s
@@ -0,0 +1,16 @@
+// RUN: llvm-mc -triple x86_64-linux-gnu -filetype=obj %s | llvm-readobj -r | FileCheck %s
+
+
+ // CHECK: Relocations [
+ // CHECK-NEXT: Section ({{[0-9]+}}) .rela.text {
+
+pushq $foo // CHECK-NEXT: R_X86_64_32S
+addq $foo, %rax // CHECK-NEXT: R_X86_64_32S
+andq $foo, %rax // CHECK-NEXT: R_X86_64_32S
+movq $foo, %rax // CHECK-NEXT: R_X86_64_32S
+bextr $foo, (%edi), %eax // CHECK-NEXT: R_X86_64_32
+bextr $foo, (%rdi), %rax // CHECK-NEXT: R_X86_64_32S
+imul $foo, %rax // CHECK-NEXT: R_X86_64_32S
+
+ // CHECK-NEXT: }
+ // CHECK-NEXT: ]