From: Jason W Kim Date: Wed, 12 Jan 2011 00:19:25 +0000 (+0000) Subject: 1. Support ELF pcrel relocations for movw/movt: X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=86a97f2e4d0cde5e992f52ac287da0de687e0110;p=oota-llvm.git 1. Support ELF pcrel relocations for movw/movt: R_ARM_MOVT_PREL and R_ARM_MOVW_PREL_NC. 2. Fix minor bug in ARMAsmPrinter - treat bitfield flag as a bitfield, not an enum. 3. Add support for 3 new elf section types (no-ops) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123294 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 757a56aa6e1..470c6f58444 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -1268,6 +1268,9 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, case ELF::SHT_NOTE: case ELF::SHT_NULL: case ELF::SHT_ARM_ATTRIBUTES: + case ELF::SHT_INIT_ARRAY: + case ELF::SHT_FINI_ARRAY: + case ELF::SHT_PREINIT_ARRAY: // Nothing to do. break; @@ -1490,6 +1493,13 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, default: Type = ELF::R_ARM_CALL; break; } break; + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + Type = ELF::R_ARM_MOVT_PREL; break; + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movw_lo16_pcrel: + Type = ELF::R_ARM_MOVW_PREL_NC; break; + } } else { switch ((unsigned)Fixup.getKind()) { diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index c72e7908298..0d5a9af1eba 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -78,6 +78,8 @@ public: { "fixup_arm_thumb_bcc", 1, 8, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_movt_hi16", 0, 16, 0 }, { "fixup_arm_movw_lo16", 0, 16, 0 }, +{ "fixup_arm_movt_hi16_pcrel", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_movw_lo16_pcrel", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, }; if (Kind < FirstTargetFixupKind) @@ -156,7 +158,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case FK_Data_4: return Value; case ARM::fixup_arm_movt_hi16: - case ARM::fixup_arm_movw_lo16: { + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movt_hi16_pcrel: + case ARM::fixup_arm_movw_lo16_pcrel: { unsigned Hi4 = (Value & 0xF000) >> 12; unsigned Lo12 = Value & 0x0FFF; // inst{19-16} = Hi4; diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index d1a975d3423..cce15766111 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -189,10 +189,10 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, int64_t Imm = MO.getImm(); O << '#'; if ((Modifier && strcmp(Modifier, "lo16") == 0) || - (TF == ARMII::MO_LO16)) + (TF & ARMII::MO_LO16)) O << ":lower16:"; else if ((Modifier && strcmp(Modifier, "hi16") == 0) || - (TF == ARMII::MO_HI16)) + (TF & ARMII::MO_HI16)) O << ":upper16:"; O << Imm; break; diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h index 3e0bd0e7b7a..12efcb23006 100644 --- a/lib/Target/ARM/ARMFixupKinds.h +++ b/lib/Target/ARM/ARMFixupKinds.h @@ -74,6 +74,11 @@ enum Fixups { fixup_arm_movt_hi16, // :upper16: fixup_arm_movw_lo16, // :lower16: + // It is possible to create an "immediate" that happens to be pcrel. + // Needed to support ELF::R_ARM_MOVT_PREL and ELF::R_ARM_MOVW_PREL_NC + fixup_arm_movt_hi16_pcrel, // :upper16: + fixup_arm_movw_lo16_pcrel, // :lower16: + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 0e6922128c3..4b328eebbe4 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -626,6 +626,32 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, return Binary; } +// FIXME: This routine needs to handle more MCExpr types +static const MCSymbolRefExpr *FindLHSymExpr(const MCExpr *E) { + // recurse left child until finding a MCSymbolRefExpr + switch (E->getKind()) { + case MCExpr::SymbolRef: + return cast(E); + case MCExpr::Binary: + return FindLHSymExpr(cast(E)->getLHS()); + default: + return NULL; + } +} + +// FIXME: This routine assumes that a binary +// expression will always result in a PCRel expression +// In reality, its only true if one or more subexpressions +// is itself a PCRel (i.e. "." in asm or some other pcrel construct) +// but this is good enough for now. +static bool EvaluateAsPCRel(const MCExpr *Expr) { + switch (Expr->getKind()) { + case MCExpr::SymbolRef: return false; + case MCExpr::Binary: return true; + default: assert(0 && "Unexpected expression type"); + } +} + uint32_t ARMMCCodeEmitter:: getMovtImmOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups) const { @@ -635,18 +661,27 @@ getMovtImmOpValue(const MCInst &MI, unsigned OpIdx, if (MO.isImm()) { return static_cast(MO.getImm()); } else if (const MCSymbolRefExpr *Expr = - dyn_cast(MO.getExpr())) { + FindLHSymExpr(MO.getExpr())) { + // FIXME: :lower16: and :upper16: should be applicable to + // to whole expression, not just symbolrefs + // Until that change takes place, this hack is required to + // generate working code. + const MCExpr *OrigExpr = MO.getExpr(); MCFixupKind Kind; switch (Expr->getKind()) { default: assert(0 && "Unsupported ARMFixup"); case MCSymbolRefExpr::VK_ARM_HI16: Kind = MCFixupKind(ARM::fixup_arm_movt_hi16); + if (EvaluateAsPCRel(OrigExpr)) + Kind = MCFixupKind(ARM::fixup_arm_movt_hi16_pcrel); break; case MCSymbolRefExpr::VK_ARM_LO16: Kind = MCFixupKind(ARM::fixup_arm_movw_lo16); + if (EvaluateAsPCRel(OrigExpr)) + Kind = MCFixupKind(ARM::fixup_arm_movw_lo16_pcrel); break; } - Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + Fixups.push_back(MCFixup::Create(0, OrigExpr, Kind)); return 0; }; llvm_unreachable("Unsupported MCExpr type in MCOperand!"); diff --git a/test/MC/ARM/elf-movt.s b/test/MC/ARM/elf-movt.s index 51c54298de9..066b2d1baf4 100644 --- a/test/MC/ARM/elf-movt.s +++ b/test/MC/ARM/elf-movt.s @@ -1,4 +1,6 @@ @ RUN: llvm-mc %s -triple=armv7-linux-gnueabi | FileCheck -check-prefix=ASM %s +@ RUN: llvm-mc %s -triple=armv7-linux-gnueabi -filetype=obj -o - | \ +@ RUN: elf-dump --dump-section-data | FileCheck -check-prefix=OBJ %s .syntax unified .text .globl barf @@ -12,3 +14,26 @@ barf: @ @barf @ ASM: movw r0, :lower16:GOT-(.LPC0_2+8) @ ASM-NEXT: movt r0, :upper16:GOT-(.LPC0_2+16) +@@ make sure that the text section fixups are sane too +@ OBJ: '.text' +@ OBJ-NEXT: 'sh_type', 0x00000001 +@ OBJ-NEXT: 'sh_flags', 0x00000006 +@ OBJ-NEXT: 'sh_addr', 0x00000000 +@ OBJ-NEXT: 'sh_offset', 0x00000034 +@ OBJ-NEXT: 'sh_size', 0x00000008 +@ OBJ-NEXT: 'sh_link', 0x00000000 +@ OBJ-NEXT: 'sh_info', 0x00000000 +@ OBJ-NEXT: 'sh_addralign', 0x00000004 +@ OBJ-NEXT: 'sh_entsize', 0x00000000 +@ OBJ-NEXT: '_section_data', 'f00f0fe3 ec0f4fe3' + +@ OBJ: Relocation 0x00000000 +@ OBJ-NEXT: 'r_offset', 0x00000000 +@ OBJ-NEXT: 'r_sym' +@ OBJ-NEXT: 'r_type', 0x0000002d + +@ OBJ: Relocation 0x00000001 +@ OBJ-NEXT: 'r_offset', 0x00000004 +@ OBJ-NEXT: 'r_sym' +@ OBJ-NEXT: 'r_type', 0x0000002e +