[llvm] [BOLT][Hexagon] Add Hexagon MCPlusBuilder, relocations (PR #192189)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 14 22:57:01 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-bolt
Author: Brian Cain (androm3da)
<details>
<summary>Changes</summary>
Add the Hexagon target backend for BOLT, enabling binary analysis and optimization of Hexagon ELF executables.
---
Patch is 66.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/192189.diff
22 Files Affected:
- (modified) bolt/CMakeLists.txt (+1-1)
- (modified) bolt/include/bolt/Core/BinaryContext.h (+4)
- (modified) bolt/include/bolt/Core/MCPlusBuilder.h (+22)
- (modified) bolt/lib/Core/BinaryContext.cpp (+5)
- (modified) bolt/lib/Core/BinaryEmitter.cpp (+124-2)
- (modified) bolt/lib/Core/BinaryFunction.cpp (+27)
- (modified) bolt/lib/Core/Relocation.cpp (+219)
- (modified) bolt/lib/Rewrite/RewriteInstance.cpp (+6-1)
- (added) bolt/lib/Target/Hexagon/CMakeLists.txt (+34)
- (added) bolt/lib/Target/Hexagon/HexagonMCPlusBuilder.cpp (+635)
- (added) bolt/test/Hexagon/cfg-build.s (+30)
- (added) bolt/test/Hexagon/cfg-compound-branch.s (+37)
- (added) bolt/test/Hexagon/cfg-cond-tail-call.s (+38)
- (added) bolt/test/Hexagon/cfg-duplex.s (+39)
- (added) bolt/test/Hexagon/cfg-indirect-call.s (+30)
- (added) bolt/test/Hexagon/lit.local.cfg (+7)
- (added) bolt/test/Hexagon/rewrite-allocframe.s (+75)
- (added) bolt/test/Hexagon/rewrite-branch-target.s (+110)
- (added) bolt/test/Hexagon/rewrite-cond-return.s (+52)
- (added) bolt/test/Hexagon/rewrite-const-extender.s (+33)
- (added) bolt/test/Hexagon/rewrite-newvalue-jump.s (+40)
- (added) bolt/test/Hexagon/rewrite-newvalue-store.s (+35)
``````````diff
diff --git a/bolt/CMakeLists.txt b/bolt/CMakeLists.txt
index 5c7d51e1e398c..5dbe9a2bf5957 100644
--- a/bolt/CMakeLists.txt
+++ b/bolt/CMakeLists.txt
@@ -62,7 +62,7 @@ endif() # standalone
# Determine default set of targets to build -- the intersection of
# those BOLT supports and those LLVM is targeting.
-set(BOLT_TARGETS_TO_BUILD_all "AArch64;X86;RISCV")
+set(BOLT_TARGETS_TO_BUILD_all "AArch64;X86;RISCV;Hexagon")
set(BOLT_TARGETS_TO_BUILD_default)
foreach (tgt ${BOLT_TARGETS_TO_BUILD_all})
if (tgt IN_LIST LLVM_TARGETS_TO_BUILD)
diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h
index f8a0be0418433..c4ae7b445dc8a 100644
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -887,6 +887,10 @@ class BinaryContext {
bool isRISCV() const { return TheTriple->getArch() == llvm::Triple::riscv64; }
+ bool isHexagon() const {
+ return TheTriple->getArch() == llvm::Triple::hexagon;
+ }
+
// AArch64/RISC-V functions to check if symbol is used to delimit
// code/data in .text. Code is marked by $x, data by $d.
MarkerSymType getMarkerType(const SymbolRef &Symbol) const;
diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index 0f6076688b65d..1bcc986d26df1 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -2523,6 +2523,23 @@ class MCPlusBuilder {
return 2;
}
+ /// Return true if this target requires instructions to be wrapped in
+ /// BUNDLE MCInsts before emission (e.g. Hexagon VLIW packets).
+ virtual bool requiresBundleEmission() const { return false; }
+
+ /// Return true if the instruction is a .new value consumer that requires
+ /// its producer to be in the same VLIW packet (e.g. Hexagon .new value
+ /// stores and .new compare-and-jump instructions).
+ virtual bool isNewValueConsumer(const MCInst &Inst) const { return false; }
+
+ /// Create a BUNDLE MCInst from a sequence of individual instructions.
+ /// Used by targets that require bundle emission (e.g. Hexagon).
+ virtual MCInst createBundle(MCContext &Ctx, ArrayRef<MCInst> Instrs,
+ bool InnerLoop = false,
+ bool OuterLoop = false) const {
+ llvm_unreachable("not implemented");
+ }
+
// AliasMap caches a mapping of registers to the set of registers that
// alias (are sub or superregs of itself, including itself).
std::vector<BitVector> AliasMap;
@@ -2546,6 +2563,11 @@ MCPlusBuilder *createRISCVMCPlusBuilder(const MCInstrAnalysis *,
const MCRegisterInfo *,
const MCSubtargetInfo *);
+MCPlusBuilder *createHexagonMCPlusBuilder(const MCInstrAnalysis *,
+ const MCInstrInfo *,
+ const MCRegisterInfo *,
+ const MCSubtargetInfo *);
+
} // namespace bolt
} // namespace llvm
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index 554efe671fd5b..bc0cead1c17e0 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -206,6 +206,11 @@ Expected<std::unique_ptr<BinaryContext>> BinaryContext::createBinaryContext(
FeaturesStr = Features->getString();
break;
}
+ case llvm::Triple::hexagon:
+ ArchName = "hexagon";
+ if (Features)
+ FeaturesStr = Features->getString();
+ break;
default:
return createStringError(std::errc::not_supported,
"BOLT-ERROR: Unrecognized machine in ELF file");
diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp
index 49604542cc7da..c102205afa167 100644
--- a/bolt/lib/Core/BinaryEmitter.cpp
+++ b/bolt/lib/Core/BinaryEmitter.cpp
@@ -454,18 +454,91 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
BF.duplicateConstantIslands();
}
+ const bool NeedBundles = BC.MIB->requiresBundleEmission();
+
+ // Hexagon packet accumulator: collects instructions until a packet-end
+ // annotation is seen, then emits them as a single BUNDLE MCInst.
+ SmallVector<MCInst, 4> HexPacket;
+
+ // Helper: flush accumulated Hexagon packet as a BUNDLE.
+ auto flushHexPacket = [&]() {
+ if (HexPacket.empty())
+ return;
+ LLVM_DEBUG({
+ dbgs() << "BOLT-DEBUG: flushing packet (" << HexPacket.size()
+ << " instrs) in " << BF.getPrintName() << "\n";
+ });
+ MCInst Bundle = BC.MIB->createBundle(Streamer.getContext(), HexPacket);
+ Streamer.emitInstruction(Bundle, *BC.STI);
+ HexPacket.clear();
+ };
+
// Track the first emitted instruction with debug info.
bool FirstInstr = true;
+ BinaryBasicBlock *PrevBB = nullptr;
for (BinaryBasicBlock *const BB : FF) {
if ((opts::AlignBlocks || opts::PreserveBlocksAlignment) &&
BB->getAlignment() > 1)
Streamer.emitCodeAlignment(BB->getAlign(), &*BC.STI,
BB->getAlignmentMaxBytes());
+
+ // On Hexagon, a VLIW packet may span BB boundaries because BOLT
+ // splits packets at branch instructions, placing post-branch
+ // instructions in the fallthrough BB. Since all instructions in a
+ // Hexagon packet execute atomically, we carry the pending packet
+ // across the BB boundary to keep them in the same bundle.
+ //
+ // When carrying across, we still emit the BB label (BOLT requires
+ // all emitted BB labels to be defined), but we do NOT flush the
+ // pending packet. The label will precede the combined bundle in
+ // the output, which is correct: on Hexagon, all instructions in
+ // the packet execute atomically, so the label points to the same
+ // execution point regardless of where it falls within the packet.
+ //
+ // Carry-across is safe when the BB is a pure fallthrough: either
+ // unreachable (pred_size == 0) or the only predecessor is the
+ // immediately preceding layout block. Branch targets (multiple
+ // predecessors, non-adjacent predecessor) must flush so the label
+ // starts a new packet.
+ //
+ // On Hexagon, entry points (including secondary entries) do not
+ // force a flush: the processor executes entire packets atomically,
+ // so a jump to a mid-packet label still runs all instructions from
+ // the packet start. This preserves .new dependencies that span an
+ // entry-point boundary within a packet.
+ if (NeedBundles && !HexPacket.empty()) {
+ bool CanCarryAcross =
+ (!BB->isEntryPoint() || BC.isHexagon()) &&
+ (BB->pred_size() == 0 ||
+ (BB->pred_size() == 1 && PrevBB && *BB->pred_begin() == PrevBB));
+ if (!CanCarryAcross || HexPacket.size() >= 4) {
+ // Before flushing, check whether the next BB starts with a
+ // .new value consumer (compare-and-jump or store). If so,
+ // keep the packet open: the producer in the current packet
+ // must stay in the same emitted packet as the consumer.
+ // Hexagon packets execute atomically, so the label pointing
+ // here runs all instructions from the packet start anyway.
+ bool NextIsNewValue = false;
+ if (BC.isHexagon() && !BB->empty()) {
+ auto First = BB->begin();
+ // Skip pseudos (CFI, etc.) to find the first real instruction.
+ while (First != BB->end() && BC.MIB->isPseudo(*First))
+ ++First;
+ if (First != BB->end())
+ NextIsNewValue = BC.MIB->isNewValueConsumer(*First);
+ }
+ if (!NextIsNewValue)
+ flushHexPacket();
+ }
+ } else if (NeedBundles) {
+ flushHexPacket();
+ }
Streamer.emitLabel(BB->getLabel());
if (!EmitCodeOnly) {
if (MCSymbol *EntrySymbol = BF.getSecondaryEntryPointSymbol(*BB))
Streamer.emitLabel(EntrySymbol);
}
+ PrevBB = BB;
SMLoc LastLocSeen;
for (auto I = BB->begin(), E = BB->end(); I != E; ++I) {
@@ -499,8 +572,21 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
BB->getLocSyms().emplace_back(Offset, InstrLabel);
}
- if (InstrLabel)
- Streamer.emitLabel(InstrLabel);
+ if (InstrLabel) {
+ // On Hexagon, labels cannot fall mid-packet because all
+ // instructions in a packet execute atomically. Flushing the
+ // packet here would split .new producer/consumer pairs.
+ // Only emit the label if we are not in the middle of a packet.
+ if (NeedBundles && !HexPacket.empty()) {
+ // Mid-packet addresses are not meaningful on Hexagon
+ // because packets execute atomically. Drop the label.
+ LLVM_DEBUG(dbgs() << "BOLT-DEBUG: dropping mid-packet label "
+ << InstrLabel->getName() << " in "
+ << BF.getPrintName() << '\n');
+ } else {
+ Streamer.emitLabel(InstrLabel);
+ }
+ }
}
// Emit sized NOPs via MCAsmBackend::writeNopData() interface on x86.
@@ -515,10 +601,46 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
}
}
+ // Hexagon: accumulate instructions into packets and emit as bundles.
+ if (NeedBundles) {
+ bool IsPacketEnd = BC.MIB->hasAnnotation(Instr, "HexPacketEnd");
+ // Skip MC pseudo instructions (e.g. A2_nop) that the Hexagon code
+ // emitter cannot encode. If the pseudo is at a packet end, flush
+ // the packet without it.
+ if (BC.MIB->isPseudo(Instr)) {
+ if (IsPacketEnd)
+ flushHexPacket();
+ continue;
+ }
+ // Constant extender (immext / A4_ext) instructions must be
+ // included in the packet. The MC code emitter requires them
+ // to set State.Extended, which tells it to encode only the
+ // lower bits of the next instruction's immediate (the upper
+ // bits come from the immext word).
+ // Safety: if the packet already has 4 instructions (Hexagon max),
+ // flush before adding more. This guards against pathological
+ // carry-across scenarios.
+ if (HexPacket.size() >= 4)
+ flushHexPacket();
+ HexPacket.push_back(Instr);
+ // Flush on packet end. Instructions with HexPacketEnd annotation
+ // (from disassembly or BOLT-generated) terminate the current packet.
+ // Note: all BOLT-generated instructions get HexPacketEnd added by
+ // the Hexagon MCPlusBuilder, so they become singleton packets.
+ if (IsPacketEnd) {
+ flushHexPacket();
+ }
+ continue;
+ }
+
Streamer.emitInstruction(Instr, *BC.STI);
}
}
+ // Flush any remaining Hexagon packet at end of function fragment.
+ if (NeedBundles)
+ flushHexPacket();
+
if (!EmitCodeOnly)
emitConstantIslands(BF, FF.isSplitFragment());
}
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index c5aefe685de34..f001e9cd53d74 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -35,6 +35,7 @@
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
#include "llvm/Support/GenericLoopInfoImpl.h"
#include "llvm/Support/GraphWriter.h"
@@ -1543,6 +1544,25 @@ Error BinaryFunction::disassemble() {
MIB->setSize(Instruction, Size);
}
+ // Annotate Hexagon packet boundaries from parse bits in the raw
+ // instruction word. The Hexagon disassembler returns individual
+ // instructions but does not convey packet structure. We recover it
+ // by inspecting bits [15:14] of the 32-bit instruction word:
+ // 0b11 = packet end,
+ // 0b10 = hardware loop end (handled in hwloop support),
+ // 0b01 = not end (middle of packet),
+ // 0b00 = duplex (always last word in packet).
+ if (BC.isHexagon() && Size >= 4) {
+ uint32_t RawWord =
+ support::endian::read32le(FunctionData.data() + Offset);
+ uint32_t ParseBits = RawWord & 0xc000;
+ // Packet end: 0xc000 (end) or 0x0000 (duplex, always last).
+ if (ParseBits == 0xc000 || ParseBits == 0x0000) {
+ if (!MIB->hasAnnotation(Instruction, "HexPacketEnd"))
+ MIB->addAnnotation(Instruction, "HexPacketEnd", true);
+ }
+ }
+
addInstruction(Offset, std::move(Instruction));
}
@@ -1828,6 +1848,13 @@ bool BinaryFunction::scanExternalRefs() {
}
}
+ // On Hexagon, the MC encoder expects BUNDLE MCInsts and the
+ // createRelocation method is not implemented, so skip instruction
+ // encoding for external reference scanning. The branch-target
+ // handling above (which doesn't need encoding) is sufficient.
+ if (BC.isHexagon())
+ continue;
+
// Emit the instruction using temp emitter and generate relocations.
SmallString<256> Code;
SmallVector<MCFixup, 4> Fixups;
diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp
index f872db2cae0ce..5376b203efe4b 100644
--- a/bolt/lib/Core/Relocation.cpp
+++ b/bolt/lib/Core/Relocation.cpp
@@ -133,6 +133,51 @@ static bool isSupportedRISCV(uint32_t Type) {
}
}
+static bool isSupportedHexagon(uint32_t Type) {
+ switch (Type) {
+ default:
+ return false;
+ case ELF::R_HEX_B22_PCREL:
+ case ELF::R_HEX_B15_PCREL:
+ case ELF::R_HEX_B7_PCREL:
+ case ELF::R_HEX_B13_PCREL:
+ case ELF::R_HEX_B9_PCREL:
+ case ELF::R_HEX_B32_PCREL_X:
+ case ELF::R_HEX_B22_PCREL_X:
+ case ELF::R_HEX_B15_PCREL_X:
+ case ELF::R_HEX_B13_PCREL_X:
+ case ELF::R_HEX_B9_PCREL_X:
+ case ELF::R_HEX_B7_PCREL_X:
+ case ELF::R_HEX_32_6_X:
+ case ELF::R_HEX_16_X:
+ case ELF::R_HEX_12_X:
+ case ELF::R_HEX_11_X:
+ case ELF::R_HEX_10_X:
+ case ELF::R_HEX_9_X:
+ case ELF::R_HEX_8_X:
+ case ELF::R_HEX_7_X:
+ case ELF::R_HEX_6_X:
+ case ELF::R_HEX_32:
+ case ELF::R_HEX_16:
+ case ELF::R_HEX_8:
+ case ELF::R_HEX_LO16:
+ case ELF::R_HEX_HI16:
+ case ELF::R_HEX_32_PCREL:
+ case ELF::R_HEX_PLT_B22_PCREL:
+ case ELF::R_HEX_GOT_32_6_X:
+ case ELF::R_HEX_GOT_16_X:
+ case ELF::R_HEX_GOT_11_X:
+ case ELF::R_HEX_GOTREL_32_6_X:
+ case ELF::R_HEX_GOTREL_16_X:
+ case ELF::R_HEX_GOTREL_11_X:
+ case ELF::R_HEX_6_PCREL_X:
+ case ELF::R_HEX_TPREL_32_6_X:
+ case ELF::R_HEX_TPREL_16_X:
+ case ELF::R_HEX_TPREL_11_X:
+ return true;
+ }
+}
+
static size_t getSizeForTypeX86(uint32_t Type) {
switch (Type) {
default:
@@ -241,6 +286,54 @@ static size_t getSizeForTypeRISCV(uint32_t Type) {
}
}
+static size_t getSizeForTypeHexagon(uint32_t Type) {
+ switch (Type) {
+ default:
+ errs() << object::getELFRelocationTypeName(ELF::EM_HEXAGON, Type) << '\n';
+ llvm_unreachable("unsupported relocation type");
+ case ELF::R_HEX_8:
+ return 1;
+ case ELF::R_HEX_16:
+ return 2;
+ case ELF::R_HEX_B22_PCREL:
+ case ELF::R_HEX_B15_PCREL:
+ case ELF::R_HEX_B7_PCREL:
+ case ELF::R_HEX_B13_PCREL:
+ case ELF::R_HEX_B9_PCREL:
+ case ELF::R_HEX_B32_PCREL_X:
+ case ELF::R_HEX_B22_PCREL_X:
+ case ELF::R_HEX_B15_PCREL_X:
+ case ELF::R_HEX_B13_PCREL_X:
+ case ELF::R_HEX_B9_PCREL_X:
+ case ELF::R_HEX_B7_PCREL_X:
+ case ELF::R_HEX_32_6_X:
+ case ELF::R_HEX_16_X:
+ case ELF::R_HEX_12_X:
+ case ELF::R_HEX_11_X:
+ case ELF::R_HEX_10_X:
+ case ELF::R_HEX_9_X:
+ case ELF::R_HEX_8_X:
+ case ELF::R_HEX_7_X:
+ case ELF::R_HEX_6_X:
+ case ELF::R_HEX_32:
+ case ELF::R_HEX_32_PCREL:
+ case ELF::R_HEX_LO16:
+ case ELF::R_HEX_HI16:
+ case ELF::R_HEX_PLT_B22_PCREL:
+ case ELF::R_HEX_GOT_32_6_X:
+ case ELF::R_HEX_GOT_16_X:
+ case ELF::R_HEX_GOT_11_X:
+ case ELF::R_HEX_GOTREL_32_6_X:
+ case ELF::R_HEX_GOTREL_16_X:
+ case ELF::R_HEX_GOTREL_11_X:
+ case ELF::R_HEX_6_PCREL_X:
+ case ELF::R_HEX_TPREL_32_6_X:
+ case ELF::R_HEX_TPREL_16_X:
+ case ELF::R_HEX_TPREL_11_X:
+ return 4;
+ }
+}
+
static bool skipRelocationTypeX86(uint32_t Type) {
return Type == ELF::R_X86_64_NONE;
}
@@ -266,6 +359,19 @@ static bool skipRelocationTypeRISCV(uint32_t Type) {
}
}
+static bool skipRelocationTypeHexagon(uint32_t Type) {
+ switch (Type) {
+ default:
+ return false;
+ case ELF::R_HEX_NONE:
+ case ELF::R_HEX_GPREL16_0:
+ case ELF::R_HEX_GPREL16_1:
+ case ELF::R_HEX_GPREL16_2:
+ case ELF::R_HEX_GPREL16_3:
+ return true;
+ }
+}
+
static uint64_t encodeValueX86(uint32_t Type, uint64_t Value, uint64_t PC) {
switch (Type) {
default:
@@ -524,6 +630,13 @@ static uint64_t extractValueRISCV(uint32_t Type, uint64_t Contents,
}
}
+static uint64_t extractValueHexagon(uint32_t Type, uint64_t Contents,
+ uint64_t PC) {
+ // For binary analysis (read-only), return the raw contents. Full extraction
+ // of Hexagon instruction-encoded immediates is only needed for rewriting.
+ return Contents;
+}
+
static bool isGOTX86(uint32_t Type) {
switch (Type) {
default:
@@ -570,6 +683,20 @@ static bool isGOTRISCV(uint32_t Type) {
}
}
+static bool isGOTHexagon(uint32_t Type) {
+ switch (Type) {
+ default:
+ return false;
+ case ELF::R_HEX_GOT_32_6_X:
+ case ELF::R_HEX_GOT_16_X:
+ case ELF::R_HEX_GOT_11_X:
+ case ELF::R_HEX_GOTREL_32_6_X:
+ case ELF::R_HEX_GOTREL_16_X:
+ case ELF::R_HEX_GOTREL_11_X:
+ return true;
+ }
+}
+
static bool isTLSX86(uint32_t Type) {
switch (Type) {
default:
@@ -614,6 +741,17 @@ static bool isTLSRISCV(uint32_t Type) {
}
}
+static bool isTLSHexagon(uint32_t Type) {
+ switch (Type) {
+ case ELF::R_HEX_TPREL_32_6_X:
+ case ELF::R_HEX_TPREL_16_X:
+ case ELF::R_HEX_TPREL_11_X:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool isPCRelativeX86(uint32_t Type) {
switch (Type) {
default:
@@ -716,12 +854,60 @@ static bool isPCRelativeRISCV(uint32_t Type) {
}
}
+static bool isPCRelativeHexagon(uint32_t Type) {
+ switch (Type) {
+ default:
+ llvm_unreachable("Unknown relocation type");
+ case ELF::R_HEX_32:
+ case ELF::R_HEX_16:
+ case ELF::R_HEX_8:
+ case ELF::R_HEX_LO16:
+ case ELF::R_HEX_HI16:
+ case ELF::R_HEX_32_6_X:
+ case ELF::R_HEX_16_X:
+ case ELF::R_HEX_12_X:
+ case ELF::R_HEX_11_X:
+ case ELF::R_HEX_10_X:
+ case ELF::R_HEX_9_X:
+ case ELF::R_HEX_8_X:
+ case ELF::R_HEX_7_X:
+ case ELF::R_HEX_6_X:
+ case ELF::R_HEX_GOT_32_6_X:
+ case ELF::R_HEX_GOT_16_X:
+ case ELF::R_HEX_GOT_11_X:
+ case ELF::R_HEX_GOTREL_32_6_X:
+ case ELF::R_HEX_GOTREL_16_X:
+ case ELF::R_HEX_GOTREL_11_X:
+ case ELF::R_HEX_TPREL_32_6_X:
+ case ELF::R_HEX_TPREL_16_X:
+ case ELF::R_HEX_TPREL_11_X:
+ return false;
+ case ELF::R_HEX_6_PCREL_X:
+ case ELF::R_HEX_B22_PCREL:
+ case ELF::R_HEX_B15_PCREL:
+ case ELF::R_HEX_B7_PCREL:
+ case ELF::R_HEX_B13_PCREL:
+ case ELF::R_HEX_B9_PCREL:
+ case ELF::R_HEX_B32_PCREL_X:
+ case ELF::R_HEX_B22_PCREL_X:
+ case ELF::R_HEX_B15_PCREL_X:
+ case ELF::R_HEX_B13_PCREL_X:
+ case ELF::R_HEX_B9_PCREL_X:
+ case ELF::R_HEX_B7_PCREL_X:
+ case ELF::R_HEX_32_PCREL:
+ case ELF::R_HEX_PLT_B22_PCREL:
+ return true;
+ }
+}
+
bool Relocation::isSupported(uint32_t Type) {
switch (Arch) {
default:
return false;
case Triple::aarch64:
return isSupportedAArch64(Type);
+ case Triple::hexagon:
+ return isSupportedHexagon(Type);
case Triple::riscv64:
return isSupportedRISCV(Type);
case Triple::x86_64:
@@ -735,6 +921,8 @@ size_t Relocation::getSizeForType(uint32_t Type) {
llvm_unreachable("Unsupported architecture");
case Triple::aarch64:
return getSizeForTypeAArch64(Type);
+ case Triple::hexagon:
+ return getSizeForTypeHexagon(Type);
case Triple::riscv64:
return getSizeForTypeRISCV(Type);
case Triple::x86_64:
@@ -748,6 +936,8 @@ bool Relocation::skipRelocationType(uint32_t Type) {
llvm_unreachable("Unsupported architecture");
case Triple::aarch64:
return skipRelocationTypeAArch64(Type);
+ case Triple::hexagon:
+ return skipRelocationTypeHexagon(Type);
case Triple::riscv64:
return skipRelocationTypeRISCV(Type);
case Triple::x86_64:
@@ -761,6 +951,8 @@ uint64_t Relocation::encodeValue(uint32_t Type, uint64_t Value, uint64_t PC) {
llvm_unreachable("Unsupported architectur...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/192189
More information about the llvm-commits
mailing list