[llvm] [BOLT][Instrumentation] Initial instrumentation support for RISCV64 (PR #133882)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 15 16:16:52 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-bolt
Author: wangjue (WangJee)
<details>
<summary>Changes</summary>
This patch adds code generation for RISCV64 instrumentation.The work
involved includes the following three points:
a) Implements support for instrumenting direct function call and jump
on RISC-V which relies on , Atomic instructions
(used to increment counters) are only available on RISC-V when the A
extension is used.
b) Implements support for instrumenting direct function inderect call
by implementing the createInstrumentedIndCallHandlerEntryBB and
createInstrumentedIndCallHandlerExitBB interfaces. In this process, we
need to accurately record the target address and IndCallID to ensure
the correct recording of the indirect call counters.
c)Implemented the RISCV64 Bolt runtime library, implemented some system
call interfaces through embedded assembly. Get the difference between
runtime addrress of .text section andstatic address in section header
table, which in turn can be used to search for indirect call description.
However, the community code currently has problems with relocation in
some scenarios, but this has nothing to do with instrumentation. We
may continue to submit patches to fix the related bugs.
---
Patch is 45.31 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133882.diff
11 Files Affected:
- (modified) bolt/CMakeLists.txt (+2-1)
- (modified) bolt/lib/Core/Relocation.cpp (+4)
- (modified) bolt/lib/Rewrite/RewriteInstance.cpp (+1-1)
- (modified) bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp (+378)
- (modified) bolt/runtime/CMakeLists.txt (+10-4)
- (modified) bolt/runtime/common.h (+3-1)
- (modified) bolt/runtime/instr.cpp (+48)
- (added) bolt/runtime/sys_riscv64.h (+460)
- (added) bolt/test/runtime/RISCV/basic-instrumentation.s (+33)
- (added) bolt/test/runtime/RISCV/instrumentation-ind-call.c (+39)
- (added) bolt/test/runtime/RISCV/lit.local.cfg (+2)
``````````diff
diff --git a/bolt/CMakeLists.txt b/bolt/CMakeLists.txt
index 73c3ab54722e9..52c796518ac05 100644
--- a/bolt/CMakeLists.txt
+++ b/bolt/CMakeLists.txt
@@ -82,7 +82,8 @@ endforeach()
set(BOLT_ENABLE_RUNTIME_default OFF)
if ((CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
- OR CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)$")
+ OR CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)$"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
AND (CMAKE_SYSTEM_NAME STREQUAL "Linux"
OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
AND (NOT CMAKE_CROSSCOMPILING))
diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp
index ff1681f823987..f099dfa46f3d4 100644
--- a/bolt/lib/Core/Relocation.cpp
+++ b/bolt/lib/Core/Relocation.cpp
@@ -123,6 +123,7 @@ static bool isSupportedRISCV(uint32_t Type) {
case ELF::R_RISCV_LO12_S:
case ELF::R_RISCV_64:
case ELF::R_RISCV_TLS_GOT_HI20:
+ case ELF::R_RISCV_TLS_GD_HI20:
case ELF::R_RISCV_TPREL_HI20:
case ELF::R_RISCV_TPREL_ADD:
case ELF::R_RISCV_TPREL_LO12_I:
@@ -236,6 +237,7 @@ static size_t getSizeForTypeRISCV(uint32_t Type) {
case ELF::R_RISCV_64:
case ELF::R_RISCV_GOT_HI20:
case ELF::R_RISCV_TLS_GOT_HI20:
+ case ELF::R_RISCV_TLS_GD_HI20:
// See extractValueRISCV for why this is necessary.
return 8;
}
@@ -491,6 +493,7 @@ static uint64_t extractValueRISCV(uint32_t Type, uint64_t Contents,
return extractBImmRISCV(Contents);
case ELF::R_RISCV_GOT_HI20:
case ELF::R_RISCV_TLS_GOT_HI20:
+ case ELF::R_RISCV_TLS_GD_HI20:
// We need to know the exact address of the GOT entry so we extract the
// value from both the AUIPC and L[D|W]. We cannot rely on the symbol in the
// relocation for this since it simply refers to the object that is stored
@@ -707,6 +710,7 @@ static bool isPCRelativeRISCV(uint32_t Type) {
case ELF::R_RISCV_RVC_BRANCH:
case ELF::R_RISCV_32_PCREL:
case ELF::R_RISCV_TLS_GOT_HI20:
+ case ELF::R_RISCV_TLS_GD_HI20:
return true;
}
}
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index a03df3de39e83..ab7685fd24783 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -2931,7 +2931,7 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
// of sections and whose symbol address is not really what should be
// encoded in the instruction). So we essentially disabled this check
// for AArch64 and live with bogus names for objects.
- assert((IsAArch64 || IsSectionRelocation ||
+ assert((IsAArch64 || BC->isRISCV() || IsSectionRelocation ||
BD->nameStartsWith(SymbolName) ||
BD->nameStartsWith("PG" + SymbolName) ||
(BD->nameStartsWith("ANONYMOUS") &&
diff --git a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
index 4320c679acd54..0e27d29019e95 100644
--- a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
+++ b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
@@ -14,7 +14,9 @@
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "bolt/Core/MCPlusBuilder.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
@@ -72,6 +74,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
case ELF::R_RISCV_LO12_I:
case ELF::R_RISCV_LO12_S:
case ELF::R_RISCV_TLS_GOT_HI20:
+ case ELF::R_RISCV_TLS_GD_HI20:
return true;
default:
llvm_unreachable("Unexpected RISCV relocation type in code");
@@ -252,6 +255,11 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
return createCall(RISCV::PseudoCALL, Inst, Target, Ctx);
}
+ void createLongTailCall(InstructionListType &Seq, const MCSymbol *Target,
+ MCContext *Ctx) override {
+ createShortJmp(Seq, Target, Ctx, /*IsTailCall*/ true);
+ }
+
void createTailCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) override {
return createCall(RISCV::PseudoTAIL, Inst, Target, Ctx);
@@ -424,6 +432,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
return Expr;
case ELF::R_RISCV_GOT_HI20:
case ELF::R_RISCV_TLS_GOT_HI20:
+ case ELF::R_RISCV_TLS_GD_HI20:
// The GOT is reused so no need to create GOT relocations
case ELF::R_RISCV_PCREL_HI20:
return RISCVMCExpr::create(Expr, RISCVMCExpr::VK_PCREL_HI, Ctx);
@@ -483,6 +492,375 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
return 2;
return 4;
}
+
+ void createStackPointerIncrement(
+ MCInst &Inst, int imm,
+ bool NoFlagsClobber = false /*unused for RISCV*/) const override {
+ Inst = MCInstBuilder(RISCV::ADDI)
+ .addReg(RISCV::X2)
+ .addReg(RISCV::X2)
+ .addImm(-imm);
+ }
+
+ void createStackPointerDecrement(
+ MCInst &Inst, int imm,
+ bool NoFlagsClobber = false /*unused for RISCV*/) const override {
+ Inst = MCInstBuilder(RISCV::ADDI)
+ .addReg(RISCV::X2)
+ .addReg(RISCV::X2)
+ .addImm(imm);
+ }
+
+ void loadReg(MCInst &Inst, MCPhysReg To, MCPhysReg From,
+ int64_t offset) const {
+ Inst = MCInstBuilder(RISCV::LD).addReg(To).addReg(From).addImm(offset);
+ }
+
+ void storeReg(MCInst &Inst, MCPhysReg From, MCPhysReg To,
+ int64_t offset) const {
+ Inst = MCInstBuilder(RISCV::SD).addReg(From).addReg(To).addImm(offset);
+ }
+
+ void spillRegs(InstructionListType &Insts,
+ const SmallVector<unsigned> &Regs) const {
+ Insts.emplace_back();
+ createStackPointerIncrement(Insts.back(), Regs.size() * 8);
+
+ int64_t Offset = 0;
+ for (auto Reg : Regs) {
+ Insts.emplace_back();
+ storeReg(Insts.back(), Reg, RISCV::X2, Offset);
+ Offset += 8;
+ }
+ }
+
+ void reloadRegs(InstructionListType &Insts,
+ const SmallVector<unsigned> &Regs) const {
+ int64_t Offset = 0;
+ for (auto Reg : Regs) {
+ Insts.emplace_back();
+ loadReg(Insts.back(), Reg, RISCV::X2, Offset);
+ Offset += 8;
+ }
+
+ Insts.emplace_back();
+ createStackPointerDecrement(Insts.back(), Regs.size() * 8);
+ }
+
+ void atomicAdd(MCInst &Inst, MCPhysReg RegAtomic, MCPhysReg RegTo,
+ MCPhysReg RegCnt) const {
+ Inst = MCInstBuilder(RISCV::AMOADD_D)
+ .addReg(RegAtomic)
+ .addReg(RegTo)
+ .addReg(RegCnt);
+ }
+
+ InstructionListType createCmpJE(MCPhysReg RegNo, MCPhysReg RegTmp,
+ const MCSymbol *Target,
+ MCContext *Ctx) const {
+ InstructionListType Insts;
+ Insts.emplace_back(
+ MCInstBuilder(RISCV::SUB).addReg(RegTmp).addReg(RegNo).addReg(RegNo));
+ Insts.emplace_back(MCInstBuilder(RISCV::BEQ)
+ .addReg(RegNo)
+ .addReg(RegTmp)
+ .addExpr(MCSymbolRefExpr::create(
+ Target, MCSymbolRefExpr::VK_None, *Ctx)));
+ return Insts;
+ }
+
+ void createTrap(MCInst &Inst) const override {
+ Inst.clear();
+ Inst.setOpcode(RISCV::EBREAK);
+ }
+
+ void createShortJmp(InstructionListType &Seq, const MCSymbol *Target,
+ MCContext *Ctx, bool IsTailCall) override {
+ // The sequence of instructions we create here is the following:
+ // auipc a5, hi20(Target)
+ // addi a5, a5, low12(Target)
+ // jr x5 => jalr x0, x5, 0
+ MCPhysReg Reg = RISCV::X5;
+ InstructionListType Insts = materializeAddress(Target, Ctx, Reg);
+ Insts.emplace_back();
+ MCInst &Inst = Insts.back();
+ Inst.clear();
+ Inst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Reg).addImm(0);
+ if (IsTailCall)
+ setTailCall(Inst);
+ Seq.swap(Insts);
+ }
+
+ InstructionListType createGetter(MCContext *Ctx, const char *name) const {
+ InstructionListType Insts(4);
+ MCSymbol *Locs = Ctx->getOrCreateSymbol(name);
+ InstructionListType Addr = materializeAddress(Locs, Ctx, RISCV::X10);
+ std::copy(Addr.begin(), Addr.end(), Insts.begin());
+ loadReg(Insts[2], RISCV::X10, RISCV::X10, 0);
+ createReturn(Insts[3]);
+ return Insts;
+ }
+
+ InstructionListType createIncMemory(MCPhysReg RegTo, MCPhysReg RegCnt,
+ MCPhysReg RegAtomic) const {
+ InstructionListType Insts;
+ Insts.emplace_back();
+ Insts.back() =
+ MCInstBuilder(RISCV::ADDI).addReg(RegCnt).addReg(RegAtomic).addImm(1);
+ Insts.emplace_back();
+ atomicAdd(Insts.back(), RegAtomic, RegTo, RegCnt);
+ return Insts;
+ }
+
+ InstructionListType materializeAddress(const MCSymbol *Target, MCContext *Ctx,
+ MCPhysReg RegName,
+ int64_t Addend = 0) const override {
+ // Get the symbol address by auipc + addi
+ InstructionListType Insts(2);
+ MCSymbol *AuipcLabel = Ctx->createNamedTempSymbol("pcrel_hi");
+ Insts[0] = MCInstBuilder(RISCV::AUIPC).addReg(RegName).addImm(0);
+ setOperandToSymbolRef(Insts[0], /* OpNum */ 1, Target, Addend, Ctx,
+ ELF::R_RISCV_PCREL_HI20);
+ setInstLabel(Insts[0], AuipcLabel);
+
+ Insts[1] =
+ MCInstBuilder(RISCV::ADDI).addReg(RegName).addReg(RegName).addImm(0);
+ setOperandToSymbolRef(Insts[1], /* OpNum */ 2, AuipcLabel, Addend, Ctx,
+ ELF::R_RISCV_PCREL_LO12_I);
+ return Insts;
+ }
+
+ InstructionListType
+ createInstrIncMemory(const MCSymbol *Target, MCContext *Ctx, bool IsLeaf,
+ unsigned CodePointerSize) const override {
+ // We need 2 scratch registers: one for the target address (x10), and one
+ // for the increment value (x11).
+ // addi sp, sp, -16
+ // sd x10, 0(sp)
+ // sd x11, 8(sp)
+ // la x10, target # 1: auipc x10, %pcrel_hi(target)
+ // # addi x10, x10, %pcrel_lo(1b)
+ // li x11, 1 # addi x11, zero, 1
+ // amoadd.d zero, x10, x11
+ // ld x10, 0(sp)
+ // ld x11, 8(sp)
+ // addi sp, sp, 16
+
+ InstructionListType Insts;
+ spillRegs(Insts, {RISCV::X10, RISCV::X11});
+ InstructionListType Addr = materializeAddress(Target, Ctx, RISCV::X10);
+ Insts.insert(Insts.end(), Addr.begin(), Addr.end());
+ InstructionListType IncInsts =
+ createIncMemory(RISCV::X10, RISCV::X11, RISCV::X0);
+ Insts.insert(Insts.end(), IncInsts.begin(), IncInsts.end());
+ reloadRegs(Insts, {RISCV::X10, RISCV::X11});
+ return Insts;
+ }
+
+ void createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx,
+ bool IsTailCall) override {
+ Inst.setOpcode(RISCV::JAL);
+ Inst.clear();
+ if (IsTailCall) {
+ Inst.addOperand(MCOperand::createReg(RISCV::X0));
+ Inst.addOperand(MCOperand::createExpr(getTargetExprFor(
+ Inst, MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx),
+ *Ctx, 0)));
+ convertJmpToTailCall(Inst);
+ } else {
+ Inst.addOperand(MCOperand::createReg(RISCV::X1));
+ Inst.addOperand(MCOperand::createExpr(getTargetExprFor(
+ Inst, MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx),
+ *Ctx, 0)));
+ }
+ }
+
+ void createIndirectCallInst(MCInst &Inst, bool IsTailCall, MCPhysReg Reg,
+ int64_t Disp) const {
+ Inst.clear();
+ Inst.setOpcode(RISCV::JALR);
+ Inst.clear();
+ if (IsTailCall) {
+ Inst.addOperand(MCOperand::createReg(RISCV::X0));
+ Inst.addOperand(MCOperand::createReg(Reg));
+ Inst.addOperand(MCOperand::createImm(Disp));
+ } else {
+ Inst.addOperand(MCOperand::createReg(RISCV::X1));
+ Inst.addOperand(MCOperand::createReg(Reg));
+ Inst.addOperand(MCOperand::createImm(Disp));
+ }
+ }
+
+ InstructionListType
+ createInstrumentedIndCallHandlerEntryBB(const MCSymbol *InstrTrampoline,
+ const MCSymbol *IndCallHandler,
+ MCContext *Ctx) override {
+ // Code sequence used to check whether InstrTampoline was initialized
+ // and call it if so, returns via IndCallHandler
+ // sp -16(sp)
+ // sd x10, 0(sp)
+ // sd x11, 0(sp)
+ // la x10, InstrTrampoline -> auipc + addi
+ // ld x10, [x10]
+ // beq x10, x11, IndCallHandler
+ // sp -16(sp)
+ // sd x1, 0(sp)
+ // jalr x1,x10,0
+ // ld x1, [sp], #16
+ // sp 16(sp)
+ // jal x0, IndCallHandler
+
+ InstructionListType Insts;
+ spillRegs(Insts, {RISCV::X10, RISCV::X11});
+ InstructionListType Addr =
+ materializeAddress(InstrTrampoline, Ctx, RISCV::X10);
+ Insts.insert(Insts.end(), Addr.begin(), Addr.end());
+ Insts.emplace_back();
+ loadReg(Insts.back(), RISCV::X10, RISCV::X10, 0);
+ InstructionListType cmpJmp =
+ createCmpJE(RISCV::X10, RISCV::X11, IndCallHandler, Ctx);
+ Insts.insert(Insts.end(), cmpJmp.begin(), cmpJmp.end());
+ Insts.emplace_back();
+ createStackPointerIncrement(Insts.back(), 16);
+ Insts.emplace_back();
+ storeReg(Insts.back(), RISCV::X1, RISCV::X2, 0);
+ Insts.emplace_back();
+ createIndirectCallInst(Insts.back(), /*IsTailCall*/ false, RISCV::X10, 0);
+ Insts.emplace_back();
+ loadReg(Insts.back(), RISCV::X1, RISCV::X2, 0);
+ Insts.emplace_back();
+ createStackPointerDecrement(Insts.back(), 16);
+ Insts.emplace_back();
+ createDirectCall(Insts.back(), IndCallHandler, Ctx, /*IsTailCall*/ true);
+ return Insts;
+ }
+
+ InstructionListType createInstrumentedIndCallHandlerExitBB() const override {
+ InstructionListType Insts;
+ reloadRegs(Insts, {RISCV::X10, RISCV::X11});
+ Insts.emplace_back();
+ loadReg(Insts.back(), RISCV::X5, RISCV::X2, 0);
+ Insts.emplace_back();
+ createStackPointerDecrement(Insts.back(), 16);
+ reloadRegs(Insts, {RISCV::X10, RISCV::X11});
+ Insts.emplace_back();
+ createIndirectCallInst(Insts.back(), /*IsTailCall*/ true, RISCV::X5, 0);
+ return Insts;
+ }
+
+ InstructionListType
+ createInstrumentedIndTailCallHandlerExitBB() const override {
+ return createInstrumentedIndCallHandlerExitBB();
+ }
+
+ std::vector<MCInst> createSymbolTrampoline(const MCSymbol *TgtSym,
+ MCContext *Ctx) override {
+ std::vector<MCInst> Insts;
+ createShortJmp(Insts, TgtSym, Ctx, /*IsTailCall*/ true);
+ return Insts;
+ }
+
+ InstructionListType createNumCountersGetter(MCContext *Ctx) const override {
+ return createGetter(Ctx, "__bolt_num_counters");
+ }
+
+ InstructionListType
+ createInstrLocationsGetter(MCContext *Ctx) const override {
+ return createGetter(Ctx, "__bolt_instr_locations");
+ }
+
+ InstructionListType createInstrTablesGetter(MCContext *Ctx) const override {
+ return createGetter(Ctx, "__bolt_instr_tables");
+ }
+
+ InstructionListType createInstrNumFuncsGetter(MCContext *Ctx) const override {
+ return createGetter(Ctx, "__bolt_instr_num_funcs");
+ }
+
+ void convertIndirectCallToLoad(MCInst &Inst, MCPhysReg Reg,
+ MCPhysReg ZeroReg) const {
+ bool IsTailCall = isTailCall(Inst);
+ if (IsTailCall)
+ removeAnnotation(Inst, MCPlus::MCAnnotation::kTailCall);
+ Inst.setOpcode(RISCV::ADD);
+ Inst.insert(Inst.begin(), MCOperand::createReg(Reg));
+ Inst.insert(Inst.begin() + 1, MCOperand::createReg(ZeroReg));
+ return;
+ }
+
+ InstructionListType createLoadImmediate(const MCPhysReg Dest,
+ uint64_t Imm) const override {
+ InstructionListType Insts;
+ // get IMM higher 32bit
+ Insts.emplace_back(
+ MCInstBuilder(RISCV::LUI).addReg(Dest).addImm((Imm >> 44) & 0xFFFFF));
+ Insts.emplace_back(MCInstBuilder(RISCV::LUI)
+ .addReg(RISCV::X5)
+ .addImm((Imm >> 32) & 0xFFF));
+ Insts.emplace_back(MCInstBuilder(RISCV::SRLI)
+ .addReg(RISCV::X5)
+ .addReg(RISCV::X5)
+ .addImm(12));
+ Insts.emplace_back(
+ MCInstBuilder(RISCV::OR).addReg(Dest).addReg(Dest).addReg(RISCV::X5));
+ Insts.emplace_back(
+ MCInstBuilder(RISCV::SLLI).addReg(Dest).addReg(Dest).addImm(32));
+
+ // get IMM lower 32bit
+ Insts.emplace_back(MCInstBuilder(RISCV::LUI)
+ .addReg(RISCV::X5)
+ .addImm((Imm >> 12) & 0xFFFFF));
+ Insts.emplace_back(
+ MCInstBuilder(RISCV::LUI).addReg(RISCV::X6).addImm((Imm)&0xFFF));
+ Insts.emplace_back(MCInstBuilder(RISCV::SRLI)
+ .addReg(RISCV::X6)
+ .addReg(RISCV::X6)
+ .addImm(12));
+ Insts.emplace_back(
+ MCInstBuilder(RISCV::OR).addReg(RISCV::X5).addReg(RISCV::X5).addReg(
+ RISCV::X6));
+
+ // get 64bit IMM
+ Insts.emplace_back(
+ MCInstBuilder(RISCV::OR).addReg(Dest).addReg(Dest).addReg(RISCV::X5));
+ return Insts;
+ }
+
+ InstructionListType createInstrumentedIndirectCall(MCInst &&CallInst,
+ MCSymbol *HandlerFuncAddr,
+ int CallSiteID,
+ MCContext *Ctx) override {
+ // Code sequence used to enter indirect call instrumentation helper:
+ // addi sp, sp, -0x10
+ // sd a0, 0x0(sp)
+ // sd a1, 0x8(sp)
+ // mov target x0 convertIndirectCallToLoad -> add a0, zero, target
+ // mov x1 CallSiteID createLoadImmediate
+ // addi sp, sp, -0x10
+ // sd a0, 0x0(sp)
+ // sd a1, 0x8(sp)
+ // la x0 *HandlerFuncAddr -> auipc + addi
+ // jalr x0
+
+ InstructionListType Insts;
+ spillRegs(Insts, {RISCV::X10, RISCV::X11});
+ Insts.emplace_back(CallInst);
+ convertIndirectCallToLoad(Insts.back(), RISCV::X10, RISCV::X0);
+ InstructionListType LoadImm = createLoadImmediate(RISCV::X11, CallSiteID);
+ Insts.insert(Insts.end(), LoadImm.begin(), LoadImm.end());
+ spillRegs(Insts, {RISCV::X10, RISCV::X11});
+ InstructionListType Addr =
+ materializeAddress(HandlerFuncAddr, Ctx, RISCV::X5);
+ Insts.insert(Insts.end(), Addr.begin(), Addr.end());
+ Insts.emplace_back();
+ createIndirectCallInst(Insts.back(), isTailCall(CallInst), RISCV::X5, 0);
+
+ // // Carry over metadata including tail call marker if present.
+ stripAnnotations(Insts.back());
+ moveAnnotations(std::move(CallInst), Insts.back());
+
+ return Insts;
+ }
};
} // end anonymous namespace
diff --git a/bolt/runtime/CMakeLists.txt b/bolt/runtime/CMakeLists.txt
index 0deb69a27d435..87cc44812da11 100644
--- a/bolt/runtime/CMakeLists.txt
+++ b/bolt/runtime/CMakeLists.txt
@@ -35,15 +35,21 @@ set(BOLT_RT_FLAGS
-fno-exceptions
-fno-rtti
-fno-stack-protector
- -fPIC
- -mgeneral-regs-only)
+ -fPIC)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
- set(BOLT_RT_FLAGS ${BOLT_RT_FLAGS} "-mno-sse")
+ set(BOLT_RT_FLAGS ${BOLT_RT_FLAGS}
+ -mno-sse
+ -mgeneral-regs-only)
+endif()
+if (CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64")
+ set(BOLT_RT_FLAGS ${BOLT_RT_FLAGS})
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
check_cxx_compiler_flag("-mno-outline-atomics" CXX_SUPPORTS_OUTLINE_ATOMICS)
if (CXX_SUPPORTS_OUTLINE_ATOMICS)
- set(BOLT_RT_FLAGS ${BOLT_RT_FLAGS} "-mno-outline-atomics")
+ set(BOLT_RT_FLAGS ${BOLT_RT_FLAGS}
+ -mno-outline-atomics
+ -mgeneral-regs-only)
endif()
endif()
diff --git a/bolt/runtime/common.h b/bolt/runtime/common.h
index 27d0830071067..3461f8c545f9f 100644
--- a/bolt/runtime/common.h
+++ b/bolt/runtime/common.h
@@ -153,10 +153,12 @@ struct timespec {
#if defined(__aarch64__) || defined(__arm64__)
#include "sys_aarch64.h"
+#elif defined(__riscv)
+#include "sys_riscv64.h"
#elif defined(__x86_64__)
#include "sys_x86_64.h"
#else
-#error "For AArch64/ARM64 and X86_64 only."
+#error "For AArch64/ARM64,X86_64 AND RISCV64 only."
#endif
constexpr uint32_t BufSize = 10240;
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/133882
More information about the llvm-commits
mailing list