summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason W Kim <jason.w.kim.2009@gmail.com>2011-02-04 19:47:15 +0000
committerJason W Kim <jason.w.kim.2009@gmail.com>2011-02-04 19:47:15 +0000
commit685c350ae76b588e1f00c01a511fe8bd57f18394 (patch)
tree928a83853f72ae7ac0064957ef996de0cd0fc886
parentcb6404711b7fe6f583480adce8d7e9d5e4b99ae6 (diff)
downloadllvm-685c350ae76b588e1f00c01a511fe8bd57f18394.tar.gz
llvm-685c350ae76b588e1f00c01a511fe8bd57f18394.tar.bz2
llvm-685c350ae76b588e1f00c01a511fe8bd57f18394.tar.xz
Teach ARM/MC/ELF to handle R_ARM_JUMP24 relocation type for conditional jumps.
(yes, this is different from R_ARM_CALL) - Adds a new method getARMBranchTargetOpValue() which handles the necessary distinction between the conditional and unconditional br/bl needed for ARM/ELF At least for ARM mode, the needed fixup for conditional versus unconditional br/bl is identical, but the ARM docs and existing ARM tools expect this reloc type... Added a few FIXME's for future naming fixups in ARMInstrInfo.td git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124895 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/MC/ELFObjectWriter.cpp12
-rw-r--r--lib/MC/MachObjectWriter.cpp3
-rw-r--r--lib/Target/ARM/ARMAsmBackend.cpp9
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp2
-rw-r--r--lib/Target/ARM/ARMFixupKinds.h9
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td22
-rw-r--r--lib/Target/ARM/ARMMCCodeEmitter.cpp38
-rw-r--r--test/MC/ARM/arm_fixups.s2
-rw-r--r--utils/TableGen/EDEmitter.cpp7
9 files changed, 88 insertions, 16 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index 4dbb5387f3..629d746826 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -1503,7 +1503,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
break;
}
break;
- case ARM::fixup_arm_branch:
+ case ARM::fixup_arm_uncondbranch:
switch (Modifier) {
case MCSymbolRefExpr::VK_ARM_PLT:
Type = ELF::R_ARM_PLT32;
@@ -1513,6 +1513,9 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
break;
}
break;
+ case ARM::fixup_arm_condbranch:
+ Type = ELF::R_ARM_JUMP24;
+ break;
case ARM::fixup_arm_movt_hi16:
case ARM::fixup_arm_movt_hi16_pcrel:
Type = ELF::R_ARM_MOVT_PREL;
@@ -1565,11 +1568,12 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
case ARM::fixup_arm_thumb_br:
assert(0 && "Unimplemented");
break;
- case ARM::fixup_arm_branch:
- // FIXME: Differentiate between R_ARM_CALL and
- // R_ARM_JUMP24 (latter used for conditional jumps)
+ case ARM::fixup_arm_uncondbranch:
Type = ELF::R_ARM_CALL;
break;
+ case ARM::fixup_arm_condbranch:
+ Type = ELF::R_ARM_JUMP24;
+ break;
case ARM::fixup_arm_movt_hi16:
Type = ELF::R_ARM_MOVT_ABS;
break;
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index 1fb0f99ba4..8af07c74fd 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -940,7 +940,8 @@ public:
case ARM::fixup_arm_ldst_pcrel_12:
case ARM::fixup_arm_pcrel_10:
case ARM::fixup_arm_adr_pcrel_12:
- case ARM::fixup_arm_branch:
+ case ARM::fixup_arm_condbranch:
+ case ARM::fixup_arm_uncondbranch:
RelocType = unsigned(macho::RIT_ARM_Branch24Bit);
// Report as 'long', even though that is not quite accurate.
Log2Size = llvm::Log2_32(4);
diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp
index fa8809d587..ec23449d7d 100644
--- a/lib/Target/ARM/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/ARMAsmBackend.cpp
@@ -67,7 +67,8 @@ public:
{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
-{ "fixup_arm_branch", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
@@ -254,7 +255,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
return swapped;
}
- case ARM::fixup_arm_branch:
+ case ARM::fixup_arm_condbranch:
+ case ARM::fixup_arm_uncondbranch:
// These values don't encode the low two bits since they're always zero.
// Offset by 8 just as above.
return 0xffffff & ((Value - 8) >> 2);
@@ -454,7 +456,8 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
case ARM::fixup_arm_ldst_pcrel_12:
case ARM::fixup_arm_pcrel_10:
case ARM::fixup_arm_adr_pcrel_12:
- case ARM::fixup_arm_branch:
+ case ARM::fixup_arm_condbranch:
+ case ARM::fixup_arm_uncondbranch:
return 3;
case FK_Data_4:
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index fc12ddc1d2..9bbf6a0306 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -187,6 +187,8 @@ namespace {
const { return 0; }
unsigned getUnconditionalBranchTargetOpValue(const MachineInstr &MI,
unsigned Op) const { return 0; }
+ unsigned getARMBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
+ const { return 0; }
unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op)
const { return 0; }
unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op)
diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h
index 9425f22261..3d175e3869 100644
--- a/lib/Target/ARM/ARMFixupKinds.h
+++ b/lib/Target/ARM/ARMFixupKinds.h
@@ -40,9 +40,12 @@ enum Fixups {
// fixup_t2_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
// instruction.
fixup_t2_adr_pcrel_12,
- // fixup_arm_branch - 24-bit PC relative relocation for direct branch
- // instructions.
- fixup_arm_branch,
+ // fixup_arm_condbranch - 24-bit PC relative relocation for conditional branch
+ // instructions.
+ fixup_arm_condbranch,
+ // fixup_arm_uncondbranch - 24-bit PC relative relocation for
+ // branch instructions. (unconditional)
+ fixup_arm_uncondbranch,
// fixup_t2_condbranch - 20-bit PC relative relocation for Thumb2 direct
// uconditional branch instructions.
fixup_t2_condbranch,
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index e6addfee81..bd58fccce7 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -293,20 +293,36 @@ def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{
//
// Branch target.
+// FIXME: rename brtarget to t2_brtarget
def brtarget : Operand<OtherVT> {
let EncoderMethod = "getBranchTargetOpValue";
}
+// FIXME: get rid of this one?
def uncondbrtarget : Operand<OtherVT> {
let EncoderMethod = "getUnconditionalBranchTargetOpValue";
}
+// Branch target for ARM. Handles conditional/unconditional
+def br_target : Operand<OtherVT> {
+ let EncoderMethod = "getARMBranchTargetOpValue";
+}
+
// Call target.
+// FIXME: rename bltarget to t2_bl_target?
def bltarget : Operand<i32> {
// Encoded the same as branch targets.
let EncoderMethod = "getBranchTargetOpValue";
}
+// Call target for ARM. Handles conditional/unconditional
+// FIXME: rename bl_target to t2_bltarget?
+def bl_target : Operand<i32> {
+ // Encoded the same as branch targets.
+ let EncoderMethod = "getARMBranchTargetOpValue";
+}
+
+
// A list of registers separated by comma. Used by load/store multiple.
def RegListAsmOperand : AsmOperandClass {
let Name = "RegList";
@@ -1271,7 +1287,7 @@ let isCall = 1,
D16, D17, D18, D19, D20, D21, D22, D23,
D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR],
Uses = [SP] in {
- def BL : ABXI<0b1011, (outs), (ins bltarget:$func, variable_ops),
+ def BL : ABXI<0b1011, (outs), (ins bl_target:$func, variable_ops),
IIC_Br, "bl\t$func",
[(ARMcall tglobaladdr:$func)]>,
Requires<[IsARM, IsNotDarwin]> {
@@ -1280,7 +1296,7 @@ let isCall = 1,
let Inst{23-0} = func;
}
- def BL_pred : ABI<0b1011, (outs), (ins bltarget:$func, variable_ops),
+ def BL_pred : ABI<0b1011, (outs), (ins bl_target:$func, variable_ops),
IIC_Br, "bl", "\t$func",
[(ARMcall_pred tglobaladdr:$func)]>,
Requires<[IsARM, IsNotDarwin]> {
@@ -1456,7 +1472,7 @@ let isBranch = 1, isTerminator = 1 in {
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
// a two-value operand where a dag node expects two operands. :(
- def Bcc : ABI<0b1010, (outs), (ins brtarget:$target),
+ def Bcc : ABI<0b1010, (outs), (ins br_target:$target),
IIC_Br, "b", "\t$target",
[/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> {
bits<24> target;
diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp
index a309122160..94321ad57a 100644
--- a/lib/Target/ARM/ARMMCCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp
@@ -99,6 +99,10 @@ public:
uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
+ /// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate
+ /// branch target.
+ uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
/// getAdrLabelOpValue - Return encoding info for 12-bit immediate
/// ADR label target.
@@ -473,6 +477,23 @@ getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups);
}
+/// Return true if this branch has a non-always predication
+static bool HasConditionalBranch(const MCInst &MI) {
+ int NumOp = MI.getNumOperands();
+ if (NumOp >= 2) {
+ for (int i = 0; i < NumOp-1; ++i) {
+ const MCOperand &MCOp1 = MI.getOperand(i);
+ const MCOperand &MCOp2 = MI.getOperand(i + 1);
+ if (MCOp1.isImm() && MCOp2.isReg() &&
+ (MCOp2.getReg() == 0 || MCOp2.getReg() == ARM::CPSR)) {
+ if (ARMCC::CondCodes(MCOp1.getImm()) != ARMCC::AL)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
/// target.
uint32_t ARMMCCodeEmitter::
@@ -483,9 +504,24 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
if (Subtarget->isThumb2())
return
::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups);
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_branch, Fixups);
+ return getARMBranchTargetOpValue(MI, OpIdx, Fixups);
}
+/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
+/// target.
+uint32_t ARMMCCodeEmitter::
+getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ if (HasConditionalBranch(MI))
+ return ::getBranchTargetOpValue(MI, OpIdx,
+ ARM::fixup_arm_condbranch, Fixups);
+ return ::getBranchTargetOpValue(MI, OpIdx,
+ ARM::fixup_arm_uncondbranch, Fixups);
+}
+
+
+
+
/// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
/// immediate branch target.
uint32_t ARMMCCodeEmitter::
diff --git a/test/MC/ARM/arm_fixups.s b/test/MC/ARM/arm_fixups.s
index 146de9cf26..0dceb83c24 100644
--- a/test/MC/ARM/arm_fixups.s
+++ b/test/MC/ARM/arm_fixups.s
@@ -2,6 +2,6 @@
// RUN: FileCheck < %t %s
// CHECK: bl _printf @ encoding: [A,A,A,0xeb]
-// CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_branch
+// CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_uncondbranch
bl _printf
\ No newline at end of file
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index 7051f2e0bc..f00f79d56a 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -325,6 +325,9 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
PCR("uncondbrtarget");
PCR("bltarget");
+ // all I, ARM mode only, conditional/unconditional
+ PCR("br_target");
+ PCR("bl_target");
return 1;
}
@@ -600,6 +603,10 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("t_bcctarget", "kOperandTypeARMBranchTarget"); // ?
MISC("t_cbtarget", "kOperandTypeARMBranchTarget"); // ?
MISC("bltarget", "kOperandTypeARMBranchTarget"); // ?
+
+ MISC("br_target", "kOperandTypeARMBranchTarget"); // ?
+ MISC("bl_target", "kOperandTypeARMBranchTarget"); // ?
+
MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ?
MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ?
MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I