From 05018c2f2872a05b1a2fff1a9934621ba1f38084 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Thu, 9 Dec 2010 20:27:52 +0000 Subject: [PATCH] Fix an issue in some Thumb fixups, where the effective PC address needs to be 4-byte aligned when calculating the offset. Add a new fixup flag to represent this, and use it for the one fixups that I have a testcase for needing this. It's quite likely that the other Thumb fixups will need this too, and to have their fixup encoding logic adjusted accordingly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121408 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCCodeEmitter.h | 5 ++++- lib/MC/MCAssembler.cpp | 11 +++++++++-- lib/Target/ARM/ARMAsmBackend.cpp | 4 ++-- lib/Target/ARM/ARMMCCodeEmitter.cpp | 3 ++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index eac06ede2ab..2588661b62a 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -25,7 +25,10 @@ struct MCFixupKindInfo { enum FixupKindFlags { /// Is this fixup kind PCrelative? This is used by the assembler backend to /// evaluate fixup values in a target independent manner when possible. - FKF_IsPCRel = (1 << 0) + FKF_IsPCRel = (1 << 0), + + // Should this fixup kind force a 4-byte aligned effective PC value? + FKF_IsAligned = (1 << 1) }; /// A target specific name for the fixup kind. The names will be unique for diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 323352ff8b7..319f04cfe70 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -253,8 +253,15 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer, if (IsResolved) IsResolved = Writer.IsFixupFullyResolved(*this, Target, IsPCRel, DF); - if (IsPCRel) - Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset(); + if (IsPCRel) { + bool ShouldAlignPC = Emitter.getFixupKindInfo( + Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsAligned; + // PC should be aligned to a 4-byte value. + if (ShouldAlignPC) + Value -= Layout.getFragmentOffset(DF) + (Fixup.getOffset() & ~0x3); + else + Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset(); + } return IsResolved; } diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index 6be9f9288e2..606437efbb4 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -100,10 +100,10 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { } case ARM::fixup_arm_ldst_pcrel_12: // ARM PC-relative values are offset by 8. - Value -= 6; + Value -= 4; case ARM::fixup_t2_ldst_pcrel_12: { // Offset by 4, adjusted by two due to the half-word ordering of thumb. - Value -= 2; + Value -= 4; bool isAdd = true; if ((int64_t)Value < 0) { Value = -Value; diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index c81833b28f8..4d8791c9989 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -47,7 +47,8 @@ public: const static MCFixupKindInfo Infos[] = { // name off bits flags { "fixup_arm_ldst_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAligned}, { "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },