[llvm] 0ad562b - [JITLink][RISCV] Initial Support RISCV64 in JITLink

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 23 08:47:49 PDT 2021


Author: luxufan
Date: 2021-07-23T23:47:30+08:00
New Revision: 0ad562b48bfd7a487eb38ceaa309cdd9a1ad87e7

URL: https://github.com/llvm/llvm-project/commit/0ad562b48bfd7a487eb38ceaa309cdd9a1ad87e7
DIFF: https://github.com/llvm/llvm-project/commit/0ad562b48bfd7a487eb38ceaa309cdd9a1ad87e7.diff

LOG: [JITLink][RISCV] Initial Support RISCV64 in JITLink

This patch is the initial support, it implements translation from object file to JIT link graph, and very few relocations were supported. Currently, the test file ELF_pc_indirect.s is passed, the HelloWorld program(compiled with mno-relax flag) can be linked correctly and run on instruction emulator correctly.

In the downstream implementation, I have implemented the GOT, PLT function, and EHFrame and some optimization will be implement soon. I will organize the code in to patches, then gradually send it to upstream.

Differential Revision: https://reviews.llvm.org/D105429

Added: 
    llvm/include/llvm/ExecutionEngine/JITLink/ELF_riscv.h
    llvm/include/llvm/ExecutionEngine/JITLink/riscv.h
    llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
    llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s

Modified: 
    llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
    llvm/lib/ExecutionEngine/JITLink/ELF.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_riscv.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_riscv.h
new file mode 100644
index 0000000000000..1339ab51cbb9c
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_riscv.h
@@ -0,0 +1,38 @@
+//===----- ELF_riscv.h - JIT link functions for ELF/riscv ----*- C++ -*----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+//
+// jit-link functions for ELF/riscv.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_ELF_RISCV_H
+#define LLVM_EXECUTIONENGINE_JITLINK_ELF_RISCV_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+namespace llvm {
+namespace jitlink {
+
+/// Create a LinkGraph from an ELF/riscv relocatable object
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_riscv(MemoryBufferRef ObjectBuffer);
+
+/// jit-link the given object buffer, which must be a ELF riscv object file.
+void link_ELF_riscv(std::unique_ptr<LinkGraph> G,
+                    std::unique_ptr<JITLinkContext> Ctx);
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_ELF_RISCV64_H

diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h
new file mode 100644
index 0000000000000..a4509f3888a4a
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h
@@ -0,0 +1,84 @@
+//===--  riscv.h  - Generic JITLink riscv edge kinds, utilities -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic utilities for graphs representing riscv objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_RISCV_H
+#define LLVM_EXECUTIONENGINE_JITLINK_RISCV_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+namespace llvm {
+namespace jitlink {
+namespace riscv {
+
+/// Represets riscv fixups
+enum EdgeKind_riscv : Edge::Kind {
+
+  // TODO: Capture and replace to generic fixups
+  /// A plain 32-bit pointer value relocation
+  ///
+  /// Fixup expression:
+  ///   Fixup <= Target + Addend : uint32
+  ///
+  R_RISCV_32 = Edge::FirstRelocation,
+
+  /// A plain 64-bit pointer value relocation
+  ///
+  /// Fixup expression:
+  ///   Fixup <- Target + Addend : uint32
+  ///
+  R_RISCV_64,
+
+  /// High 20 bits of 32-bit pointer value relocation
+  ///
+  /// Fixup expression
+  ///   Fixup <- (Target + Addend + 0x800) >> 12
+  R_RISCV_HI20,
+
+  /// Low 12 bits of 32-bit pointer value relocation
+  ///
+  /// Fixup expression
+  ///   Fixup <- (Target + Addend) & 0xFFF
+  R_RISCV_LO12_I,
+  /// High 20 bits of PC relative relocation
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target - Fixup + Addend + 0x800) >> 12
+  R_RISCV_PCREL_HI20,
+
+  /// Low 12 bits of PC relative relocation, used by I type instruction format
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target - Fixup + Addend) & 0xFFF
+  R_RISCV_PCREL_LO12_I,
+
+  /// Low 12 bits of PC relative relocation, used by S type instruction format
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target - Fixup + Addend) & 0xFFF
+  R_RISCV_PCREL_LO12_S,
+
+  /// PC relative call
+  ///
+  /// Fixup expression:
+  ///   Fixup <- (Target - Fixup + Addend)
+  R_RISCV_CALL
+
+};
+
+/// Returns a string name for the given riscv edge. For debugging purposes
+/// only
+const char *getEdgeKindName(Edge::Kind K);
+} // namespace riscv
+} // namespace jitlink
+} // namespace llvm
+
+#endif

diff  --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
index ab4b24abd492e..eedcdb96f8ce8 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
@@ -16,9 +16,11 @@ add_llvm_component_library(LLVMJITLink
 
   ELF.cpp
   ELFLinkGraphBuilder.cpp
+  ELF_riscv.cpp
   ELF_x86_64.cpp
 
   # Architectures:
+  riscv.cpp
   x86_64.cpp
 
   ADDITIONAL_HEADER_DIRS

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
index 3a270d8508152..252e44fe4a74f 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ExecutionEngine/JITLink/ELF.h"
 
 #include "llvm/BinaryFormat/ELF.h"
+#include "llvm/ExecutionEngine/JITLink/ELF_riscv.h"
 #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/Endian.h"
@@ -64,6 +65,8 @@ createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
     return TargetMachineArch.takeError();
 
   switch (*TargetMachineArch) {
+  case ELF::EM_RISCV:
+    return createLinkGraphFromELFObject_riscv(ObjectBuffer);
   case ELF::EM_X86_64:
     return createLinkGraphFromELFObject_x86_64(ObjectBuffer);
   default:
@@ -76,6 +79,10 @@ createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
 void link_ELF(std::unique_ptr<LinkGraph> G,
               std::unique_ptr<JITLinkContext> Ctx) {
   switch (G->getTargetTriple().getArch()) {
+  case Triple::riscv32:
+  case Triple::riscv64:
+    link_ELF_riscv(std::move(G), std::move(Ctx));
+    return;
   case Triple::x86_64:
     link_ELF_x86_64(std::move(G), std::move(Ctx));
     return;

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
new file mode 100644
index 0000000000000..d0e65ef1c3ac5
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
@@ -0,0 +1,315 @@
+//===------- ELF_riscv.cpp -JIT linker implementation for ELF/riscv -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// ELF/riscv jit-link implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/ELF_riscv.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITLink/riscv.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFObjectFile.h"
+
+#include "ELFLinkGraphBuilder.h"
+#include "JITLinkGeneric.h"
+
+#define DEBUG_TYPE "jitlink"
+using namespace llvm;
+
+namespace llvm {
+namespace jitlink {
+
+static Expected<const Edge &> getRISCVPCRelHi20(const Edge &E) {
+  using namespace riscv;
+  assert((E.getKind() == R_RISCV_PCREL_LO12_I ||
+          E.getKind() == R_RISCV_PCREL_LO12_S) &&
+         "Can only have high relocation for R_RISCV_PCREL_LO12_I or "
+         "R_RISCV_PCREL_LO12_S");
+
+  const Symbol &Sym = E.getTarget();
+  const Block &B = Sym.getBlock();
+  JITTargetAddress Offset = Sym.getOffset();
+
+  struct Comp {
+    bool operator()(const Edge &Lhs, JITTargetAddress Offset) {
+      return Lhs.getOffset() < Offset;
+    }
+    bool operator()(JITTargetAddress Offset, const Edge &Rhs) {
+      return Offset < Rhs.getOffset();
+    }
+  };
+
+  auto Bound =
+      std::equal_range(B.edges().begin(), B.edges().end(), Offset, Comp{});
+
+  for (auto It = Bound.first; It != Bound.second; ++It) {
+    if (It->getKind() == R_RISCV_PCREL_HI20)
+      return *It;
+  }
+
+  return make_error<JITLinkError>(
+      "No HI20 PCREL relocation type be found for LO12 PCREL relocation type");
+}
+
+static uint32_t extractBits(uint64_t Num, unsigned High, unsigned Low) {
+  return (Num & ((1ULL << (High + 1)) - 1)) >> Low;
+}
+
+class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
+  friend class JITLinker<ELFJITLinker_riscv>;
+
+public:
+  ELFJITLinker_riscv(std::unique_ptr<JITLinkContext> Ctx,
+                     std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
+      : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
+
+private:
+  Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
+    using namespace riscv;
+    using namespace llvm::support;
+
+    char *BlockWorkingMem = B.getAlreadyMutableContent().data();
+    char *FixupPtr = BlockWorkingMem + E.getOffset();
+    JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
+    switch (E.getKind()) {
+    case R_RISCV_HI20: {
+      int64_t Value = E.getTarget().getAddress() + E.getAddend();
+      int32_t Hi = (Value + 0x800) & 0xFFFFF000;
+      uint32_t RawInstr = *(little32_t *)FixupPtr;
+      *(little32_t *)FixupPtr = (RawInstr & 0xFFF) | static_cast<uint32_t>(Hi);
+      break;
+    }
+    case R_RISCV_LO12_I: {
+      int64_t Value = E.getTarget().getAddress() + E.getAddend();
+      int32_t Lo = Value & 0xFFF;
+      uint32_t RawInstr = *(little32_t *)FixupPtr;
+      *(little32_t *)FixupPtr =
+          (RawInstr & 0xFFFFF) | (static_cast<uint32_t>(Lo & 0xFFF) << 20);
+      break;
+    }
+    case R_RISCV_CALL: {
+      int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+      int32_t Hi = (Value + 0x800) & 0xFFFFF000;
+      int32_t Lo = Value & 0xFFF;
+      uint32_t RawInstrAuipc = *(little32_t *)FixupPtr;
+      uint32_t RawInstrJalr = *(little32_t *)(FixupPtr + 4);
+      *(little32_t *)FixupPtr = RawInstrAuipc | static_cast<uint32_t>(Hi);
+      *(little32_t *)(FixupPtr + 4) =
+          RawInstrJalr | (static_cast<uint32_t>(Lo) << 20);
+      break;
+    }
+    case R_RISCV_PCREL_HI20: {
+      int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+      int32_t Hi = (Value + 0x800) & 0xFFFFF000;
+      uint32_t RawInstr = *(little32_t *)FixupPtr;
+      *(little32_t *)FixupPtr = (RawInstr & 0xFFF) | static_cast<uint32_t>(Hi);
+      break;
+    }
+    case R_RISCV_PCREL_LO12_I: {
+      auto RelHI20 = getRISCVPCRelHi20(E);
+      if (!RelHI20)
+        return RelHI20.takeError();
+      int64_t Value = RelHI20->getTarget().getAddress() +
+                      RelHI20->getAddend() - E.getTarget().getAddress();
+      int64_t Lo = Value & 0xFFF;
+      uint32_t RawInstr = *(little32_t *)FixupPtr;
+      *(little32_t *)FixupPtr =
+          (RawInstr & 0xFFFFF) | (static_cast<uint32_t>(Lo & 0xFFF) << 20);
+      break;
+    }
+    case R_RISCV_PCREL_LO12_S: {
+      auto RelHI20 = getRISCVPCRelHi20(E);
+      int64_t Value = RelHI20->getTarget().getAddress() +
+                      RelHI20->getAddend() - E.getTarget().getAddress();
+      int64_t Lo = Value & 0xFFF;
+      uint32_t Imm31_25 = extractBits(Lo, 11, 5) << 25;
+      uint32_t Imm11_7 = extractBits(Lo, 4, 0) << 7;
+      uint32_t RawInstr = *(little32_t *)FixupPtr;
+
+      *(little32_t *)FixupPtr = (RawInstr & 0x1FFF07F) | Imm31_25 | Imm11_7;
+      break;
+    }
+    }
+    return Error::success();
+  }
+};
+
+template <typename ELFT>
+class ELFLinkGraphBuilder_riscv : public ELFLinkGraphBuilder<ELFT> {
+private:
+  static Expected<riscv::EdgeKind_riscv>
+  getRelocationKind(const uint32_t Type) {
+    using namespace riscv;
+    switch (Type) {
+    case ELF::R_RISCV_32:
+      return EdgeKind_riscv::R_RISCV_32;
+    case ELF::R_RISCV_64:
+      return EdgeKind_riscv::R_RISCV_64;
+    case ELF::R_RISCV_HI20:
+      return EdgeKind_riscv::R_RISCV_HI20;
+    case ELF::R_RISCV_LO12_I:
+      return EdgeKind_riscv::R_RISCV_LO12_I;
+    case ELF::R_RISCV_CALL:
+      return EdgeKind_riscv::R_RISCV_CALL;
+    case ELF::R_RISCV_PCREL_HI20:
+      return EdgeKind_riscv::R_RISCV_PCREL_HI20;
+    case ELF::R_RISCV_PCREL_LO12_I:
+      return EdgeKind_riscv::R_RISCV_PCREL_LO12_I;
+    case ELF::R_RISCV_PCREL_LO12_S:
+      return EdgeKind_riscv::R_RISCV_PCREL_LO12_S;
+    }
+
+    return make_error<JITLinkError>("Unsupported riscv relocation:" +
+                                    formatv("{0:d}", Type));
+  }
+
+  Error addRelocations() override {
+    using Base = ELFLinkGraphBuilder<ELFT>;
+    LLVM_DEBUG(dbgs() << "Adding relocations\n");
+
+    // TODO a partern is forming of iterate some sections but only give me
+    // ones I am interested, I should abstract that concept some where
+    for (auto &SecRef : Base::Sections) {
+      if (SecRef.sh_type != ELF::SHT_RELA && SecRef.sh_type != ELF::SHT_REL)
+        continue;
+      auto RelSectName = Base::Obj.getSectionName(SecRef);
+      if (!RelSectName)
+        return RelSectName.takeError();
+
+      LLVM_DEBUG({
+        dbgs() << "Adding relocations from section " << *RelSectName << "\n";
+      });
+
+      auto UpdateSection = Base::Obj.getSection(SecRef.sh_info);
+      if (!UpdateSection)
+        return UpdateSection.takeError();
+
+      auto UpdateSectionName = Base::Obj.getSectionName(**UpdateSection);
+      if (!UpdateSectionName)
+        return UpdateSectionName.takeError();
+      // Don't process relocations for debug sections.
+      if (Base::isDwarfSection(*UpdateSectionName)) {
+        LLVM_DEBUG({
+          dbgs() << "  Target is dwarf section " << *UpdateSectionName
+                 << ". Skipping.\n";
+        });
+        continue;
+      } else
+        LLVM_DEBUG({
+          dbgs() << "  For target section " << *UpdateSectionName << "\n";
+        });
+
+      auto *JITSection = Base::G->findSectionByName(*UpdateSectionName);
+      if (!JITSection)
+        return make_error<llvm::StringError>(
+            "Refencing a section that wasn't added to graph" +
+                *UpdateSectionName,
+            llvm::inconvertibleErrorCode());
+
+      auto Relocations = Base::Obj.relas(SecRef);
+      if (!Relocations)
+        return Relocations.takeError();
+
+      for (const auto &Rela : *Relocations) {
+        auto Type = Rela.getType(false);
+
+        LLVM_DEBUG({
+          dbgs() << "Relocation Type: " << Type << "\n"
+                 << "Name: " << Base::Obj.getRelocationTypeName(Type) << "\n";
+        });
+
+        auto SymbolIndex = Rela.getSymbol(false);
+        auto Symbol = Base::Obj.getRelocationSymbol(Rela, Base::SymTabSec);
+        if (!Symbol)
+          return Symbol.takeError();
+
+        auto BlockToFix = *(JITSection->blocks().begin());
+        auto *TargetSymbol = Base::getGraphSymbol(SymbolIndex);
+
+        if (!TargetSymbol) {
+          return make_error<llvm::StringError>(
+              "Could not find symbol at given index, did you add it to "
+              "JITSymbolTable? index: " +
+                  std::to_string(SymbolIndex) + ", shndx: " +
+                  std::to_string((*Symbol)->st_shndx) + " Size of table: " +
+                  std::to_string(Base::GraphSymbols.size()),
+              llvm::inconvertibleErrorCode());
+        }
+        int64_t Addend = Rela.r_addend;
+        JITTargetAddress FixupAddress =
+            (*UpdateSection)->sh_addr + Rela.r_offset;
+
+        LLVM_DEBUG({
+          dbgs() << "Processing relocation at "
+                 << format("0x%016" PRIx64, FixupAddress) << "\n";
+        });
+        auto Kind = getRelocationKind(Type);
+        if (!Kind)
+          return Kind.takeError();
+
+        BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(),
+                            *TargetSymbol, Addend);
+      }
+    }
+    return Error::success();
+  }
+
+public:
+  ELFLinkGraphBuilder_riscv(StringRef FileName,
+                            const object::ELFFile<ELFT> &Obj, const Triple T)
+      : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
+                                  riscv::getEdgeKindName) {}
+};
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_riscv(MemoryBufferRef ObjectBuffer) {
+  LLVM_DEBUG({
+    dbgs() << "Building jitlink graph for new input "
+           << ObjectBuffer.getBufferIdentifier() << "...\n";
+  });
+
+  auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
+  if (!ELFObj)
+    return ELFObj.takeError();
+
+  if ((*ELFObj)->getArch() == Triple::riscv64) {
+    auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
+    return ELFLinkGraphBuilder_riscv<object::ELF64LE>(
+               (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
+               (*ELFObj)->makeTriple())
+        .buildGraph();
+  } else {
+    assert((*ELFObj)->getArch() == Triple::riscv32 &&
+           "Invalid triple for RISCV ELF object file");
+    auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
+    return ELFLinkGraphBuilder_riscv<object::ELF32LE>(
+               (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
+               (*ELFObj)->makeTriple())
+        .buildGraph();
+  }
+}
+
+void link_ELF_riscv(std::unique_ptr<LinkGraph> G,
+                    std::unique_ptr<JITLinkContext> Ctx) {
+  PassConfiguration Config;
+  const Triple &TT = G->getTargetTriple();
+  if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+    if (auto MarkLive = Ctx->getMarkLivePass(TT))
+      Config.PrePrunePasses.push_back(std::move(MarkLive));
+    else
+      Config.PrePrunePasses.push_back(markAllSymbolsLive);
+  }
+  if (auto Err = Ctx->modifyPassConfig(*G, Config))
+    return Ctx->notifyFailed(std::move(Err));
+
+  ELFJITLinker_riscv::link(std::move(Ctx), std::move(G), std::move(Config));
+}
+
+} // namespace jitlink
+} // namespace llvm

diff  --git a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s
new file mode 100644
index 0000000000000..875c8c87613a4
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s
@@ -0,0 +1,39 @@
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=riscv64 -position-independent -filetype=obj -o %t/elf_riscv64_sm_pic_reloc.o %s
+# RUN: llvm-mc -triple=riscv32 -position-independent -filetype=obj -o %t/elf_riscv32_sm_pic_reloc.o %s
+# RUN: llvm-jitlink -noexec -slab-allocate 100Kb -slab-address 0xfff00000 \
+# RUN:              -check %s %t/elf_riscv64_sm_pic_reloc.o
+# RUN: llvm-jitlink -noexec -slab-allocate 100Kb -slab-address 0xfff00000 \
+# RUN:              -check %s %t/elf_riscv32_sm_pic_reloc.o
+#
+# Test ELF small/PIC relocations
+
+        .text
+        .file   "testcase.c"
+
+# Empty main entry point.
+        .globl  main
+        .p2align  1
+        .type   main, at function
+main:
+        ret
+
+        .size   main, .-main
+
+# Test R_RISCV_PCREL_HI20 and R_RISCV_PCREL_LO
+# jitlink-check: decode_operand(test_pcrel32, 1) = ((named_data - test_pcrel32) + 0x800)[31:12] 
+        .globl  test_pcrel32
+        .p2align  1
+        .type   test_pcrel32, at function
+test_pcrel32:
+        auipc a0, %pcrel_hi(named_data)
+        lw  a0, %pcrel_lo(test_pcrel32)(a0)
+
+        .size   test_pcrel32, .-test_pcrel32
+
+        .data
+        .type   named_data, at object
+        .p2align  1
+named_data:
+        .quad   42
+        .size   named_data, 4


        


More information about the llvm-commits mailing list