114 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLD_ELF_ARCH_RISCVINTERNALRELOCATIONS_H10#define LLD_ELF_ARCH_RISCVINTERNALRELOCATIONS_H11 12#include "Relocations.h"13#include "Symbols.h"14 15namespace lld::elf {16 17// Bit 8 of RelType is used to indicate linker-internal relocations that are18// not vendor-specific.19// These are internal relocation numbers for GP/X0 relaxation. They aren't part20// of the psABI spec.21constexpr uint32_t INTERNAL_R_RISCV_GPREL_I = 256;22constexpr uint32_t INTERNAL_R_RISCV_GPREL_S = 257;23constexpr uint32_t INTERNAL_R_RISCV_X0REL_I = 258;24constexpr uint32_t INTERNAL_R_RISCV_X0REL_S = 259;25 26// Bits 9 -> 31 of RelType are used to indicate vendor-specific relocations.27constexpr uint32_t INTERNAL_RISCV_VENDOR_MASK = 0xFFFFFFFF << 9;28constexpr uint32_t INTERNAL_RISCV_VENDOR_QUALCOMM = 1 << 9;29constexpr uint32_t INTERNAL_RISCV_VENDOR_ANDES = 2 << 9;30 31constexpr uint32_t INTERNAL_RISCV_QC_ABS20_U =32 INTERNAL_RISCV_VENDOR_QUALCOMM | llvm::ELF::R_RISCV_QC_ABS20_U;33constexpr uint32_t INTERNAL_RISCV_QC_E_BRANCH =34 INTERNAL_RISCV_VENDOR_QUALCOMM | llvm::ELF::R_RISCV_QC_E_BRANCH;35constexpr uint32_t INTERNAL_RISCV_QC_E_32 =36 INTERNAL_RISCV_VENDOR_QUALCOMM | llvm::ELF::R_RISCV_QC_E_32;37constexpr uint32_t INTERNAL_RISCV_QC_E_CALL_PLT =38 INTERNAL_RISCV_VENDOR_QUALCOMM | llvm::ELF::R_RISCV_QC_E_CALL_PLT;39 40constexpr uint32_t INTERNAL_RISCV_NDS_BRANCH_10 =41 INTERNAL_RISCV_VENDOR_ANDES | llvm::ELF::R_RISCV_NDS_BRANCH_10;42 43uint32_t getRISCVVendorRelMarker(llvm::StringRef rvVendor);44std::optional<llvm::StringRef> getRISCVVendorString(RelType ty);45 46class vendor_reloc_iterator {47public:48 using iterator_category = std::forward_iterator_tag;49 using value_type = Relocation;50 using difference_type = std::ptrdiff_t;51 using pointer = Relocation *;52 using reference = Relocation; // returned by value53 54 vendor_reloc_iterator(MutableArrayRef<Relocation>::iterator i,55 MutableArrayRef<Relocation>::iterator e)56 : it(i), end(e) {}57 58 // Dereference59 Relocation operator*() const {60 Relocation r = *it;61 r.type.v |= rvVendorFlag;62 return r;63 }64 65 struct vendor_reloc_proxy {66 Relocation r;67 const Relocation *operator->() const { return &r; }68 };69 70 vendor_reloc_proxy operator->() const {71 return vendor_reloc_proxy{this->operator*()};72 }73 74 vendor_reloc_iterator &operator++() {75 ++it;76 if (it != end && it->type == llvm::ELF::R_RISCV_VENDOR) {77 rvVendorFlag = getRISCVVendorRelMarker(it->sym->getName());78 ++it;79 } else {80 rvVendorFlag = 0;81 }82 return *this;83 }84 85 vendor_reloc_iterator operator++(int) {86 vendor_reloc_iterator tmp(*this);87 ++(*this);88 return tmp;89 }90 91 bool operator==(const vendor_reloc_iterator &other) const {92 return it == other.it;93 }94 bool operator!=(const vendor_reloc_iterator &other) const {95 return it != other.it;96 }97 98 Relocation *getUnderlyingRelocation() const { return &*it; }99 100private:101 MutableArrayRef<Relocation>::iterator it;102 MutableArrayRef<Relocation>::iterator end;103 uint32_t rvVendorFlag = 0;104};105 106inline auto riscv_vendor_relocs(MutableArrayRef<Relocation> arr) {107 return llvm::make_range(vendor_reloc_iterator(arr.begin(), arr.end()),108 vendor_reloc_iterator(arr.end(), arr.end()));109}110 111} // namespace lld::elf112 113#endif114