From 93f81d9b33bf5f01c113b1558962a5112b987092 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 30 Jan 2014 22:20:41 +0000 Subject: [PATCH] [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 --- lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 27 +++++++- .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 17 +++-- lib/Target/X86/X86InstrArithmetic.td | 18 +++--- lib/Target/X86/X86InstrFormats.td | 62 +++++++++++-------- lib/Target/X86/X86InstrInfo.td | 15 ++--- test/MC/X86/x86_64-signed-reloc.s | 16 +++++ 6 files changed, 100 insertions(+), 55 deletions(-) create mode 100644 test/MC/X86/x86_64-signed-reloc.s diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index 49d8b116581..c085f147814 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 1c6a0b2da6b..52d6d14a8f8 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 184e1ce4184..cbc00abaf36 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; def Xi64 : X86TypeInfo; /// 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 adc24e23182..ded1d903370 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 val> { - bits<3> Value = val; +class ImmType 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 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 pattern> @@ -294,6 +295,12 @@ class Ii32 o, Format f, dag outs, dag ins, string asm, let Pattern = pattern; let CodeSize = 3; } +class Ii32S o, Format f, dag outs, dag ins, string asm, + list pattern, InstrItinClass itin = NoItinerary> + : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} class Ii16PCRel o, Format f, dag outs, dag ins, string asm, list pattern, InstrItinClass itin = NoItinerary> @@ -743,6 +750,9 @@ class RIi16 o, Format F, dag outs, dag ins, string asm, class RIi32 o, Format F, dag outs, dag ins, string asm, list pattern, InstrItinClass itin = NoItinerary> : Ii32, REX_W; +class RIi32S o, Format F, dag outs, dag ins, string asm, + list pattern, InstrItinClass itin = NoItinerary> + : Ii32S, REX_W; class RIi64 o, Format f, dag outs, dag ins, string asm, list pattern, InstrItinClass itin = NoItinerary> diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 2885bb54fca..35709133a20 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 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 00000000000..e8a2720df1d --- /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: ] -- 2.34.1