15c1d160cSStefan Gränitz //===----- ELF_aarch32.cpp - JIT linker implementation for arm/thumb ------===// 25c1d160cSStefan Gränitz // 35c1d160cSStefan Gränitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45c1d160cSStefan Gränitz // See https://llvm.org/LICENSE.txt for license information. 55c1d160cSStefan Gränitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65c1d160cSStefan Gränitz // 75c1d160cSStefan Gränitz //===----------------------------------------------------------------------===// 85c1d160cSStefan Gränitz // 95c1d160cSStefan Gränitz // ELF/aarch32 jit-link implementation. 105c1d160cSStefan Gränitz // 115c1d160cSStefan Gränitz //===----------------------------------------------------------------------===// 125c1d160cSStefan Gränitz 135c1d160cSStefan Gränitz #include "llvm/ExecutionEngine/JITLink/ELF_aarch32.h" 145c1d160cSStefan Gränitz 155c1d160cSStefan Gränitz #include "llvm/BinaryFormat/ELF.h" 165c1d160cSStefan Gränitz #include "llvm/ExecutionEngine/JITLink/JITLink.h" 175c1d160cSStefan Gränitz #include "llvm/ExecutionEngine/JITLink/aarch32.h" 185c1d160cSStefan Gränitz #include "llvm/Object/ELF.h" 195c1d160cSStefan Gränitz #include "llvm/Object/ELFObjectFile.h" 205c1d160cSStefan Gränitz #include "llvm/Support/ErrorHandling.h" 215c1d160cSStefan Gränitz #include "llvm/TargetParser/ARMTargetParser.h" 225c1d160cSStefan Gränitz 235c1d160cSStefan Gränitz #include "ELFLinkGraphBuilder.h" 245c1d160cSStefan Gränitz #include "JITLinkGeneric.h" 255c1d160cSStefan Gränitz 265c1d160cSStefan Gränitz #define DEBUG_TYPE "jitlink" 275c1d160cSStefan Gränitz 285c1d160cSStefan Gränitz using namespace llvm::object; 295c1d160cSStefan Gränitz 305c1d160cSStefan Gränitz namespace llvm { 315c1d160cSStefan Gränitz namespace jitlink { 325c1d160cSStefan Gränitz 335c1d160cSStefan Gränitz /// Translate from ELF relocation type to JITLink-internal edge kind. 34bfb09326SStefan Gränitz Expected<aarch32::EdgeKind_aarch32> 35bfb09326SStefan Gränitz getJITLinkEdgeKind(uint32_t ELFType, const aarch32::ArmConfig &ArmCfg) { 365c1d160cSStefan Gränitz switch (ELFType) { 37a05a98a2SStefan Gränitz case ELF::R_ARM_ABS32: 38a05a98a2SStefan Gränitz return aarch32::Data_Pointer32; 39c4fc563bSStefan Gränitz case ELF::R_ARM_GOT_PREL: 40c4fc563bSStefan Gränitz return aarch32::Data_RequestGOTAndTransformToDelta32; 415c1d160cSStefan Gränitz case ELF::R_ARM_REL32: 425c1d160cSStefan Gränitz return aarch32::Data_Delta32; 435c1d160cSStefan Gränitz case ELF::R_ARM_CALL: 445c1d160cSStefan Gränitz return aarch32::Arm_Call; 4562f793ecSEymen Ünay case ELF::R_ARM_JUMP24: 4662f793ecSEymen Ünay return aarch32::Arm_Jump24; 47e575b7cbSEymen Ünay case ELF::R_ARM_MOVW_ABS_NC: 48e575b7cbSEymen Ünay return aarch32::Arm_MovwAbsNC; 49e575b7cbSEymen Ünay case ELF::R_ARM_MOVT_ABS: 50e575b7cbSEymen Ünay return aarch32::Arm_MovtAbs; 51565470edSStefan Gränitz case ELF::R_ARM_NONE: 52565470edSStefan Gränitz return aarch32::None; 539577806bSStefan Gränitz case ELF::R_ARM_PREL31: 549577806bSStefan Gränitz return aarch32::Data_PRel31; 55bfb09326SStefan Gränitz case ELF::R_ARM_TARGET1: 56bfb09326SStefan Gränitz return (ArmCfg.Target1Rel) ? aarch32::Data_Delta32 57bfb09326SStefan Gränitz : aarch32::Data_Pointer32; 585c1d160cSStefan Gränitz case ELF::R_ARM_THM_CALL: 595c1d160cSStefan Gränitz return aarch32::Thumb_Call; 605c1d160cSStefan Gränitz case ELF::R_ARM_THM_JUMP24: 615c1d160cSStefan Gränitz return aarch32::Thumb_Jump24; 625c1d160cSStefan Gränitz case ELF::R_ARM_THM_MOVW_ABS_NC: 635c1d160cSStefan Gränitz return aarch32::Thumb_MovwAbsNC; 645c1d160cSStefan Gränitz case ELF::R_ARM_THM_MOVT_ABS: 655c1d160cSStefan Gränitz return aarch32::Thumb_MovtAbs; 6687081f1cSEymen Ünay case ELF::R_ARM_THM_MOVW_PREL_NC: 6787081f1cSEymen Ünay return aarch32::Thumb_MovwPrelNC; 6887081f1cSEymen Ünay case ELF::R_ARM_THM_MOVT_PREL: 6987081f1cSEymen Ünay return aarch32::Thumb_MovtPrel; 705c1d160cSStefan Gränitz } 715c1d160cSStefan Gränitz 725c1d160cSStefan Gränitz return make_error<JITLinkError>( 735c1d160cSStefan Gränitz "Unsupported aarch32 relocation " + formatv("{0:d}: ", ELFType) + 745c1d160cSStefan Gränitz object::getELFRelocationTypeName(ELF::EM_ARM, ELFType)); 755c1d160cSStefan Gränitz } 765c1d160cSStefan Gränitz 775c1d160cSStefan Gränitz /// Translate from JITLink-internal edge kind back to ELF relocation type. 785c1d160cSStefan Gränitz Expected<uint32_t> getELFRelocationType(Edge::Kind Kind) { 795c1d160cSStefan Gränitz switch (static_cast<aarch32::EdgeKind_aarch32>(Kind)) { 805c1d160cSStefan Gränitz case aarch32::Data_Delta32: 815c1d160cSStefan Gränitz return ELF::R_ARM_REL32; 82a05a98a2SStefan Gränitz case aarch32::Data_Pointer32: 83a05a98a2SStefan Gränitz return ELF::R_ARM_ABS32; 849577806bSStefan Gränitz case aarch32::Data_PRel31: 859577806bSStefan Gränitz return ELF::R_ARM_PREL31; 86c4fc563bSStefan Gränitz case aarch32::Data_RequestGOTAndTransformToDelta32: 87c4fc563bSStefan Gränitz return ELF::R_ARM_GOT_PREL; 885c1d160cSStefan Gränitz case aarch32::Arm_Call: 895c1d160cSStefan Gränitz return ELF::R_ARM_CALL; 9062f793ecSEymen Ünay case aarch32::Arm_Jump24: 9162f793ecSEymen Ünay return ELF::R_ARM_JUMP24; 92e575b7cbSEymen Ünay case aarch32::Arm_MovwAbsNC: 93e575b7cbSEymen Ünay return ELF::R_ARM_MOVW_ABS_NC; 94e575b7cbSEymen Ünay case aarch32::Arm_MovtAbs: 95e575b7cbSEymen Ünay return ELF::R_ARM_MOVT_ABS; 965c1d160cSStefan Gränitz case aarch32::Thumb_Call: 975c1d160cSStefan Gränitz return ELF::R_ARM_THM_CALL; 985c1d160cSStefan Gränitz case aarch32::Thumb_Jump24: 995c1d160cSStefan Gränitz return ELF::R_ARM_THM_JUMP24; 1005c1d160cSStefan Gränitz case aarch32::Thumb_MovwAbsNC: 1015c1d160cSStefan Gränitz return ELF::R_ARM_THM_MOVW_ABS_NC; 1025c1d160cSStefan Gränitz case aarch32::Thumb_MovtAbs: 1035c1d160cSStefan Gränitz return ELF::R_ARM_THM_MOVT_ABS; 10487081f1cSEymen Ünay case aarch32::Thumb_MovwPrelNC: 10587081f1cSEymen Ünay return ELF::R_ARM_THM_MOVW_PREL_NC; 10687081f1cSEymen Ünay case aarch32::Thumb_MovtPrel: 10787081f1cSEymen Ünay return ELF::R_ARM_THM_MOVT_PREL; 108565470edSStefan Gränitz case aarch32::None: 109565470edSStefan Gränitz return ELF::R_ARM_NONE; 1105c1d160cSStefan Gränitz } 1115c1d160cSStefan Gränitz 1125c1d160cSStefan Gränitz return make_error<JITLinkError>(formatv("Invalid aarch32 edge {0:d}: ", 1135c1d160cSStefan Gränitz Kind)); 1145c1d160cSStefan Gränitz } 1155c1d160cSStefan Gränitz 1165c1d160cSStefan Gränitz /// Get a human-readable name for the given ELF AArch32 edge kind. 1175c1d160cSStefan Gränitz const char *getELFAArch32EdgeKindName(Edge::Kind R) { 1185c1d160cSStefan Gränitz // No ELF-specific edge kinds yet 1195c1d160cSStefan Gränitz return aarch32::getEdgeKindName(R); 1205c1d160cSStefan Gränitz } 1215c1d160cSStefan Gränitz 1225c1d160cSStefan Gränitz class ELFJITLinker_aarch32 : public JITLinker<ELFJITLinker_aarch32> { 1235c1d160cSStefan Gränitz friend class JITLinker<ELFJITLinker_aarch32>; 1245c1d160cSStefan Gränitz 1255c1d160cSStefan Gränitz public: 1265c1d160cSStefan Gränitz ELFJITLinker_aarch32(std::unique_ptr<JITLinkContext> Ctx, 1275c1d160cSStefan Gränitz std::unique_ptr<LinkGraph> G, PassConfiguration PassCfg, 1285c1d160cSStefan Gränitz aarch32::ArmConfig ArmCfg) 1295c1d160cSStefan Gränitz : JITLinker(std::move(Ctx), std::move(G), std::move(PassCfg)), 1305c1d160cSStefan Gränitz ArmCfg(std::move(ArmCfg)) {} 1315c1d160cSStefan Gränitz 1325c1d160cSStefan Gränitz private: 1335c1d160cSStefan Gränitz aarch32::ArmConfig ArmCfg; 1345c1d160cSStefan Gränitz 1355c1d160cSStefan Gränitz Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 1365c1d160cSStefan Gränitz return aarch32::applyFixup(G, B, E, ArmCfg); 1375c1d160cSStefan Gränitz } 1385c1d160cSStefan Gränitz }; 1395c1d160cSStefan Gränitz 140a9d50568SKazu Hirata template <llvm::endianness DataEndianness> 1415c1d160cSStefan Gränitz class ELFLinkGraphBuilder_aarch32 1425c1d160cSStefan Gränitz : public ELFLinkGraphBuilder<ELFType<DataEndianness, false>> { 1435c1d160cSStefan Gränitz private: 1445c1d160cSStefan Gränitz using ELFT = ELFType<DataEndianness, false>; 1455c1d160cSStefan Gränitz using Base = ELFLinkGraphBuilder<ELFT>; 1465c1d160cSStefan Gränitz 1475c1d160cSStefan Gränitz Error addRelocations() override { 1485c1d160cSStefan Gränitz LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 1495c1d160cSStefan Gränitz using Self = ELFLinkGraphBuilder_aarch32<DataEndianness>; 1505c1d160cSStefan Gränitz for (const auto &RelSect : Base::Sections) { 1515c1d160cSStefan Gränitz if (Error Err = Base::forEachRelRelocation(RelSect, this, 1525c1d160cSStefan Gränitz &Self::addSingleRelRelocation)) 1535c1d160cSStefan Gränitz return Err; 1545c1d160cSStefan Gränitz } 1555c1d160cSStefan Gränitz return Error::success(); 1565c1d160cSStefan Gränitz } 1575c1d160cSStefan Gränitz 1585c1d160cSStefan Gränitz Error addSingleRelRelocation(const typename ELFT::Rel &Rel, 1595c1d160cSStefan Gränitz const typename ELFT::Shdr &FixupSect, 1605c1d160cSStefan Gränitz Block &BlockToFix) { 1615c1d160cSStefan Gränitz uint32_t SymbolIndex = Rel.getSymbol(false); 1625c1d160cSStefan Gränitz auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 1635c1d160cSStefan Gränitz if (!ObjSymbol) 1645c1d160cSStefan Gränitz return ObjSymbol.takeError(); 1655c1d160cSStefan Gränitz 1665c1d160cSStefan Gränitz Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 1675c1d160cSStefan Gränitz if (!GraphSymbol) 1685c1d160cSStefan Gränitz return make_error<StringError>( 1695c1d160cSStefan Gränitz formatv("Could not find symbol at given index, did you add it to " 1705c1d160cSStefan Gränitz "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 1715c1d160cSStefan Gränitz SymbolIndex, (*ObjSymbol)->st_shndx, 1725c1d160cSStefan Gränitz Base::GraphSymbols.size()), 1735c1d160cSStefan Gränitz inconvertibleErrorCode()); 1745c1d160cSStefan Gränitz 1755c1d160cSStefan Gränitz uint32_t Type = Rel.getType(false); 176bfb09326SStefan Gränitz Expected<aarch32::EdgeKind_aarch32> Kind = getJITLinkEdgeKind(Type, ArmCfg); 1775c1d160cSStefan Gränitz if (!Kind) 1785c1d160cSStefan Gränitz return Kind.takeError(); 1795c1d160cSStefan Gränitz 1805c1d160cSStefan Gränitz auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset; 1815c1d160cSStefan Gränitz Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 1825c1d160cSStefan Gränitz 1835c1d160cSStefan Gränitz Expected<int64_t> Addend = 184808caa9dSStefan Gränitz aarch32::readAddend(*Base::G, BlockToFix, Offset, *Kind, ArmCfg); 1855c1d160cSStefan Gränitz if (!Addend) 1865c1d160cSStefan Gränitz return Addend.takeError(); 1875c1d160cSStefan Gränitz 188808caa9dSStefan Gränitz Edge E(*Kind, Offset, *GraphSymbol, *Addend); 1895c1d160cSStefan Gränitz LLVM_DEBUG({ 1905c1d160cSStefan Gränitz dbgs() << " "; 1915c1d160cSStefan Gränitz printEdge(dbgs(), BlockToFix, E, getELFAArch32EdgeKindName(*Kind)); 1925c1d160cSStefan Gränitz dbgs() << "\n"; 1935c1d160cSStefan Gränitz }); 1945c1d160cSStefan Gränitz 1955c1d160cSStefan Gränitz BlockToFix.addEdge(std::move(E)); 1965c1d160cSStefan Gränitz return Error::success(); 1975c1d160cSStefan Gränitz } 1985c1d160cSStefan Gränitz 1995c1d160cSStefan Gränitz aarch32::ArmConfig ArmCfg; 2005c1d160cSStefan Gränitz 2015c1d160cSStefan Gränitz protected: 2025c1d160cSStefan Gränitz TargetFlagsType makeTargetFlags(const typename ELFT::Sym &Sym) override { 203cd0f8910SEymen Ünay // Only emit target flag for callable symbols 204cd0f8910SEymen Ünay if (Sym.getType() != ELF::STT_FUNC) 205cd0f8910SEymen Ünay return TargetFlagsType{}; 2065c1d160cSStefan Gränitz if (Sym.getValue() & 0x01) 2075c1d160cSStefan Gränitz return aarch32::ThumbSymbol; 2085c1d160cSStefan Gränitz return TargetFlagsType{}; 2095c1d160cSStefan Gränitz } 2105c1d160cSStefan Gränitz 2115c1d160cSStefan Gränitz orc::ExecutorAddrDiff getRawOffset(const typename ELFT::Sym &Sym, 2125c1d160cSStefan Gränitz TargetFlagsType Flags) override { 2135c1d160cSStefan Gränitz assert((makeTargetFlags(Sym) & Flags) == Flags); 2145c1d160cSStefan Gränitz static constexpr uint64_t ThumbBit = 0x01; 215cd0f8910SEymen Ünay if (Sym.getType() == ELF::STT_FUNC) 2165c1d160cSStefan Gränitz return Sym.getValue() & ~ThumbBit; 217cd0f8910SEymen Ünay return Sym.getValue(); 2185c1d160cSStefan Gränitz } 2195c1d160cSStefan Gränitz 2205c1d160cSStefan Gränitz public: 221a35e4d2cSStefan Gränitz ELFLinkGraphBuilder_aarch32(StringRef FileName, 222*2ccf7ed2SJared Wyles const llvm::object::ELFFile<ELFT> &Obj, 223*2ccf7ed2SJared Wyles std::shared_ptr<orc::SymbolStringPool> SSP, 224*2ccf7ed2SJared Wyles Triple TT, SubtargetFeatures Features, 225a35e4d2cSStefan Gränitz aarch32::ArmConfig ArmCfg) 226*2ccf7ed2SJared Wyles : ELFLinkGraphBuilder<ELFT>(Obj, std::move(SSP), std::move(TT), 227*2ccf7ed2SJared Wyles std::move(Features), FileName, 228*2ccf7ed2SJared Wyles getELFAArch32EdgeKindName), 2295c1d160cSStefan Gränitz ArmCfg(std::move(ArmCfg)) {} 2305c1d160cSStefan Gränitz }; 2315c1d160cSStefan Gränitz 2329c607e77SStefan Gränitz template <typename StubsManagerType> 2335c1d160cSStefan Gränitz Error buildTables_ELF_aarch32(LinkGraph &G) { 2345c1d160cSStefan Gränitz LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 2355c1d160cSStefan Gränitz 2369c607e77SStefan Gränitz StubsManagerType StubsManager; 2379c607e77SStefan Gränitz visitExistingEdges(G, StubsManager); 238c4fc563bSStefan Gränitz aarch32::GOTBuilder GOT; 239c4fc563bSStefan Gränitz visitExistingEdges(G, GOT); 240c4fc563bSStefan Gränitz 2415c1d160cSStefan Gränitz return Error::success(); 2425c1d160cSStefan Gränitz } 2435c1d160cSStefan Gränitz 244*2ccf7ed2SJared Wyles Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_aarch32( 245*2ccf7ed2SJared Wyles MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) { 2465c1d160cSStefan Gränitz LLVM_DEBUG({ 2475c1d160cSStefan Gränitz dbgs() << "Building jitlink graph for new input " 2485c1d160cSStefan Gränitz << ObjectBuffer.getBufferIdentifier() << "...\n"; 2495c1d160cSStefan Gränitz }); 2505c1d160cSStefan Gränitz 2515c1d160cSStefan Gränitz auto ELFObj = ObjectFile::createELFObjectFile(ObjectBuffer); 2525c1d160cSStefan Gränitz if (!ELFObj) 2535c1d160cSStefan Gränitz return ELFObj.takeError(); 2545c1d160cSStefan Gränitz 255348d0a6bSJob Noorman auto Features = (*ELFObj)->getFeatures(); 256348d0a6bSJob Noorman if (!Features) 257348d0a6bSJob Noorman return Features.takeError(); 258348d0a6bSJob Noorman 2595c1d160cSStefan Gränitz // Find out what exact AArch32 instruction set and features we target. 2605c1d160cSStefan Gränitz auto TT = (*ELFObj)->makeTriple(); 2615c1d160cSStefan Gränitz ARM::ArchKind AK = ARM::parseArch(TT.getArchName()); 2625c1d160cSStefan Gränitz if (AK == ARM::ArchKind::INVALID) 2635c1d160cSStefan Gränitz return make_error<JITLinkError>( 2645c1d160cSStefan Gränitz "Failed to build ELF link graph: Invalid ARM ArchKind"); 2655c1d160cSStefan Gränitz 2665c1d160cSStefan Gränitz // Resolve our internal configuration for the target. If at some point the 2675c1d160cSStefan Gränitz // CPUArch alone becomes too unprecise, we can find more details in the 2685c1d160cSStefan Gränitz // Tag_CPU_arch_profile. 26955929cd6SStefan Gränitz auto Arch = static_cast<ARMBuildAttrs::CPUArch>(ARM::getArchAttr(AK)); 27055929cd6SStefan Gränitz aarch32::ArmConfig ArmCfg = aarch32::getArmConfigForCPUArch(Arch); 2715c1d160cSStefan Gränitz 2725c1d160cSStefan Gränitz // Populate the link-graph. 2735c1d160cSStefan Gränitz switch (TT.getArch()) { 2745c1d160cSStefan Gränitz case Triple::arm: 2755c1d160cSStefan Gränitz case Triple::thumb: { 2765c1d160cSStefan Gränitz auto &ELFFile = cast<ELFObjectFile<ELF32LE>>(**ELFObj).getELFFile(); 2774a0ccfa8SKazu Hirata return ELFLinkGraphBuilder_aarch32<llvm::endianness::little>( 278*2ccf7ed2SJared Wyles (*ELFObj)->getFileName(), ELFFile, std::move(SSP), TT, 279*2ccf7ed2SJared Wyles std::move(*Features), ArmCfg) 2805c1d160cSStefan Gränitz .buildGraph(); 2815c1d160cSStefan Gränitz } 2825c1d160cSStefan Gränitz case Triple::armeb: 2835c1d160cSStefan Gränitz case Triple::thumbeb: { 2845c1d160cSStefan Gränitz auto &ELFFile = cast<ELFObjectFile<ELF32BE>>(**ELFObj).getELFFile(); 2854a0ccfa8SKazu Hirata return ELFLinkGraphBuilder_aarch32<llvm::endianness::big>( 286*2ccf7ed2SJared Wyles (*ELFObj)->getFileName(), ELFFile, std::move(SSP), TT, 287*2ccf7ed2SJared Wyles std::move(*Features), ArmCfg) 2885c1d160cSStefan Gränitz .buildGraph(); 2895c1d160cSStefan Gränitz } 2905c1d160cSStefan Gränitz default: 2915c1d160cSStefan Gränitz return make_error<JITLinkError>( 2925c1d160cSStefan Gränitz "Failed to build ELF/aarch32 link graph: Invalid target triple " + 2935c1d160cSStefan Gränitz TT.getTriple()); 2945c1d160cSStefan Gränitz } 2955c1d160cSStefan Gränitz } 2965c1d160cSStefan Gränitz 2975c1d160cSStefan Gränitz void link_ELF_aarch32(std::unique_ptr<LinkGraph> G, 2985c1d160cSStefan Gränitz std::unique_ptr<JITLinkContext> Ctx) { 2995c1d160cSStefan Gränitz const Triple &TT = G->getTargetTriple(); 3005c1d160cSStefan Gränitz 3015c1d160cSStefan Gränitz using namespace ARMBuildAttrs; 3025c1d160cSStefan Gränitz ARM::ArchKind AK = ARM::parseArch(TT.getArchName()); 3035c1d160cSStefan Gränitz auto CPU = static_cast<CPUArch>(ARM::getArchAttr(AK)); 3045c1d160cSStefan Gränitz aarch32::ArmConfig ArmCfg = aarch32::getArmConfigForCPUArch(CPU); 3055c1d160cSStefan Gränitz 3065c1d160cSStefan Gränitz PassConfiguration PassCfg; 3075c1d160cSStefan Gränitz if (Ctx->shouldAddDefaultTargetPasses(TT)) { 3085c1d160cSStefan Gränitz // Add a mark-live pass. 3095c1d160cSStefan Gränitz if (auto MarkLive = Ctx->getMarkLivePass(TT)) 3105c1d160cSStefan Gränitz PassCfg.PrePrunePasses.push_back(std::move(MarkLive)); 3115c1d160cSStefan Gränitz else 3125c1d160cSStefan Gränitz PassCfg.PrePrunePasses.push_back(markAllSymbolsLive); 3135c1d160cSStefan Gränitz 3145c1d160cSStefan Gränitz switch (ArmCfg.Stubs) { 31555929cd6SStefan Gränitz case aarch32::StubsFlavor::pre_v7: 31655929cd6SStefan Gränitz PassCfg.PostPrunePasses.push_back( 31755929cd6SStefan Gränitz buildTables_ELF_aarch32<aarch32::StubsManager_prev7>); 31855929cd6SStefan Gränitz break; 319a979797dSStefan Gränitz case aarch32::StubsFlavor::v7: 3205c1d160cSStefan Gränitz PassCfg.PostPrunePasses.push_back( 3219c607e77SStefan Gränitz buildTables_ELF_aarch32<aarch32::StubsManager_v7>); 3225c1d160cSStefan Gränitz break; 32355929cd6SStefan Gränitz case aarch32::StubsFlavor::Undefined: 3245c1d160cSStefan Gränitz llvm_unreachable("Check before building graph"); 3255c1d160cSStefan Gränitz } 3265c1d160cSStefan Gränitz } 3275c1d160cSStefan Gränitz 3285c1d160cSStefan Gränitz if (auto Err = Ctx->modifyPassConfig(*G, PassCfg)) 3295c1d160cSStefan Gränitz return Ctx->notifyFailed(std::move(Err)); 3305c1d160cSStefan Gränitz 3315c1d160cSStefan Gränitz ELFJITLinker_aarch32::link(std::move(Ctx), std::move(G), std::move(PassCfg), 3325c1d160cSStefan Gränitz std::move(ArmCfg)); 3335c1d160cSStefan Gränitz } 3345c1d160cSStefan Gränitz 3355c1d160cSStefan Gränitz } // namespace jitlink 3365c1d160cSStefan Gränitz } // namespace llvm 337