[lldb] [llvm] [lldb][RISCV] function calls support in lldb expressions (PR #99336)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 19 07:31:58 PDT 2024


https://github.com/dlav-sc updated https://github.com/llvm/llvm-project/pull/99336

>From 2fc70cf82a7e67bde2d4fb35d2457d2812b34273 Mon Sep 17 00:00:00 2001
From: Daniil Avdeev <daniil.avdeev at syntacore.com>
Date: Thu, 11 Jul 2024 11:21:36 +0000
Subject: [PATCH 1/4] [lldb][RISCV] add jitted function calls to ABI

Function calls support in LLDB expressions for RISCV: 1 of 5

Augments corresponding functionality to RISCV ABI, which allows to jit
lldb expressions and thus make function calls inside them. Only function
calls with integer and void function arguments and return value are
supported.
---
 .../Plugins/ABI/RISCV/ABISysV_riscv.cpp       | 91 +++++++++++++++++--
 1 file changed, 84 insertions(+), 7 deletions(-)

diff --git a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp
index de304183f67175..38d452b6ab560c 100644
--- a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp
+++ b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp
@@ -10,7 +10,9 @@
 
 #include <array>
 #include <limits>
+#include <sstream>
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/DerivedTypes.h"
 
 #include "Utility/RISCV_DWARF_Registers.h"
@@ -20,6 +22,7 @@
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/Target/StackFrame.h"
 #include "lldb/Target/Thread.h"
+#include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/RegisterValue.h"
 
 #define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
@@ -120,6 +123,10 @@ static const std::array<RegisterInfo, 33> g_register_infos = {
 } // namespace dwarf
 } // namespace
 
+// Number of argument registers (the base integer calling convention
+// provides 8 argument registers, a0-a7)
+static constexpr size_t g_regs_for_args_count = 8U;
+
 const RegisterInfo *ABISysV_riscv::GetRegisterInfoArray(uint32_t &count) {
   count = dwarf::g_register_infos.size();
   return dwarf::g_register_infos.data();
@@ -164,11 +171,81 @@ TotalArgsSizeInWords(bool is_rv64,
   return total_size;
 }
 
+static bool UpdateRegister(RegisterContext *reg_ctx,
+                           const lldb::RegisterKind reg_kind,
+                           const uint32_t reg_num, const addr_t value) {
+  Log *log = GetLog(LLDBLog::Expressions);
+
+  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(reg_kind, reg_num);
+
+  LLDB_LOG(log, "Writing {0}: 0x{1:x}", reg_info->name,
+           static_cast<uint64_t>(value));
+  if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, value)) {
+    LLDB_LOG(log, "Writing {0}: failed", reg_info->name);
+    return false;
+  }
+  return true;
+}
+
+static void LogInitInfo(Log &log, const Thread &thread, addr_t sp,
+                        addr_t func_addr, addr_t return_addr,
+                        const llvm::ArrayRef<addr_t> args) {
+  std::stringstream ss;
+  ss << "ABISysV_riscv::PrepareTrivialCall"
+     << " (tid = 0x" << std::hex << thread.GetID() << ", sp = 0x" << sp
+     << ", func_addr = 0x" << func_addr << ", return_addr = 0x" << return_addr;
+
+  for (auto [idx, arg] : enumerate(args))
+    ss << ", arg" << std::dec << idx << " = 0x" << std::hex << arg;
+  ss << ")";
+  log.PutString(ss.str());
+}
+
 bool ABISysV_riscv::PrepareTrivialCall(Thread &thread, addr_t sp,
                                        addr_t func_addr, addr_t return_addr,
                                        llvm::ArrayRef<addr_t> args) const {
-  // TODO: Implement
-  return false;
+  Log *log = GetLog(LLDBLog::Expressions);
+  if (log)
+    LogInitInfo(*log, thread, sp, func_addr, return_addr, args);
+
+  const auto reg_ctx_sp = thread.GetRegisterContext();
+  if (!reg_ctx_sp) {
+    LLDB_LOG(log, "Failed to get RegisterContext");
+    return false;
+  }
+
+  if (args.size() > g_regs_for_args_count) {
+    LLDB_LOG(log, "Function has {0} arguments, but only {1} are allowed!",
+             args.size(), g_regs_for_args_count);
+    return false;
+  }
+
+  // Write arguments to registers
+  for (auto [idx, arg] : enumerate(args)) {
+    const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(
+        eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + idx);
+    LLDB_LOG(log, "About to write arg{0} (0x{1:x}) into {2}", idx, arg,
+             reg_info->name);
+
+    if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) {
+      LLDB_LOG(log, "Failed to write arg{0} (0x{1:x}) into {2}", idx, arg,
+               reg_info->name);
+      return false;
+    }
+  }
+
+  if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
+                      LLDB_REGNUM_GENERIC_PC, func_addr))
+    return false;
+  if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
+                      LLDB_REGNUM_GENERIC_SP, sp))
+    return false;
+  if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
+                      LLDB_REGNUM_GENERIC_RA, return_addr))
+    return false;
+
+  LLDB_LOG(log, "ABISysV_riscv::{0}() success", __FUNCTION__);
+  return true;
 }
 
 bool ABISysV_riscv::PrepareTrivialCall(
@@ -222,14 +299,14 @@ bool ABISysV_riscv::PrepareTrivialCall(
   assert(prototype.getFunctionNumParams() == args.size());
 
   const size_t num_args = args.size();
-  const size_t regs_for_args_count = 8U;
   const size_t num_args_in_regs =
-      num_args > regs_for_args_count ?  regs_for_args_count : num_args;
+      num_args > g_regs_for_args_count ? g_regs_for_args_count : num_args;
 
   // Number of arguments passed on stack.
   size_t args_size = TotalArgsSizeInWords(m_is_rv64, args);
-  auto on_stack =
-      args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count;
+  auto on_stack = args_size <= g_regs_for_args_count
+                      ? 0
+                      : args_size - g_regs_for_args_count;
   auto offset = on_stack * word_size;
 
   uint8_t reg_value[8];
@@ -260,7 +337,7 @@ bool ABISysV_riscv::PrepareTrivialCall(
       ++reg_index;
     }
 
-    if (reg_index < regs_for_args_count || size == 0)
+    if (reg_index < g_regs_for_args_count || size == 0)
       continue;
 
     // Remaining arguments are passed on the stack.

>From 994fdb1f63cf982dc62e8ad2ffdca5d37d899453 Mon Sep 17 00:00:00 2001
From: Daniil Avdeev <daniil.avdeev at syntacore.com>
Date: Thu, 11 Jul 2024 11:23:39 +0000
Subject: [PATCH 2/4] [lldb][RISCV] add JIT relocations resolver

Function calls support in LLDB expressions for RISCV: 2 of 5

Adds required RISCV relocations resolving functionality in lldb
ExecutionEngine.
---
 .../RuntimeDyld/RuntimeDyldELF.cpp            | 155 +++++++++++++++++-
 .../RuntimeDyld/RuntimeDyldELF.h              |   7 +
 2 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index b4e088d5339466..92f37c22ae5132 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -1011,6 +1011,135 @@ void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section,
   }
 }
 
+static void applyUTypeImmRISCV(uint8_t *InstrAddr, uint32_t Imm) {
+  uint32_t UpperImm = (Imm + 0x800) & 0xfffff000;
+  auto Instr = support::ulittle32_t::ref(InstrAddr);
+  Instr = (Instr & 0xfff) | UpperImm;
+}
+
+static void applyITypeImmRISCV(uint8_t *InstrAddr, uint32_t Imm) {
+  uint32_t LowerImm = Imm & 0xfff;
+  auto Instr = support::ulittle32_t::ref(InstrAddr);
+  Instr = (Instr & 0xfffff) | (LowerImm << 20);
+}
+
+void RuntimeDyldELF::resolveRISCVRelocation(const SectionEntry &Section,
+                                            uint64_t Offset, uint64_t Value,
+                                            uint32_t Type, int64_t Addend,
+                                            SID SectionID) {
+  switch (Type) {
+  default: {
+    std::string Err = "Unimplemented reloc type: " + std::to_string(Type);
+    llvm::report_fatal_error(Err.c_str());
+  }
+    // 32-bit PC-relative function call, macros call, tail (PIC)
+    // Write first 20 bits of 32 bit value to the auipc instruction
+    // Last 12 bits to the jalr instruction
+  case ELF::R_RISCV_CALL:
+  case ELF::R_RISCV_CALL_PLT: {
+    uint64_t P = Section.getLoadAddressWithOffset(Offset);
+    uint64_t PCOffset = Value + Addend - P;
+    applyUTypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
+    applyITypeImmRISCV(Section.getAddressWithOffset(Offset + 4), PCOffset);
+    break;
+  }
+    // High 20 bits of 32-bit absolute address, %hi(symbol)
+  case ELF::R_RISCV_HI20: {
+    uint64_t PCOffset = Value + Addend;
+    applyUTypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
+    break;
+  }
+    // Low 12 bits of 32-bit absolute address, %lo(symbol)
+  case ELF::R_RISCV_LO12_I: {
+    uint64_t PCOffset = Value + Addend;
+    applyITypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
+    break;
+  }
+    // High 20 bits of 32-bit PC-relative reference, %pcrel_hi(symbol)
+  case ELF::R_RISCV_GOT_HI20:
+  case ELF::R_RISCV_PCREL_HI20: {
+    uint64_t P = Section.getLoadAddressWithOffset(Offset);
+    uint64_t PCOffset = Value + Addend - P;
+    applyUTypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
+    break;
+  }
+
+    // label:
+    //    auipc      a0, %pcrel_hi(symbol)    // R_RISCV_PCREL_HI20
+    //    addi       a0, a0, %pcrel_lo(label) // R_RISCV_PCREL_LO12_I
+    //
+    // The low 12 bits of relative address between pc and symbol.
+    // The symbol is related to the high part instruction which is marked by
+    // label.
+  case ELF::R_RISCV_PCREL_LO12_I: {
+    for (auto &&PendingReloc : PendingRelocs) {
+      const RelocationValueRef &MatchingValue = PendingReloc.first;
+      RelocationEntry &Reloc = PendingReloc.second;
+      uint64_t HIRelocPC =
+          getSectionLoadAddress(Reloc.SectionID) + Reloc.Offset;
+      if (Value + Addend == HIRelocPC) {
+        uint64_t Symbol = getSectionLoadAddress(MatchingValue.SectionID) +
+                          MatchingValue.Addend;
+        auto PCOffset = Symbol - HIRelocPC;
+        applyITypeImmRISCV(Section.getAddressWithOffset(Offset), PCOffset);
+        return;
+      }
+    }
+
+    llvm::report_fatal_error(
+        "R_RISCV_PCREL_LO12_I without matching R_RISCV_PCREL_HI20");
+  }
+  case ELF::R_RISCV_32_PCREL: {
+    uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
+    int64_t RealOffset = Value + Addend - FinalAddress;
+    int32_t TruncOffset = Lo_32(RealOffset);
+    support::ulittle32_t::ref(Section.getAddressWithOffset(Offset)) =
+        TruncOffset;
+    break;
+  }
+  case ELF::R_RISCV_32: {
+    auto Ref = support::ulittle32_t::ref(Section.getAddressWithOffset(Offset));
+    Ref = Value + Addend;
+    break;
+  }
+  case ELF::R_RISCV_64: {
+    auto Ref = support::ulittle64_t::ref(Section.getAddressWithOffset(Offset));
+    Ref = Value + Addend;
+    break;
+  }
+  case ELF::R_RISCV_ADD16: {
+    auto Ref = support::ulittle16_t::ref(Section.getAddressWithOffset(Offset));
+    Ref = Ref + Value + Addend;
+    break;
+  }
+  case ELF::R_RISCV_ADD32: {
+    auto Ref = support::ulittle32_t::ref(Section.getAddressWithOffset(Offset));
+    Ref = Ref + Value + Addend;
+    break;
+  }
+  case ELF::R_RISCV_ADD64: {
+    auto Ref = support::ulittle64_t::ref(Section.getAddressWithOffset(Offset));
+    Ref = Ref + Value + Addend;
+    break;
+  }
+  case ELF::R_RISCV_SUB16: {
+    auto Ref = support::ulittle16_t::ref(Section.getAddressWithOffset(Offset));
+    Ref = Ref - Value - Addend;
+    break;
+  }
+  case ELF::R_RISCV_SUB32: {
+    auto Ref = support::ulittle32_t::ref(Section.getAddressWithOffset(Offset));
+    Ref = Ref - Value - Addend;
+    break;
+  }
+  case ELF::R_RISCV_SUB64: {
+    auto Ref = support::ulittle64_t::ref(Section.getAddressWithOffset(Offset));
+    Ref = Ref - Value - Addend;
+    break;
+  }
+  }
+}
+
 // The target location for the relocation is described by RE.SectionID and
 // RE.Offset.  RE.SectionID can be used to find the SectionEntry.  Each
 // SectionEntry has three members describing its location.
@@ -1076,12 +1205,17 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
   case Triple::bpfeb:
     resolveBPFRelocation(Section, Offset, Value, Type, Addend);
     break;
+  case Triple::riscv32: // Fall through.
+  case Triple::riscv64:
+    resolveRISCVRelocation(Section, Offset, Value, Type, Addend, SectionID);
+    break;
   default:
     llvm_unreachable("Unsupported CPU type!");
   }
 }
 
-void *RuntimeDyldELF::computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const {
+void *RuntimeDyldELF::computePlaceholderAddress(unsigned SectionID,
+                                                uint64_t Offset) const {
   return (void *)(Sections[SectionID].getObjAddress() + Offset);
 }
 
@@ -1870,7 +2004,8 @@ RuntimeDyldELF::processRelocationRef(
       Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset));
       processSimpleRelocation(SectionID, Offset, RelType, Value);
     } else if (RelType == ELF::R_X86_64_PC64) {
-      Value.Addend += support::ulittle64_t::ref(computePlaceholderAddress(SectionID, Offset));
+      Value.Addend += support::ulittle64_t::ref(
+          computePlaceholderAddress(SectionID, Offset));
       processSimpleRelocation(SectionID, Offset, RelType, Value);
     } else if (RelType == ELF::R_X86_64_GOTTPOFF) {
       processX86_64GOTTPOFFRelocation(SectionID, Offset, Value, Addend);
@@ -1884,9 +2019,23 @@ RuntimeDyldELF::processRelocationRef(
     } else {
       processSimpleRelocation(SectionID, Offset, RelType, Value);
     }
+  } else if (Arch == Triple::riscv32 || Arch == Triple::riscv64) {
+    // *_LO12 relocation receive information about a symbol from the
+    // corresponding *_HI20 relocation, so we have to collect this information
+    // before resolving
+    if (RelType == ELF::R_RISCV_GOT_HI20 ||
+        RelType == ELF::R_RISCV_PCREL_HI20 ||
+        RelType == ELF::R_RISCV_TPREL_HI20 ||
+        RelType == ELF::R_RISCV_TLS_GD_HI20 ||
+        RelType == ELF::R_RISCV_TLS_GOT_HI20) {
+      RelocationEntry RE(SectionID, Offset, RelType, Addend);
+      PendingRelocs.push_back({Value, RE});
+    }
+    processSimpleRelocation(SectionID, Offset, RelType, Value);
   } else {
     if (Arch == Triple::x86) {
-      Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset));
+      Value.Addend += support::ulittle32_t::ref(
+          computePlaceholderAddress(SectionID, Offset));
     }
     processSimpleRelocation(SectionID, Offset, RelType, Value);
   }
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
index 1b90013dfe2df9..97517884654bc5 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
@@ -58,6 +58,10 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
   void resolveBPFRelocation(const SectionEntry &Section, uint64_t Offset,
                             uint64_t Value, uint32_t Type, int64_t Addend);
 
+  void resolveRISCVRelocation(const SectionEntry &Section, uint64_t Offset,
+                              uint64_t Value, uint32_t Type, int64_t Addend,
+                              SID SectionID);
+
   unsigned getMaxStubSize() const override {
     if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be)
       return 20; // movz; movk; movk; movk; br
@@ -146,6 +150,9 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
 
   // *HI16 relocations will be added for resolving when we find matching
   // *LO16 part. (Mips specific)
+  //
+  // *HI20 relocations will be added for resolving when we find matching
+  // *LO12 part. (RISC-V specific)
   SmallVector<std::pair<RelocationValueRef, RelocationEntry>, 8> PendingRelocs;
 
   // When a module is loaded we save the SectionID of the EH frame section

>From e25187ef340957d28cd8610dde437da28e23009c Mon Sep 17 00:00:00 2001
From: Daniil Avdeev <daniil.avdeev at syntacore.com>
Date: Tue, 10 Sep 2024 19:34:43 +0300
Subject: [PATCH 3/4] [lldb][RISCV] RISC-V large code model in lldb expressions

Function calls support in LLDB expressions for RISCV: 3 of 5

This patch sets large code model in MCJIT settings for RISC-V 64-bit targets
that allows to make assembly jumps at any 64bit address. This is needed,
because resulted jitted code may contain more that +-2GB jumps, that are
not available in RISC-V with medium code model.
---
 lldb/source/Expression/IRExecutionUnit.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index 15ca2ddbbae046..baf70cbccc8c5c 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -277,6 +277,12 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr,
       .setMCJITMemoryManager(std::make_unique<MemoryManager>(*this))
       .setOptLevel(llvm::CodeGenOptLevel::Less);
 
+  // Resulted jitted code can be placed too far from the code in the binary
+  // and thus can contain more than +-2GB jumps, that are not available
+  // in RISC-V without large code model.
+  if (triple.isRISCV64())
+    builder.setCodeModel(llvm::CodeModel::Large);
+
   llvm::StringRef mArch;
   llvm::StringRef mCPU;
   llvm::SmallVector<std::string, 0> mAttrs;

>From b9275b35bee921bdd84339a983fbf4214c9ca3a5 Mon Sep 17 00:00:00 2001
From: Daniil Avdeev <daniil.avdeev at syntacore.com>
Date: Tue, 10 Sep 2024 19:30:11 +0300
Subject: [PATCH 4/4] [lldb][RISCV] doubles support in lldb expressions

Function calls support in LLDB expressions for RISCV: 4 of 5

This patch adds desired feature flags in MCJIT compiler to enable
hard-float instructions if target supports them and allows to use floats
and doubles in lldb expressions.
---
 .../Clang/ClangExpressionParser.cpp           | 69 +++++++++++++++----
 1 file changed, 54 insertions(+), 15 deletions(-)

diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 2fe3c0460aa7f8..12bca8cecb7732 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -43,6 +43,7 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/TargetParser/Triple.h"
 
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
@@ -407,24 +408,50 @@ static void SetupDefaultClangDiagnostics(CompilerInstance &compiler) {
 /// \return
 ///     A string representing target ABI for the current architecture.
 static std::string GetClangTargetABI(const ArchSpec &target_arch) {
-  std::string abi;
-
   if (target_arch.IsMIPS()) {
     switch (target_arch.GetFlags() & ArchSpec::eMIPSABI_mask) {
     case ArchSpec::eMIPSABI_N64:
-      abi = "n64";
-      break;
+      return "n64";
     case ArchSpec::eMIPSABI_N32:
-      abi = "n32";
-      break;
+      return "n32";
     case ArchSpec::eMIPSABI_O32:
-      abi = "o32";
-      break;
+      return "o32";
     default:
-      break;
+      return {};
     }
   }
-  return abi;
+
+  if (target_arch.GetTriple().isRISCV64()) {
+    switch (target_arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask) {
+    case ArchSpec::eRISCV_float_abi_soft:
+      return "lp64";
+    case ArchSpec::eRISCV_float_abi_single:
+      return "lp64f";
+    case ArchSpec::eRISCV_float_abi_double:
+      return "lp64d";
+    case ArchSpec::eRISCV_float_abi_quad:
+      return "lp64q";
+    default:
+      return {};
+    }
+  }
+
+  if (target_arch.GetTriple().isRISCV32()) {
+    switch (target_arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask) {
+    case ArchSpec::eRISCV_float_abi_soft:
+      return "ilp32";
+    case ArchSpec::eRISCV_float_abi_single:
+      return "ilp32f";
+    case ArchSpec::eRISCV_float_abi_double:
+      return "ilp32d";
+    case ArchSpec::eRISCV_float_abi_soft | ArchSpec::eRISCV_rve:
+      return "ilp32e";
+    default:
+      return {};
+    }
+  }
+
+  return {};
 }
 
 static void SetupTargetOpts(CompilerInstance &compiler,
@@ -471,6 +498,18 @@ static void SetupTargetOpts(CompilerInstance &compiler,
   // Set the target ABI
   if (std::string abi = GetClangTargetABI(target_arch); !abi.empty())
     compiler.getTargetOpts().ABI = std::move(abi);
+
+  if ((target_machine == llvm::Triple::riscv64 &&
+       compiler.getTargetOpts().ABI == "lp64f") ||
+      (target_machine == llvm::Triple::riscv32 &&
+       compiler.getTargetOpts().ABI == "ilp32f"))
+    compiler.getTargetOpts().FeaturesAsWritten.emplace_back("+f");
+
+  if ((target_machine == llvm::Triple::riscv64 &&
+       compiler.getTargetOpts().ABI == "lp64d") ||
+      (target_machine == llvm::Triple::riscv32 &&
+       compiler.getTargetOpts().ABI == "ilp32d"))
+    compiler.getTargetOpts().FeaturesAsWritten.emplace_back("+d");
 }
 
 static void SetupLangOpts(CompilerInstance &compiler,
@@ -722,7 +761,7 @@ ClangExpressionParser::ClangExpressionParser(
   m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
   m_compiler->getCodeGenOpts().InstrumentFunctions = false;
   m_compiler->getCodeGenOpts().setFramePointer(
-                                    CodeGenOptions::FramePointerKind::All);
+      CodeGenOptions::FramePointerKind::All);
   if (generate_debug_info)
     m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
   else
@@ -736,7 +775,7 @@ ClangExpressionParser::ClangExpressionParser(
   // FIXME: We shouldn't need to do this, the target should be immutable once
   // created. This complexity should be lifted elsewhere.
   m_compiler->getTarget().adjust(m_compiler->getDiagnostics(),
-		                 m_compiler->getLangOpts());
+                                 m_compiler->getLangOpts());
 
   // 5. Set up the diagnostic buffer for reporting errors
 
@@ -1156,8 +1195,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
           if (auto fileEntry = m_compiler->getFileManager().getOptionalFileRef(
                   result_path)) {
             source_mgr.setMainFileID(source_mgr.createFileID(
-                *fileEntry,
-                SourceLocation(), SrcMgr::C_User));
+                *fileEntry, SourceLocation(), SrcMgr::C_User));
             created_main_file = true;
           }
         }
@@ -1504,7 +1542,8 @@ lldb_private::Status ClangExpressionParser::DoPrepareForExecution(
 
           DiagnosticManager install_diags;
           if (Error Err = dynamic_checkers->Install(install_diags, exe_ctx)) {
-            std::string ErrMsg = "couldn't install checkers: " + toString(std::move(Err));
+            std::string ErrMsg =
+                "couldn't install checkers: " + toString(std::move(Err));
             if (install_diags.Diagnostics().size())
               ErrMsg = ErrMsg + "\n" + install_diags.GetString().c_str();
             err = Status(ErrMsg);



More information about the llvm-commits mailing list