[lld] r219655 - [mach-o] Add Pass to create are shim Atoms for ARM interworking.
Eric Christopher
echristo at gmail.com
Mon Oct 13 19:49:37 PDT 2014
Ah, I missed the relocation handling in the pass. The kind names made
it seem somewhat generic.
-eric
On Mon, Oct 13, 2014 at 7:39 PM, Nick Kledzik <kledzik at apple.com> wrote:
> On Oct 13, 2014, at 7:09 PM, Eric Christopher <echristo at gmail.com> wrote:
>> For fun, is there any reason why this pass is Mach-O specific? :)
> The relocation model is completely different between mach-o and ELF. We did not try to unify them, so there is no way to write a generic pass like this.
>
> -Nick
>
>> On Mon, Oct 13, 2014 at 6:51 PM, Nick Kledzik <kledzik at apple.com> wrote:
>>> Author: kledzik
>>> Date: Mon Oct 13 20:51:42 2014
>>> New Revision: 219655
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=219655&view=rev
>>> Log:
>>> [mach-o] Add Pass to create are shim Atoms for ARM interworking.
>>>
>>> Arm code has two instruction encodings "thumb" and "arm". When branching from
>>> one code encoding to another, you need to use an instruction that switches
>>> the instruction mode. Usually the transition only happens at call sites, and
>>> the linker can transform a BL instruction in BLX (or vice versa). But if the
>>> compiler did a tail call optimization and a function ends with a branch (not
>>> branch and link), there is no pc-rel BX instruction.
>>>
>>> The ShimPass looks for pc-rel B instructions that will need to switch mode.
>>> For those cases it synthesizes a shim which does the transition, then modifies
>>> the original atom with the B instruction to target to the shim atom.
>>>
>>> Added:
>>> lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp
>>> lld/trunk/test/mach-o/arm-shims.yaml
>>> Modified:
>>> lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
>>> lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
>>> lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
>>> lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
>>> lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
>>> lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
>>> lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
>>> lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
>>> lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h
>>> lld/trunk/test/mach-o/arm-interworking.yaml
>>> lld/trunk/test/mach-o/parse-arm-relocs.yaml
>>>
>>> Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
>>> +++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Mon Oct 13 20:51:42 2014
>>> @@ -230,6 +230,9 @@ public:
>>> /// Pass to transform __compact_unwind into __unwind_info should be run.
>>> bool needsCompactUnwindPass() const;
>>>
>>> + /// Pass to add shims switching between thumb and arm mode.
>>> + bool needsShimPass() const;
>>> +
>>> /// Magic symbol name stubs will need to help lazy bind.
>>> StringRef binderSymbolName() const;
>>>
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h (original)
>>> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h Mon Oct 13 20:51:42 2014
>>> @@ -9,6 +9,7 @@
>>>
>>> #include "MachONormalizedFile.h"
>>> #include "Atoms.h"
>>> +#include "File.h"
>>>
>>> #include "lld/Core/LLVM.h"
>>> #include "lld/Core/Reference.h"
>>> @@ -50,6 +51,9 @@ public:
>>> return false;
>>> }
>>>
>>> + /// Used by ShimPass to insert shims in branches that switch mode.
>>> + virtual bool isNonCallBranch(const Reference &) = 0;
>>> +
>>> /// Used by GOTPass to update GOT References
>>> virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
>>>
>>> @@ -182,6 +186,12 @@ public:
>>> /// Only relevant for 32-bit arm archs.
>>> virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
>>>
>>> + /// Only relevant for 32-bit arm archs.
>>> + virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
>>> + const DefinedAtom &) {
>>> + llvm_unreachable("shims only support on arm");
>>> + }
>>> +
>>> struct ReferenceInfo {
>>> Reference::KindArch arch;
>>> uint16_t kind;
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
>>> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Mon Oct 13 20:51:42 2014
>>> @@ -36,6 +36,7 @@ public:
>>> bool isCallSite(const Reference &) override;
>>> bool isPointer(const Reference &) override;
>>> bool isPairedReloc(const normalized::Relocation &) override;
>>> + bool isNonCallBranch(const Reference &) override;
>>>
>>> bool needsCompactUnwind() override {
>>> return false;
>>> @@ -106,8 +107,13 @@ public:
>>> }
>>>
>>> bool isThumbFunction(const DefinedAtom &atom) override;
>>> + const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
>>> + const DefinedAtom &) override;
>>>
>>> private:
>>> + friend class Thumb2ToArmShimAtom;
>>> + friend class ArmToThumbShimAtom;
>>> +
>>> static const Registry::KindStrings _sKindStrings[];
>>> static const StubInfo _sStubInfoArmPIC;
>>>
>>> @@ -119,12 +125,14 @@ private:
>>> modeData, /// Content starting at this offset is data.
>>>
>>> // Kinds found in mach-o .o files:
>>> - thumb_b22, /// ex: bl _foo
>>> + thumb_bl22, /// ex: bl _foo
>>> + thumb_b22, /// ex: b _foo
>>> thumb_movw, /// ex: movw r1, :lower16:_foo
>>> thumb_movt, /// ex: movt r1, :lower16:_foo
>>> thumb_movw_funcRel, /// ex: movw r1, :lower16:(_foo-(L1+4))
>>> thumb_movt_funcRel, /// ex: movt r1, :upper16:(_foo-(L1+4))
>>> - arm_b24, /// ex: bl _foo
>>> + arm_bl24, /// ex: bl _foo
>>> + arm_b24, /// ex: b _foo
>>> arm_movw, /// ex: movw r1, :lower16:_foo
>>> arm_movt, /// ex: movt r1, :lower16:_foo
>>> arm_movw_funcRel, /// ex: movw r1, :lower16:(_foo-(L1+4))
>>> @@ -154,6 +162,7 @@ private:
>>> static uint32_t setWordFromThumbMov(uint32_t instruction, uint16_t word);
>>> static uint32_t setWordFromArmMov(uint32_t instruction, uint16_t word);
>>>
>>> + StringRef stubName(const DefinedAtom &);
>>> bool useExternalRelocationTo(const Atom &target);
>>>
>>> void applyFixupFinal(const Reference &ref, uint8_t *location,
>>> @@ -183,11 +192,13 @@ const Registry::KindStrings ArchHandler_
>>> LLD_KIND_STRING_ENTRY(modeThumbCode),
>>> LLD_KIND_STRING_ENTRY(modeArmCode),
>>> LLD_KIND_STRING_ENTRY(modeData),
>>> + LLD_KIND_STRING_ENTRY(thumb_bl22),
>>> LLD_KIND_STRING_ENTRY(thumb_b22),
>>> LLD_KIND_STRING_ENTRY(thumb_movw),
>>> LLD_KIND_STRING_ENTRY(thumb_movt),
>>> LLD_KIND_STRING_ENTRY(thumb_movw_funcRel),
>>> LLD_KIND_STRING_ENTRY(thumb_movt_funcRel),
>>> + LLD_KIND_STRING_ENTRY(arm_bl24),
>>> LLD_KIND_STRING_ENTRY(arm_b24),
>>> LLD_KIND_STRING_ENTRY(arm_movw),
>>> LLD_KIND_STRING_ENTRY(arm_movt),
>>> @@ -256,13 +267,31 @@ const ArchHandler::StubInfo &ArchHandler
>>> }
>>>
>>> bool ArchHandler_arm::isCallSite(const Reference &ref) {
>>> - return (ref.kindValue() == thumb_b22) || (ref.kindValue() == arm_b24);
>>> + switch (ref.kindValue()) {
>>> + case thumb_b22:
>>> + case thumb_bl22:
>>> + case arm_b24:
>>> + case arm_bl24:
>>> + return true;
>>> + default:
>>> + return false;
>>> + }
>>> }
>>>
>>> bool ArchHandler_arm::isPointer(const Reference &ref) {
>>> return (ref.kindValue() == pointer32);
>>> }
>>>
>>> +bool ArchHandler_arm::isNonCallBranch(const Reference &ref) {
>>> + switch (ref.kindValue()) {
>>> + case thumb_b22:
>>> + case arm_b24:
>>> + return true;
>>> + default:
>>> + return false;
>>> + }
>>> +}
>>> +
>>> bool ArchHandler_arm::isPairedReloc(const Relocation &reloc) {
>>> switch (reloc.type) {
>>> case ARM_RELOC_SECTDIFF:
>>> @@ -275,6 +304,23 @@ bool ArchHandler_arm::isPairedReloc(cons
>>> }
>>> }
>>>
>>> +/// Trace references from stub atom to lazy pointer to target and get its name.
>>> +StringRef ArchHandler_arm::stubName(const DefinedAtom &stubAtom) {
>>> + assert(stubAtom.contentType() == DefinedAtom::typeStub);
>>> + for (const Reference *ref : stubAtom) {
>>> + if (const DefinedAtom* lp = dyn_cast<DefinedAtom>(ref->target())) {
>>> + if (lp->contentType() != DefinedAtom::typeLazyPointer)
>>> + continue;
>>> + for (const Reference *ref2 : *lp) {
>>> + if (ref2->kindValue() != lazyPointer)
>>> + continue;
>>> + return ref2->target()->name();
>>> + }
>>> + }
>>> + }
>>> + return "stub";
>>> +}
>>> +
>>> /// Extract displacement from an ARM b/bl/blx instruction.
>>> int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) {
>>> // Sign-extend imm24
>>> @@ -352,7 +398,7 @@ uint32_t ArchHandler_arm::setDisplacemen
>>> bool is_bl = ((instruction & 0xD000F800) == 0xD000F000);
>>> bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
>>> bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
>>> - uint32_t newInstruction = (instruction & 0xF800D000);
>>> + uint32_t newInstruction = (instruction & 0xD000F800);
>>> if (is_bl || is_blx) {
>>> if (targetIsThumb) {
>>> newInstruction = 0xD000F000; // Use bl
>>> @@ -363,7 +409,7 @@ uint32_t ArchHandler_arm::setDisplacemen
>>> displacement += 2;
>>> }
>>> } else if (is_b) {
>>> - assert(!targetIsThumb && "no pc-rel thumb branch instruction that "
>>> + assert(targetIsThumb && "no pc-rel thumb branch instruction that "
>>> "switches to arm mode");
>>> }
>>> else {
>>> @@ -461,7 +507,10 @@ std::error_code ArchHandler_arm::getRefe
>>> switch (relocPattern(reloc)) {
>>> case ARM_THUMB_RELOC_BR22 | rPcRel | rExtern | rLength4:
>>> // ex: bl _foo (and _foo is undefined)
>>> - *kind = thumb_b22;
>>> + if ((instruction & 0xD000F800) == 0x9000F000)
>>> + *kind = thumb_b22;
>>> + else
>>> + *kind = thumb_bl22;
>>> if (E ec = atomFromSymbolIndex(reloc.symbol, target))
>>> return ec;
>>> // Instruction contains branch to addend.
>>> @@ -470,13 +519,19 @@ std::error_code ArchHandler_arm::getRefe
>>> return std::error_code();
>>> case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4:
>>> // ex: bl _foo (and _foo is defined)
>>> - *kind = thumb_b22;
>>> + if ((instruction & 0xD000F800) == 0x9000F000)
>>> + *kind = thumb_b22;
>>> + else
>>> + *kind = thumb_bl22;
>>> displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
>>> targetAddress = fixupAddress + 4 + displacement;
>>> return atomFromAddress(reloc.symbol, targetAddress, target, addend);
>>> case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4:
>>> // ex: bl _foo+4 (and _foo is defined)
>>> - *kind = thumb_b22;
>>> + if ((instruction & 0xD000F800) == 0x9000F000)
>>> + *kind = thumb_b22;
>>> + else
>>> + *kind = thumb_bl22;
>>> displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
>>> targetAddress = fixupAddress + 4 + displacement;
>>> if (E ec = atomFromAddress(0, reloc.value, target, addend))
>>> @@ -487,7 +542,11 @@ std::error_code ArchHandler_arm::getRefe
>>> return std::error_code();
>>> case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4:
>>> // ex: bl _foo (and _foo is undefined)
>>> - *kind = arm_b24;
>>> + if (((instruction & 0x0F000000) == 0x0A000000)
>>> + && ((instruction & 0xF0000000) != 0xF0000000))
>>> + *kind = arm_b24;
>>> + else
>>> + *kind = arm_bl24;
>>> if (E ec = atomFromSymbolIndex(reloc.symbol, target))
>>> return ec;
>>> // Instruction contains branch to addend.
>>> @@ -496,13 +555,21 @@ std::error_code ArchHandler_arm::getRefe
>>> return std::error_code();
>>> case ARM_RELOC_BR24 | rPcRel | rLength4:
>>> // ex: bl _foo (and _foo is defined)
>>> - *kind = arm_b24;
>>> + if (((instruction & 0x0F000000) == 0x0A000000)
>>> + && ((instruction & 0xF0000000) != 0xF0000000))
>>> + *kind = arm_b24;
>>> + else
>>> + *kind = arm_bl24;
>>> displacement = getDisplacementFromArmBranch(instruction);
>>> targetAddress = fixupAddress + 8 + displacement;
>>> return atomFromAddress(reloc.symbol, targetAddress, target, addend);
>>> case ARM_RELOC_BR24 | rScattered | rPcRel | rLength4:
>>> // ex: bl _foo+4 (and _foo is defined)
>>> - *kind = arm_b24;
>>> + if (((instruction & 0x0F000000) == 0x0A000000)
>>> + && ((instruction & 0xF0000000) != 0xF0000000))
>>> + *kind = arm_b24;
>>> + else
>>> + *kind = arm_bl24;
>>> displacement = getDisplacementFromArmBranch(instruction);
>>> targetAddress = fixupAddress + 8 + displacement;
>>> if (E ec = atomFromAddress(0, reloc.value, target, addend))
>>> @@ -836,6 +903,7 @@ void ArchHandler_arm::applyFixupFinal(co
>>> case modeData:
>>> break;
>>> case thumb_b22:
>>> + case thumb_bl22:
>>> assert(thumbMode);
>>> displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
>>> value32 = setDisplacementInThumbBranch(*loc32, fixupAddress, displacement,
>>> @@ -867,7 +935,8 @@ void ArchHandler_arm::applyFixupFinal(co
>>> write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
>>> break;
>>> case arm_b24:
>>> - assert(!thumbMode);
>>> + case arm_bl24:
>>> + assert(!thumbMode);
>>> displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
>>> value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb);
>>> write32(*loc32, _swap, value32);
>>> @@ -903,7 +972,10 @@ void ArchHandler_arm::applyFixupFinal(co
>>> write32(*loc32, _swap, targetAddress + ref.addend());
>>> break;
>>> case delta32:
>>> - write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
>>> + if (targetIsThumb)
>>> + write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend() + 1);
>>> + else
>>> + write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
>>> break;
>>> case lazyPointer:
>>> case lazyImmediateLocation:
>>> @@ -990,6 +1062,7 @@ void ArchHandler_arm::applyFixupRelocata
>>> case modeData:
>>> break;
>>> case thumb_b22:
>>> + case thumb_bl22:
>>> assert(thumbMode);
>>> if (useExternalReloc)
>>> displacement = (ref.addend() - (fixupAddress + 4));
>>> @@ -1026,6 +1099,7 @@ void ArchHandler_arm::applyFixupRelocata
>>> write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
>>> break;
>>> case arm_b24:
>>> + case arm_bl24:
>>> assert(!thumbMode);
>>> if (useExternalReloc)
>>> displacement = (ref.addend() - (fixupAddress + 8));
>>> @@ -1100,6 +1174,7 @@ void ArchHandler_arm::appendSectionReloc
>>> // Do nothing.
>>> break;
>>> case thumb_b22:
>>> + case thumb_bl22:
>>> if (useExternalReloc) {
>>> appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
>>> ARM_THUMB_RELOC_BR22 | rExtern | rPcRel | rLength4);
>>> @@ -1179,6 +1254,7 @@ void ArchHandler_arm::appendSectionReloc
>>> ARM_RELOC_PAIR | rScattered | rLenThmbHi);
>>> break;
>>> case arm_b24:
>>> + case arm_bl24:
>>> if (useExternalReloc) {
>>> appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
>>> ARM_RELOC_BR24 | rExtern | rPcRel | rLength4);
>>> @@ -1307,6 +1383,112 @@ bool ArchHandler_arm::isThumbFunction(co
>>> return false;
>>> }
>>>
>>> +
>>> +class Thumb2ToArmShimAtom : public SimpleDefinedAtom {
>>> +public:
>>> + Thumb2ToArmShimAtom(MachOFile &file, StringRef targetName,
>>> + const DefinedAtom &target)
>>> + : SimpleDefinedAtom(file) {
>>> + addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
>>> + ArchHandler_arm::modeThumbCode, 0, this, 0);
>>> + addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
>>> + ArchHandler_arm::delta32, 8, &target, 0);
>>> + std::string name = std::string(targetName) + "$shim";
>>> + StringRef tmp(name);
>>> + _name = tmp.copy(file.allocator());
>>> + }
>>> +
>>> + StringRef name() const override {
>>> + return _name;
>>> + }
>>> +
>>> + ContentType contentType() const override {
>>> + return DefinedAtom::typeCode;
>>> + }
>>> +
>>> + Alignment alignment() const override {
>>> + return Alignment(2);
>>> + }
>>> +
>>> + uint64_t size() const override {
>>> + return 12;
>>> + }
>>> +
>>> + ContentPermissions permissions() const override {
>>> + return DefinedAtom::permR_X;
>>> + }
>>> +
>>> + ArrayRef<uint8_t> rawContent() const override {
>>> + static const uint8_t bytes[] =
>>> + { 0xDF, 0xF8, 0x04, 0xC0, // ldr ip, pc + 4
>>> + 0xFF, 0x44, // add ip, pc, ip
>>> + 0x60, 0x47, // ldr pc, [ip]
>>> + 0x00, 0x00, 0x00, 0x00 }; // .long target - this
>>> + assert(sizeof(bytes) == size());
>>> + return llvm::makeArrayRef(bytes, sizeof(bytes));
>>> + }
>>> +private:
>>> + StringRef _name;
>>> +};
>>> +
>>> +
>>> +class ArmToThumbShimAtom : public SimpleDefinedAtom {
>>> +public:
>>> + ArmToThumbShimAtom(MachOFile &file, StringRef targetName,
>>> + const DefinedAtom &target)
>>> + : SimpleDefinedAtom(file) {
>>> + addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
>>> + ArchHandler_arm::delta32, 12, &target, 0);
>>> + std::string name = std::string(targetName) + "$shim";
>>> + StringRef tmp(name);
>>> + _name = tmp.copy(file.allocator());
>>> + }
>>> +
>>> + StringRef name() const override {
>>> + return _name;
>>> + }
>>> +
>>> + ContentType contentType() const override {
>>> + return DefinedAtom::typeCode;
>>> + }
>>> +
>>> + Alignment alignment() const override {
>>> + return Alignment(2);
>>> + }
>>> +
>>> + uint64_t size() const override {
>>> + return 16;
>>> + }
>>> +
>>> + ContentPermissions permissions() const override {
>>> + return DefinedAtom::permR_X;
>>> + }
>>> +
>>> + ArrayRef<uint8_t> rawContent() const override {
>>> + static const uint8_t bytes[] =
>>> + { 0x04, 0xC0, 0x9F, 0xE5, // ldr ip, pc + 4
>>> + 0x0C, 0xC0, 0x8F, 0xE0, // add ip, pc, ip
>>> + 0x1C, 0xFF, 0x2F, 0xE1, // ldr pc, [ip]
>>> + 0x00, 0x00, 0x00, 0x00 }; // .long target - this
>>> + assert(sizeof(bytes) == size());
>>> + return llvm::makeArrayRef(bytes, sizeof(bytes));
>>> + }
>>> +private:
>>> + StringRef _name;
>>> +};
>>> +
>>> +const DefinedAtom *ArchHandler_arm::createShim(MachOFile &file,
>>> + bool thumbToArm,
>>> + const DefinedAtom &target) {
>>> + bool isStub = (target.contentType() == DefinedAtom::typeStub);
>>> + StringRef targetName = isStub ? stubName(target) : target.name();
>>> + if (thumbToArm)
>>> + return new (file.allocator()) Thumb2ToArmShimAtom(file, targetName, target);
>>> + else
>>> + return new (file.allocator()) ArmToThumbShimAtom(file, targetName, target);
>>> +}
>>> +
>>> +
>>> std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm() {
>>> return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm());
>>> }
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (original)
>>> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp Mon Oct 13 20:51:42 2014
>>> @@ -74,6 +74,10 @@ public:
>>> const StubInfo &stubInfo() override { return _sStubInfo; }
>>>
>>> bool isCallSite(const Reference &) override;
>>> + bool isNonCallBranch(const Reference &) override {
>>> + return false;
>>> + }
>>> +
>>> bool isPointer(const Reference &) override;
>>> bool isPairedReloc(const normalized::Relocation &) override;
>>>
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (original)
>>> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp Mon Oct 13 20:51:42 2014
>>> @@ -34,6 +34,10 @@ public:
>>>
>>> const StubInfo &stubInfo() override { return _sStubInfo; }
>>> bool isCallSite(const Reference &) override;
>>> + bool isNonCallBranch(const Reference &) override {
>>> + return false;
>>> + }
>>> +
>>> bool isPointer(const Reference &) override;
>>> bool isPairedReloc(const normalized::Relocation &) override;
>>>
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)
>>> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Mon Oct 13 20:51:42 2014
>>> @@ -86,6 +86,10 @@ public:
>>>
>>> const StubInfo &stubInfo() override { return _sStubInfo; }
>>>
>>> + bool isNonCallBranch(const Reference &) override {
>>> + return false;
>>> + }
>>> +
>>> bool isCallSite(const Reference &) override;
>>> bool isPointer(const Reference &) override;
>>> bool isPairedReloc(const normalized::Relocation &) override;
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt (original)
>>> +++ lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt Mon Oct 13 20:51:42 2014
>>> @@ -12,6 +12,7 @@ add_lld_library(lldMachO
>>> MachONormalizedFileFromAtoms.cpp
>>> MachONormalizedFileToAtoms.cpp
>>> MachONormalizedFileYAML.cpp
>>> + ShimPass.cpp
>>> StubsPass.cpp
>>> WriterMachO.cpp
>>> )
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
>>> +++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Mon Oct 13 20:51:42 2014
>>> @@ -324,6 +324,21 @@ bool MachOLinkingContext::needsCompactUn
>>> }
>>> }
>>>
>>> +bool MachOLinkingContext::needsShimPass() const {
>>> + // Shim pass only used in final executables.
>>> + if (_outputMachOType == MH_OBJECT)
>>> + return false;
>>> + // Only 32-bit arm arches use Shim pass.
>>> + switch (_arch) {
>>> + case arch_armv6:
>>> + case arch_armv7:
>>> + case arch_armv7s:
>>> + return true;
>>> + default:
>>> + return false;
>>> + }
>>> +}
>>> +
>>> StringRef MachOLinkingContext::binderSymbolName() const {
>>> return archHandler().stubInfo().binderSymbolName;
>>> }
>>> @@ -572,6 +587,8 @@ void MachOLinkingContext::addPasses(Pass
>>> mach_o::addCompactUnwindPass(pm, *this);
>>> if (needsGOTPass())
>>> mach_o::addGOTPass(pm, *this);
>>> + if (needsShimPass())
>>> + mach_o::addShimPass(pm, *this); // Shim pass must run after stubs pass.
>>> }
>>>
>>> Writer &MachOLinkingContext::writer() const {
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h (original)
>>> +++ lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h Mon Oct 13 20:51:42 2014
>>> @@ -19,6 +19,7 @@ namespace mach_o {
>>> void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx);
>>> void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx);
>>> void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx);
>>> +void addShimPass(PassManager &pm, const MachOLinkingContext &ctx);
>>>
>>> } // namespace mach_o
>>> } // namespace lld
>>>
>>> Added: lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp?rev=219655&view=auto
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp (added)
>>> +++ lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp Mon Oct 13 20:51:42 2014
>>> @@ -0,0 +1,131 @@
>>> +//===- lib/ReaderWriter/MachO/ShimPass.cpp -------------------------------===//
>>> +//
>>> +// The LLVM Linker
>>> +//
>>> +// This file is distributed under the University of Illinois Open Source
>>> +// License. See LICENSE.TXT for details.
>>> +//
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +// This linker pass updates branch-sites whose target is a different mode
>>> +// (thumb vs arm).
>>> +//
>>> +// Arm code has two instruction encodings thumb and arm. When branching from
>>> +// one code encoding to another, you need to use an instruction that switches
>>> +// the instruction mode. Usually the transition only happens at call sites, and
>>> +// the linker can transform a BL instruction in BLX (or vice versa). But if the
>>> +// compiler did a tail call optimization and a function ends with a branch (not
>>> +// branch and link), there is no pc-rel BX instruction.
>>> +//
>>> +// The ShimPass looks for pc-rel B instructions that will need to switch mode.
>>> +// For those cases it synthesizes a shim which does the transition, then
>>> +// modifies the original atom with the B instruction to target to the shim atom.
>>> +//
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#include "ArchHandler.h"
>>> +#include "File.h"
>>> +#include "MachOPasses.h"
>>> +
>>> +#include "lld/Core/DefinedAtom.h"
>>> +#include "lld/Core/File.h"
>>> +#include "lld/Core/LLVM.h"
>>> +#include "lld/Core/Reference.h"
>>> +#include "lld/Core/Simple.h"
>>> +#include "lld/ReaderWriter/MachOLinkingContext.h"
>>> +
>>> +#include "llvm/ADT/DenseMap.h"
>>> +
>>> +
>>> +namespace lld {
>>> +namespace mach_o {
>>> +
>>> +class ShimPass : public Pass {
>>> +public:
>>> + ShimPass(const MachOLinkingContext &context)
>>> + : _context(context)
>>> + , _archHandler(_context.archHandler())
>>> + , _stubInfo(_archHandler.stubInfo())
>>> + , _file("<mach-o shim pass>") {
>>> + }
>>> +
>>> +
>>> + void perform(std::unique_ptr<MutableFile> &mergedFile) override {
>>> + // Scan all references in all atoms.
>>> + for (const DefinedAtom *atom : mergedFile->defined()) {
>>> + for (const Reference *ref : *atom) {
>>> + // Look at non-call branches.
>>> + if (!_archHandler.isNonCallBranch(*ref))
>>> + continue;
>>> + const Atom *target = ref->target();
>>> + assert(target != nullptr);
>>> + if (const lld::DefinedAtom *daTarget = dyn_cast<DefinedAtom>(target)) {
>>> + bool atomIsThumb = _archHandler.isThumbFunction(*atom);
>>> + bool targetIsThumb = _archHandler.isThumbFunction(*daTarget);
>>> + if (atomIsThumb != targetIsThumb)
>>> + updateBranchToUseShim(atomIsThumb, *daTarget, ref);
>>> + }
>>> + }
>>> + }
>>> + // Exit early if no shims needed.
>>> + if (_targetToShim.empty())
>>> + return;
>>> +
>>> + // Sort shim atoms so the layout order is stable.
>>> + std::vector<const DefinedAtom *> shims;
>>> + shims.reserve(_targetToShim.size());
>>> + for (auto element : _targetToShim) {
>>> + shims.push_back(element.second);
>>> + }
>>> + std::sort(shims.begin(), shims.end(),
>>> + [](const DefinedAtom *l, const DefinedAtom *r) {
>>> + return (l->name() < r->name());
>>> + });
>>> +
>>> + // Add all shims to master file.
>>> + for (const DefinedAtom *shim : shims) {
>>> + mergedFile->addAtom(*shim);
>>> + }
>>> + }
>>> +
>>> +private:
>>> +
>>> + void updateBranchToUseShim(bool thumbToArm, const DefinedAtom& target,
>>> + const Reference *ref) {
>>> + // Make file-format specific stub and other support atoms.
>>> + const DefinedAtom *shim = this->getShim(thumbToArm, target);
>>> + assert(shim != nullptr);
>>> + // Switch branch site to target shim atom.
>>> + const_cast<Reference *>(ref)->setTarget(shim);
>>> + }
>>> +
>>> + const DefinedAtom* getShim(bool thumbToArm, const DefinedAtom& target) {
>>> + auto pos = _targetToShim.find(&target);
>>> + if ( pos != _targetToShim.end() ) {
>>> + // Reuse an existing shim.
>>> + assert(pos->second != nullptr);
>>> + return pos->second;
>>> + } else {
>>> + // There is no existing shim, so create a new one.
>>> + const DefinedAtom *shim = _archHandler.createShim(_file, thumbToArm,
>>> + target);
>>> + _targetToShim[&target] = shim;
>>> + return shim;
>>> + }
>>> + }
>>> +
>>> + const MachOLinkingContext &_context;
>>> + mach_o::ArchHandler &_archHandler;
>>> + const ArchHandler::StubInfo &_stubInfo;
>>> + MachOFile _file;
>>> + llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToShim;
>>> +};
>>> +
>>> +
>>> +
>>> +void addShimPass(PassManager &pm, const MachOLinkingContext &ctx) {
>>> + pm.add(std::unique_ptr<Pass>(new ShimPass(ctx)));
>>> +}
>>> +
>>> +} // end namespace mach_o
>>> +} // end namespace lld
>>>
>>> Modified: lld/trunk/test/mach-o/arm-interworking.yaml
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/arm-interworking.yaml?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/test/mach-o/arm-interworking.yaml (original)
>>> +++ lld/trunk/test/mach-o/arm-interworking.yaml Mon Oct 13 20:51:42 2014
>>> @@ -237,28 +237,28 @@ undefined-symbols:
>>> # CHECK: - kind: modeThumbCode
>>> # CHECK: offset: 0
>>> # CHECK: target: _t1
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 0
>>> # CHECK: target: _a1
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 6
>>> # CHECK: target: _a2
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 12
>>> # CHECK: target: _a2
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 16
>>> # CHECK: target: _t1
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 22
>>> # CHECK: target: _t1
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 28
>>> # CHECK: target: _t2
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 34
>>> # CHECK: target: _t2
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 38
>>> # CHECK: target: _t3
>>> # CHECK: - name: _t2
>>> @@ -277,16 +277,16 @@ undefined-symbols:
>>> # CHECK: - name: _a1
>>> # CHECK: scope: global
>>> # CHECK: references:
>>> -# CHECK: - kind: arm_b24
>>> +# CHECK: - kind: arm_bl24
>>> # CHECK: offset: 0
>>> # CHECK: target: _a1
>>> -# CHECK: - kind: arm_b24
>>> +# CHECK: - kind: arm_bl24
>>> # CHECK: offset: 4
>>> # CHECK: target: _a2
>>> -# CHECK: - kind: arm_b24
>>> +# CHECK: - kind: arm_bl24
>>> # CHECK: offset: 8
>>> # CHECK: target: _t1
>>> -# CHECK: - kind: arm_b24
>>> +# CHECK: - kind: arm_bl24
>>> # CHECK: offset: 12
>>> # CHECK: target: _t2
>>> # CHECK: - name: _a2
>>>
>>> Added: lld/trunk/test/mach-o/arm-shims.yaml
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/arm-shims.yaml?rev=219655&view=auto
>>> ==============================================================================
>>> --- lld/trunk/test/mach-o/arm-shims.yaml (added)
>>> +++ lld/trunk/test/mach-o/arm-shims.yaml Mon Oct 13 20:51:42 2014
>>> @@ -0,0 +1,179 @@
>>> +# RUN: lld -flavor darwin -arch armv7 %s -dylib %p/Inputs/libSystem.yaml -o %t
>>> +# RUN: macho-dump --dump-section-data %t | FileCheck %s
>>> +#
>>> +# Test b from arm to thumb or vice versa has shims added.s
>>> +#
>>> +#
>>> +
>>> +--- !mach-o
>>> +arch: armv7
>>> +file-type: MH_OBJECT
>>> +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
>>> +sections:
>>> + - segment: __TEXT
>>> + section: __text
>>> + type: S_REGULAR
>>> + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
>>> + alignment: 2
>>> + address: 0x0000000000000000
>>> + content: [ 0x00, 0xBF, 0xFF, 0xF7, 0xFE, 0xEF, 0xFF, 0xF7,
>>> + 0xFB, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3,
>>> + 0xFA, 0xFF, 0xFF, 0xFA, 0xF9, 0xFF, 0xFF, 0xEA ]
>>> + relocations:
>>> + - offset: 0x00000014
>>> + type: ARM_RELOC_BR24
>>> + length: 2
>>> + pc-rel: true
>>> + extern: true
>>> + symbol: 3
>>> + - offset: 0x00000010
>>> + type: ARM_RELOC_BR24
>>> + length: 2
>>> + pc-rel: true
>>> + extern: true
>>> + symbol: 3
>>> + - offset: 0x00000006
>>> + type: ARM_THUMB_RELOC_BR22
>>> + length: 2
>>> + pc-rel: true
>>> + extern: true
>>> + symbol: 2
>>> + - offset: 0x00000002
>>> + type: ARM_THUMB_RELOC_BR22
>>> + length: 2
>>> + pc-rel: true
>>> + extern: true
>>> + symbol: 2
>>> +global-symbols:
>>> + - name: _a1
>>> + type: N_SECT
>>> + scope: [ N_EXT ]
>>> + sect: 1
>>> + value: 0x000000000000000C
>>> + - name: _t1
>>> + type: N_SECT
>>> + scope: [ N_EXT ]
>>> + sect: 1
>>> + desc: [ N_ARM_THUMB_DEF ]
>>> + value: 0x0000000000000000
>>> +undefined-symbols:
>>> + - name: _a2
>>> + type: N_UNDF
>>> + scope: [ N_EXT ]
>>> + value: 0x0000000000000000
>>> + - name: _t2
>>> + type: N_UNDF
>>> + scope: [ N_EXT ]
>>> + value: 0x0000000000000000
>>> +
>>> +
>>> +--- !mach-o
>>> +arch: armv7
>>> +file-type: MH_OBJECT
>>> +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
>>> +sections:
>>> + - segment: __TEXT
>>> + section: __text
>>> + type: S_REGULAR
>>> + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
>>> + alignment: 2
>>> + address: 0x0000000000000000
>>> + content: [ 0x00, 0xBF, 0xFF, 0xF7, 0xFE, 0xEF, 0xFF, 0xF7,
>>> + 0xFB, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3,
>>> + 0xFA, 0xFF, 0xFF, 0xFA, 0xF9, 0xFF, 0xFF, 0xEA ]
>>> + relocations:
>>> + - offset: 0x00000014
>>> + type: ARM_RELOC_BR24
>>> + length: 2
>>> + pc-rel: true
>>> + extern: true
>>> + symbol: 3
>>> + - offset: 0x00000010
>>> + type: ARM_RELOC_BR24
>>> + length: 2
>>> + pc-rel: true
>>> + extern: true
>>> + symbol: 3
>>> + - offset: 0x00000006
>>> + type: ARM_THUMB_RELOC_BR22
>>> + length: 2
>>> + pc-rel: true
>>> + extern: true
>>> + symbol: 2
>>> + - offset: 0x00000002
>>> + type: ARM_THUMB_RELOC_BR22
>>> + length: 2
>>> + pc-rel: true
>>> + extern: true
>>> + symbol: 2
>>> +global-symbols:
>>> + - name: _a2
>>> + type: N_SECT
>>> + scope: [ N_EXT ]
>>> + sect: 1
>>> + value: 0x000000000000000C
>>> + - name: _t2
>>> + type: N_SECT
>>> + scope: [ N_EXT ]
>>> + sect: 1
>>> + desc: [ N_ARM_THUMB_DEF ]
>>> + value: 0x0000000000000000
>>> +undefined-symbols:
>>> + - name: _a1
>>> + type: N_UNDF
>>> + scope: [ N_EXT ]
>>> + value: 0x0000000000000000
>>> + - name: _t1
>>> + type: N_UNDF
>>> + scope: [ N_EXT ]
>>> + value: 0x0000000000000000
>>> +
>>> +...
>>> +
>>> +
>>> +# CHECK: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
>>> +# CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
>>> +# CHECK: ('_section_data', '00bf00f0 10e800f0 19b80000 00f020e3 000000fa 0f0000ea 00bffff7 f8ef00f0 07b80000 00f020e3 f4fffffa 050000ea dff804c0 ff446047 d4ffffff dff804c0 ff446047 e0ffffff 04c09fe5 0cc08fe0 1cff2fe1 adffffff 04c09fe5 0cc08fe0 1cff2fe1 b5ffffff')
>>> +
>>> +# When we get a good mach-o disassembler the above __text section content check can be change to be symbolic.
>>> +
>>> +
>>> +# Input file one:
>>> +#
>>> +# .align 2
>>> +# .code 16
>>> +# .globl _t1
>>> +# .thumb_func _t1
>>> +#_t1:
>>> +# nop
>>> +# blx _a2
>>> +# b _a2
>>> +#
>>> +# .code 32
>>> +# .align 2
>>> +# .globl _a1
>>> +#_a1:
>>> +# nop
>>> +# blx _t2
>>> +# b _t2
>>> +
>>> +
>>> +
>>> +# Input file two:
>>> +#
>>> +# .align 2
>>> +# .code 16
>>> +# .globl _t2
>>> +# .thumb_func _t2
>>> +#_t2:
>>> +# nop
>>> +# blx _a1
>>> +# b _a1
>>> +#
>>> +# .code 32
>>> +# .align 2
>>> +# .globl _a2
>>> +#_a2:
>>> +# nop
>>> +# blx _t1
>>> +# b _t1
>>>
>>> Modified: lld/trunk/test/mach-o/parse-arm-relocs.yaml
>>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-arm-relocs.yaml?rev=219655&r1=219654&r2=219655&view=diff
>>> ==============================================================================
>>> --- lld/trunk/test/mach-o/parse-arm-relocs.yaml (original)
>>> +++ lld/trunk/test/mach-o/parse-arm-relocs.yaml Mon Oct 13 20:51:42 2014
>>> @@ -572,19 +572,19 @@ undefined-symbols:
>>> # CHECK: references:
>>> # CHECK: - kind: modeThumbCode
>>> # CHECK: offset: 0
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 0
>>> # CHECK: target: _x
>>> # CHECK-NOT: addend:
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 4
>>> # CHECK: target: _x
>>> # CHECK: addend: 4
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 8
>>> # CHECK: target: _undef
>>> # CHECK-NOT: addend:
>>> -# CHECK: - kind: thumb_b22
>>> +# CHECK: - kind: thumb_bl22
>>> # CHECK: offset: 12
>>> # CHECK: target: _undef
>>> # CHECK: addend: 4
>>> @@ -660,19 +660,19 @@ undefined-symbols:
>>> # CHECK: - name: _foo_arm
>>> # CHECK: references:
>>> # CHECK-NOT: - kind: modeThumbCode
>>> -# CHECK: - kind: arm_b24
>>> +# CHECK: - kind: arm_bl24
>>> # CHECK: offset: 0
>>> # CHECK: target: _x
>>> # CHECK-NOT: addend:
>>> -# CHECK: - kind: arm_b24
>>> +# CHECK: - kind: arm_bl24
>>> # CHECK: offset: 4
>>> # CHECK: target: _x
>>> # CHECK: addend: 4
>>> -# CHECK: - kind: arm_b24
>>> +# CHECK: - kind: arm_bl24
>>> # CHECK: offset: 8
>>> # CHECK: target: _undef
>>> # CHECK-NOT: addend:
>>> -# CHECK: - kind: arm_b24
>>> +# CHECK: - kind: arm_bl24
>>> # CHECK: offset: 12
>>> # CHECK: target: _undef
>>> # CHECK: addend: 4
>>> @@ -739,11 +739,11 @@ undefined-symbols:
>>> # bl _undef
>>> # bl _undef+4
>>> # movw r1, :lower16:(_x-L1)
>>> -# movt r1, :upper16:(_x-L1)
>>> +# movt r1, :upper16:(_x-L1)
>>> # movw r2, :lower16:(_x+8-L1)
>>> -# movt r2, :upper16:(_x+8-L1)
>>> +# movt r2, :upper16:(_x+8-L1)
>>> # movw r1, :lower16:(_t1-L1)
>>> -# movt r1, :upper16:(_t1-L1)
>>> +# movt r1, :upper16:(_t1-L1)
>>> # add r1, pc
>>> #L1:
>>> # movw r3, :lower16:_x
>>> @@ -770,9 +770,9 @@ undefined-symbols:
>>> # bl _undef
>>> # bl _undef+4
>>> # movw r1, :lower16:(_x-L2)
>>> -# movt r1, :upper16:(_x-L2)
>>> +# movt r1, :upper16:(_x-L2)
>>> # movw r2, :lower16:(_x+8-L2)
>>> -# movt r2, :upper16:(_x+8-L2)
>>> +# movt r2, :upper16:(_x+8-L2)
>>> # add r1, pc
>>> #L2:
>>> # movw r3, :lower16:_x
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
More information about the llvm-commits
mailing list