diff options
Diffstat (limited to 'lld/ELF/Arch/RISCV.cpp')
-rw-r--r-- | lld/ELF/Arch/RISCV.cpp | 54 |
1 files changed, 28 insertions, 26 deletions
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 42db8e08162d..b340fd00deee 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -15,9 +15,8 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::support::endian; using namespace llvm::ELF; - -namespace lld { -namespace elf { +using namespace lld; +using namespace lld::elf; namespace { @@ -33,7 +32,8 @@ public: RelType getDynRel(RelType type) const override; RelExpr getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const override; - void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + void relocate(uint8_t *loc, const Relocation &rel, + uint64_t val) const override; }; } // end anonymous namespace @@ -76,6 +76,7 @@ RISCV::RISCV() { noneRel = R_RISCV_NONE; pltRel = R_RISCV_JUMP_SLOT; relativeRel = R_RISCV_RELATIVE; + iRelativeRel = R_RISCV_IRELATIVE; if (config->is64) { symbolicRel = R_RISCV_64; tlsModuleIndexRel = R_RISCV_TLS_DTPMOD64; @@ -236,9 +237,15 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s, case R_RISCV_TPREL_LO12_S: return R_TLS; case R_RISCV_RELAX: - case R_RISCV_ALIGN: case R_RISCV_TPREL_ADD: return R_NONE; + case R_RISCV_ALIGN: + // Not just a hint; always padded to the worst-case number of NOPs, so may + // not currently be aligned, and without linker relaxation support we can't + // delete NOPs to realign. + errorOrWarn(getErrorLocation(loc) + "relocation R_RISCV_ALIGN requires " + "unimplemented linker relaxation; recompile with -mno-relax"); + return R_NONE; default: error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + ") against symbol " + toString(s)); @@ -251,11 +258,10 @@ static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) { return (v & ((1ULL << (begin + 1)) - 1)) >> end; } -void RISCV::relocateOne(uint8_t *loc, const RelType type, - const uint64_t val) const { +void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { const unsigned bits = config->wordsize * 8; - switch (type) { + switch (rel.type) { case R_RISCV_32: write32le(loc, val); return; @@ -264,8 +270,8 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, return; case R_RISCV_RVC_BRANCH: { - checkInt(loc, static_cast<int64_t>(val) >> 1, 8, type); - checkAlignment(loc, val, 2, type); + checkInt(loc, static_cast<int64_t>(val) >> 1, 8, rel); + checkAlignment(loc, val, 2, rel); uint16_t insn = read16le(loc) & 0xE383; uint16_t imm8 = extractBits(val, 8, 8) << 12; uint16_t imm4_3 = extractBits(val, 4, 3) << 10; @@ -279,8 +285,8 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, } case R_RISCV_RVC_JUMP: { - checkInt(loc, static_cast<int64_t>(val) >> 1, 11, type); - checkAlignment(loc, val, 2, type); + checkInt(loc, static_cast<int64_t>(val) >> 1, 11, rel); + checkAlignment(loc, val, 2, rel); uint16_t insn = read16le(loc) & 0xE003; uint16_t imm11 = extractBits(val, 11, 11) << 12; uint16_t imm4 = extractBits(val, 4, 4) << 11; @@ -298,7 +304,7 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, case R_RISCV_RVC_LUI: { int64_t imm = SignExtend64(val + 0x800, bits) >> 12; - checkInt(loc, imm, 6, type); + checkInt(loc, imm, 6, rel); if (imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0` write16le(loc, (read16le(loc) & 0x0F83) | 0x4000); } else { @@ -310,8 +316,8 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, } case R_RISCV_JAL: { - checkInt(loc, static_cast<int64_t>(val) >> 1, 20, type); - checkAlignment(loc, val, 2, type); + checkInt(loc, static_cast<int64_t>(val) >> 1, 20, rel); + checkAlignment(loc, val, 2, rel); uint32_t insn = read32le(loc) & 0xFFF; uint32_t imm20 = extractBits(val, 20, 20) << 31; @@ -325,8 +331,8 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, } case R_RISCV_BRANCH: { - checkInt(loc, static_cast<int64_t>(val) >> 1, 12, type); - checkAlignment(loc, val, 2, type); + checkInt(loc, static_cast<int64_t>(val) >> 1, 12, rel); + checkAlignment(loc, val, 2, rel); uint32_t insn = read32le(loc) & 0x1FFF07F; uint32_t imm12 = extractBits(val, 12, 12) << 31; @@ -343,10 +349,10 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, case R_RISCV_CALL: case R_RISCV_CALL_PLT: { int64_t hi = SignExtend64(val + 0x800, bits) >> 12; - checkInt(loc, hi, 20, type); + checkInt(loc, hi, 20, rel); if (isInt<20>(hi)) { - relocateOne(loc, R_RISCV_PCREL_HI20, val); - relocateOne(loc + 4, R_RISCV_PCREL_LO12_I, val); + relocateNoSym(loc, R_RISCV_PCREL_HI20, val); + relocateNoSym(loc + 4, R_RISCV_PCREL_LO12_I, val); } return; } @@ -358,7 +364,7 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, case R_RISCV_TPREL_HI20: case R_RISCV_HI20: { uint64_t hi = val + 0x800; - checkInt(loc, SignExtend64(hi, bits) >> 12, 20, type); + checkInt(loc, SignExtend64(hi, bits) >> 12, 20, rel); write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000)); return; } @@ -431,7 +437,6 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, write64le(loc, val - dtpOffset); break; - case R_RISCV_ALIGN: case R_RISCV_RELAX: return; // Ignored (for now) @@ -440,10 +445,7 @@ void RISCV::relocateOne(uint8_t *loc, const RelType type, } } -TargetInfo *getRISCVTargetInfo() { +TargetInfo *elf::getRISCVTargetInfo() { static RISCV target; return ⌖ } - -} // namespace elf -} // namespace lld |