Index: lld/trunk/ELF/Arch/RISCV.cpp =================================================================== --- lld/trunk/ELF/Arch/RISCV.cpp +++ lld/trunk/ELF/Arch/RISCV.cpp @@ -0,0 +1,277 @@ +//===- RISCV.cpp ----------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "InputFiles.h" +#include "Target.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { + +class RISCV final : public TargetInfo { +public: + virtual uint32_t calcEFlags() 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; +}; + +} // end anonymous namespace + +static uint32_t getEFlags(InputFile *F) { + if (Config->Is64) + return cast>(F)->getObj().getHeader()->e_flags; + else + return cast>(F)->getObj().getHeader()->e_flags; +} + +uint32_t RISCV::calcEFlags() const { + assert(!ObjectFiles.empty()); + + uint32_t Target = getEFlags(ObjectFiles.front()); + + for (InputFile *F : ObjectFiles) { + uint32_t EFlags = getEFlags(F); + if (EFlags & EF_RISCV_RVC) + Target |= EF_RISCV_RVC; + + if ((EFlags & EF_RISCV_FLOAT_ABI) != (Target & EF_RISCV_FLOAT_ABI)) + error(toString(F) + + ": cannot link object files with different floating-point ABI"); + + if ((EFlags & EF_RISCV_RVE) != (Target & EF_RISCV_RVE)) + error(toString(F) + + ": cannot link object files with different EF_RISCV_RVE"); + } + + return Target; +} + +RelExpr RISCV::getRelExpr(const RelType Type, const Symbol &S, + const uint8_t *Loc) const { + switch (Type) { + case R_RISCV_JAL: + case R_RISCV_BRANCH: + case R_RISCV_CALL: + case R_RISCV_PCREL_HI20: + case R_RISCV_RVC_BRANCH: + case R_RISCV_RVC_JUMP: + case R_RISCV_32_PCREL: + return R_PC; + case R_RISCV_PCREL_LO12_I: + case R_RISCV_PCREL_LO12_S: + return R_RISCV_PC_INDIRECT; + case R_RISCV_RELAX: + case R_RISCV_ALIGN: + return R_HINT; + default: + return R_ABS; + } +} + +// Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63. +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 { + switch (Type) { + case R_RISCV_32: + write32le(Loc, Val); + return; + case R_RISCV_64: + write64le(Loc, Val); + return; + + case R_RISCV_RVC_BRANCH: { + checkInt(Loc, static_cast(Val) >> 1, 8, Type); + checkAlignment(Loc, Val, 2, Type); + uint16_t Insn = read16le(Loc) & 0xE383; + uint16_t Imm8 = extractBits(Val, 8, 8) << 12; + uint16_t Imm4_3 = extractBits(Val, 4, 3) << 10; + uint16_t Imm7_6 = extractBits(Val, 7, 6) << 5; + uint16_t Imm2_1 = extractBits(Val, 2, 1) << 3; + uint16_t Imm5 = extractBits(Val, 5, 5) << 2; + Insn |= Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5; + + write16le(Loc, Insn); + return; + } + + case R_RISCV_RVC_JUMP: { + checkInt(Loc, static_cast(Val) >> 1, 11, Type); + checkAlignment(Loc, Val, 2, Type); + uint16_t Insn = read16le(Loc) & 0xE003; + uint16_t Imm11 = extractBits(Val, 11, 11) << 12; + uint16_t Imm4 = extractBits(Val, 4, 4) << 11; + uint16_t Imm9_8 = extractBits(Val, 9, 8) << 9; + uint16_t Imm10 = extractBits(Val, 10, 10) << 8; + uint16_t Imm6 = extractBits(Val, 6, 6) << 7; + uint16_t Imm7 = extractBits(Val, 7, 7) << 6; + uint16_t Imm3_1 = extractBits(Val, 3, 1) << 3; + uint16_t Imm5 = extractBits(Val, 5, 5) << 2; + Insn |= Imm11 | Imm4 | Imm9_8 | Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5; + + write16le(Loc, Insn); + return; + } + + case R_RISCV_RVC_LUI: { + int32_t Imm = ((Val + 0x800) >> 12); + checkUInt(Loc, Imm, 6, Type); + if (Imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0` + write16le(Loc, (read16le(Loc) & 0x0F83) | 0x4000); + } else { + uint16_t Imm17 = extractBits(Val + 0x800, 17, 17) << 12; + uint16_t Imm16_12 = extractBits(Val + 0x800, 16, 12) << 2; + write16le(Loc, (read16le(Loc) & 0xEF83) | Imm17 | Imm16_12); + } + return; + } + + case R_RISCV_JAL: { + checkInt(Loc, static_cast(Val) >> 1, 20, Type); + checkAlignment(Loc, Val, 2, Type); + + uint32_t Insn = read32le(Loc) & 0xFFF; + uint32_t Imm20 = extractBits(Val, 20, 20) << 31; + uint32_t Imm10_1 = extractBits(Val, 10, 1) << 21; + uint32_t Imm11 = extractBits(Val, 11, 11) << 20; + uint32_t Imm19_12 = extractBits(Val, 19, 12) << 12; + Insn |= Imm20 | Imm10_1 | Imm11 | Imm19_12; + + write32le(Loc, Insn); + return; + } + + case R_RISCV_BRANCH: { + checkInt(Loc, static_cast(Val) >> 1, 12, Type); + checkAlignment(Loc, Val, 2, Type); + + uint32_t Insn = read32le(Loc) & 0x1FFF07F; + uint32_t Imm12 = extractBits(Val, 12, 12) << 31; + uint32_t Imm10_5 = extractBits(Val, 10, 5) << 25; + uint32_t Imm4_1 = extractBits(Val, 4, 1) << 8; + uint32_t Imm11 = extractBits(Val, 11, 11) << 7; + Insn |= Imm12 | Imm10_5 | Imm4_1 | Imm11; + + write32le(Loc, Insn); + return; + } + + // auipc + jalr pair + case R_RISCV_CALL: { + checkInt(Loc, Val, 32, Type); + if (isInt<32>(Val)) { + relocateOne(Loc, R_RISCV_PCREL_HI20, Val); + relocateOne(Loc + 4, R_RISCV_PCREL_LO12_I, Val); + } + return; + } + + case R_RISCV_PCREL_HI20: + case R_RISCV_HI20: { + checkInt(Loc, Val, 32, Type); + uint32_t Hi = Val + 0x800; + write32le(Loc, (read32le(Loc) & 0xFFF) | (Hi & 0xFFFFF000)); + return; + } + + case R_RISCV_PCREL_LO12_I: + case R_RISCV_LO12_I: { + checkInt(Loc, Val, 32, Type); + uint32_t Hi = Val + 0x800; + uint32_t Lo = Val - (Hi & 0xFFFFF000); + write32le(Loc, (read32le(Loc) & 0xFFFFF) | ((Lo & 0xFFF) << 20)); + return; + } + + case R_RISCV_PCREL_LO12_S: + case R_RISCV_LO12_S: { + checkInt(Loc, Val, 32, Type); + uint32_t Hi = Val + 0x800; + uint32_t Lo = Val - (Hi & 0xFFFFF000); + uint32_t Imm11_5 = extractBits(Lo, 11, 5) << 25; + uint32_t Imm4_0 = extractBits(Lo, 4, 0) << 7; + write32le(Loc, (read32le(Loc) & 0x1FFF07F) | Imm11_5 | Imm4_0); + return; + } + + case R_RISCV_ADD8: + *Loc += Val; + return; + case R_RISCV_ADD16: + write16le(Loc, read16le(Loc) + Val); + return; + case R_RISCV_ADD32: + write32le(Loc, read32le(Loc) + Val); + return; + case R_RISCV_ADD64: + write64le(Loc, read64le(Loc) + Val); + return; + case R_RISCV_SUB6: + *Loc = (*Loc & 0xc0) | (((*Loc & 0x3f) - Val) & 0x3f); + return; + case R_RISCV_SUB8: + *Loc -= Val; + return; + case R_RISCV_SUB16: + write16le(Loc, read16le(Loc) - Val); + return; + case R_RISCV_SUB32: + write32le(Loc, read32le(Loc) - Val); + return; + case R_RISCV_SUB64: + write64le(Loc, read64le(Loc) - Val); + return; + case R_RISCV_SET6: + *Loc = (*Loc & 0xc0) | (Val & 0x3f); + return; + case R_RISCV_SET8: + *Loc = Val; + return; + case R_RISCV_SET16: + write16le(Loc, Val); + return; + case R_RISCV_SET32: + case R_RISCV_32_PCREL: + write32le(Loc, Val); + return; + + case R_RISCV_ALIGN: + case R_RISCV_RELAX: + return; // Ignored (for now) + case R_RISCV_NONE: + return; // Do nothing + + // These are handled by the dynamic linker + case R_RISCV_RELATIVE: + case R_RISCV_COPY: + case R_RISCV_JUMP_SLOT: + // GP-relative relocations are only produced after relaxation, which + // we don't support for now + case R_RISCV_GPREL_I: + case R_RISCV_GPREL_S: + default: + error(getErrorLocation(Loc) + + "unimplemented relocation: " + toString(Type)); + return; + } +} + +TargetInfo *elf::getRISCVTargetInfo() { + static RISCV Target; + return &Target; +} Index: lld/trunk/ELF/CMakeLists.txt =================================================================== --- lld/trunk/ELF/CMakeLists.txt +++ lld/trunk/ELF/CMakeLists.txt @@ -17,6 +17,7 @@ Arch/MipsArchTree.cpp Arch/PPC.cpp Arch/PPC64.cpp + Arch/RISCV.cpp Arch/SPARCV9.cpp Arch/X86.cpp Arch/X86_64.cpp Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -125,9 +125,11 @@ .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) + .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) .Case("elf32ppc", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) + .Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) .Case("elf64ppc", {ELF64BEKind, EM_PPC64}) .Case("elf64lppc", {ELF64LEKind, EM_PPC64}) .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64}) @@ -986,7 +988,8 @@ // ABI defines which one you need to use. The following expression expresses // that. Config->IsRela = - (Config->Is64 || IsX32 || Machine == EM_PPC) && Machine != EM_MIPS; + (Config->Is64 || IsX32 || Machine == EM_PPC || Machine == EM_RISCV) && + Machine != EM_MIPS; // If the output uses REL relocations we must store the dynamic relocation // addends to the output sections. We also store addends for RELA relocations Index: lld/trunk/ELF/InputSection.h =================================================================== --- lld/trunk/ELF/InputSection.h +++ lld/trunk/ELF/InputSection.h @@ -353,6 +353,8 @@ // The list of all input sections. extern std::vector InputSections; + +Relocation *getRISCVPCRelHi20(const Symbol *Sym, const uint64_t Addend); } // namespace elf std::string toString(const elf::InputSectionBase *); Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -481,6 +481,33 @@ return OS->PtLoad->FirstSec->Addr; } +// For R_RISCV_PC_INDIRECT (R_RISCV_PCREL_LO12_{I,S}), the symbol actually +// points the corresponding R_RISCV_PCREL_HI20 relocation, and the target VA +// is calculated using PCREL_HI20's symbol. +// +// This function returns the R_RISCV_PCREL_HI20 relocation from +// R_RISCV_PCREL_LO12's symbol and addend. +Relocation *lld::elf::getRISCVPCRelHi20(const Symbol *Sym, uint64_t Addend) { + const Defined *D = cast(Sym); + InputSection *IS = cast(D->Section); + + if (Addend != 0) + warn("Non-zero addend in R_RISCV_PCREL_LO12 relocation to " + + IS->getObjMsg(D->Value) + " is ignored"); + + // Relocations are sorted by offset, so we can use std::equal_range to do + // binary search. + auto Range = std::equal_range(IS->Relocations.begin(), IS->Relocations.end(), + D->Value, RelocationOffsetComparator{}); + for (auto It = std::get<0>(Range); It != std::get<1>(Range); ++It) + if (isRelExprOneOf(It->Expr)) + return &*It; + + error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) + + " without an associated R_RISCV_PCREL_HI20 relocation"); + return nullptr; +} + static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, uint64_t P, const Symbol &Sym, RelExpr Expr) { switch (Expr) { @@ -567,6 +594,13 @@ Dest = getAArch64Page(Sym.getVA(A)); return Dest - getAArch64Page(P); } + case R_RISCV_PC_INDIRECT: { + const Relocation *HiRel = getRISCVPCRelHi20(&Sym, A); + if (!HiRel) + return 0; + return getRelocTargetVA(File, HiRel->Type, HiRel->Addend, Sym.getVA(), + *HiRel->Sym, HiRel->Expr); + } case R_PC: { uint64_t Dest; if (Sym.isUndefWeak()) { Index: lld/trunk/ELF/Relocations.h =================================================================== --- lld/trunk/ELF/Relocations.h +++ lld/trunk/ELF/Relocations.h @@ -74,6 +74,7 @@ R_RELAX_TLS_IE_TO_LE, R_RELAX_TLS_LD_TO_LE, R_RELAX_TLS_LD_TO_LE_ABS, + R_RISCV_PC_INDIRECT, R_SIZE, R_TLS, R_TLSDESC, @@ -128,6 +129,21 @@ Symbol *Sym; }; +struct RelocationOffsetComparator { + bool operator()(const Relocation &Lhs, const Relocation &Rhs) { + return Lhs.Offset < Rhs.Offset; + } + + // For std::lower_bound, std::upper_bound, std::equal_range. + bool operator()(const Relocation &Rel, uint64_t Val) { + return Rel.Offset < Val; + } + + bool operator()(uint64_t Val, const Relocation &Rel) { + return Val < Rel.Offset; + } +}; + template void scanRelocations(InputSectionBase &); class ThunkSection; Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -1047,6 +1047,11 @@ for (auto I = Rels.begin(), End = Rels.end(); I != End;) scanReloc(Sec, GetOffset, I, End); + + // Sort relocations by offset to binary search for R_RISCV_PCREL_HI20 + if (Config->EMachine == EM_RISCV) + std::stable_sort(Sec.Relocations.begin(), Sec.Relocations.end(), + RelocationOffsetComparator{}); } template void elf::scanRelocations(InputSectionBase &S) { Index: lld/trunk/ELF/Symbols.h =================================================================== --- lld/trunk/ELF/Symbols.h +++ lld/trunk/ELF/Symbols.h @@ -333,6 +333,9 @@ // __rela_iplt_end or __rel_iplt_end static Defined *RelaIpltEnd; + + // __global_pointer$ in RISC-V. + static Defined *RISCVGlobalPointer; }; // A buffer class that is large enough to hold any Symbol-derived Index: lld/trunk/ELF/Symbols.cpp =================================================================== --- lld/trunk/ELF/Symbols.cpp +++ lld/trunk/ELF/Symbols.cpp @@ -39,6 +39,7 @@ Defined *ElfSym::MipsGpDisp; Defined *ElfSym::MipsLocalGp; Defined *ElfSym::RelaIpltEnd; +Defined *ElfSym::RISCVGlobalPointer; static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) { switch (Sym.kind()) { Index: lld/trunk/ELF/Target.h =================================================================== --- lld/trunk/ELF/Target.h +++ lld/trunk/ELF/Target.h @@ -151,6 +151,7 @@ TargetInfo *getHexagonTargetInfo(); TargetInfo *getPPC64TargetInfo(); TargetInfo *getPPCTargetInfo(); +TargetInfo *getRISCVTargetInfo(); TargetInfo *getSPARCV9TargetInfo(); TargetInfo *getX32TargetInfo(); TargetInfo *getX86TargetInfo(); Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -79,6 +79,8 @@ return getPPCTargetInfo(); case EM_PPC64: return getPPC64TargetInfo(); + case EM_RISCV: + return getRISCVTargetInfo(); case EM_SPARCV9: return getSPARCV9TargetInfo(); case EM_X86_64: Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -1555,6 +1555,15 @@ // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); + // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800 if not defined. + if (Config->EMachine == EM_RISCV) { + ElfSym::RISCVGlobalPointer = + dyn_cast_or_null(Symtab->find("__global_pointer$")); + if (!ElfSym::RISCVGlobalPointer) + ElfSym::RISCVGlobalPointer = + addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800); + } + // This responsible for splitting up .eh_frame section into // pieces. The relocation scan uses those pieces, so this has to be // earlier. Index: lld/trunk/test/ELF/riscv-branch.test =================================================================== --- lld/trunk/test/ELF/riscv-branch.test +++ lld/trunk/test/ELF/riscv-branch.test @@ -0,0 +1,119 @@ +# .option norelax +# .global _start +# _start: +# beq x0, x0, _start +# +# .section .reloc_max, "ax", @progbits +# L1: +# beq x0, x0, L1 + 0xffe +# +# .section .reloc_min, "ax", @progbits +# L2: +# beq x0, x0, L2 - 0x1000 +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .text +# CHECK: Content: '63000000' +# 11000: 00000063 beqz zero,11000 <_start> +# +# CHECK: - Name: .reloc_max +# CHECK: Content: E30F007E +# 11004: 7e000fe3 beqz zero,12002 +# +# CHECK: - Name: .reloc_min +# CHECK: Content: '63000080' +# 11008: 80000063 beqz zero,10008 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '63000000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: _start + Type: R_RISCV_BRANCH + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_max + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: E30F007E + - Name: .rela.reloc_max + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_max + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_BRANCH + Addend: 4094 + - Name: .reloc_min + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: '63000080' + - Name: .rela.reloc_min + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_min + Relocations: + - Offset: 0x0000000000000000 + Symbol: L2 + Type: R_RISCV_BRANCH + Addend: -4096 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_max + Type: STT_SECTION + Section: .reloc_max + - Name: L1 + Section: .reloc_max + - Name: .reloc_min + Type: STT_SECTION + Section: .reloc_min + - Name: L2 + Section: .reloc_min + Global: + - Name: _start + Section: .text +... Index: lld/trunk/test/ELF/riscv-call.test =================================================================== --- lld/trunk/test/ELF/riscv-call.test +++ lld/trunk/test/ELF/riscv-call.test @@ -0,0 +1,95 @@ +# .option norelax +# .global _start +# _start: +# call _start + 4 +# +# .section .reloc_neg, "ax", @progbits +# L1: +# call L1 - 4 +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .text +# CHECK: Content: '97000000E7804000' +# +# 11000: 00000097 auipc ra,0x0 +# 11004: 004080e7 jalr 4(ra) +# +# CHECK: - Name: .reloc_neg +# CHECK: Content: 97000000E780C0FF +# +# 11008: 00000097 auipc ra,0x0 +# 1100c: ffc080e7 jalr -4(ra) + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '97000000E7800000' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: _start + Type: R_RISCV_CALL + Addend: 4 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_neg + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: '97000000E7800000' + - Name: .rela.reloc_neg + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_neg + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_CALL + Addend: -4 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_neg + Type: STT_SECTION + Section: .reloc_neg + - Name: L1 + Section: .reloc_neg + Global: + - Name: _start + Section: .text +... Index: lld/trunk/test/ELF/riscv-hi20-lo12.test =================================================================== --- lld/trunk/test/ELF/riscv-hi20-lo12.test +++ lld/trunk/test/ELF/riscv-hi20-lo12.test @@ -0,0 +1,86 @@ +# .option norelax +# .global _start +# +# .section .reloc_12345678, "ax", @progbits +# _start: +# foo = 0x12345678 +# lui a0, %hi(foo) +# addi a0, a0, %lo(foo) +# lw a0, %lo(foo)(a0) +# +# .section .reloc_fedcba98, "ax", @progbits +# foo = 0xfedcba98 +# lui a0, %hi(foo) +# addi a0, a0, %lo(foo) +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .reloc_12345678 +# CHECK: Content: '375534121305856703258567' +# 11000: 12345537 lui a0,0x12345 +# 11004: 67850513 addi a0,a0,1656 # 12345678 <__global_pointer$+0x12332e78> +# 11008: 67852503 lw a0,1656(a0) +# +# CHECK: - Name: .reloc_fedcba98 +# CHECK: Content: 37C5DCFE130585A9 +# 1100c: fedcc537 lui a0,0xfedcc +# 11010: a9850513 addi a0,a0,-1384 # fedcba98 <__global_pointer$+0xfedb9298> + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_12345678 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: '375534121305856703258567' + - Name: .reloc_fedcba98 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: 37C5DCFE130585A9 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_12345678 + Type: STT_SECTION + Section: .reloc_12345678 + - Name: foo + Value: 0x00000000FEDCBA98 + - Name: .reloc_fedcba98 + Type: STT_SECTION + Section: .reloc_fedcba98 + Global: + - Name: _start + Section: .reloc_12345678 +... Index: lld/trunk/test/ELF/riscv-jal-error.test =================================================================== --- lld/trunk/test/ELF/riscv-jal-error.test +++ lld/trunk/test/ELF/riscv-jal-error.test @@ -0,0 +1,93 @@ +# .option norelax +# .global _start +# +# _start: +# L1: +# jal x0, L1 + 0x100000 +# L2: +# jal x0, L2 - 0x100002 +# L3: +# jal x0, L3 + 1 +# L4: +# c.jal L4 + 1 +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s +# +# CHECK: {{.*}}(.text+0x0): relocation R_RISCV_JAL out of range +# CHECK: {{.*}}(.text+0x4): relocation R_RISCV_JAL out of range +# CHECK: {{.*}}(.text+0x8): improper alignment for relocation R_RISCV_JAL +# CHECK: {{.*}}(.text+0xC): improper alignment for relocation R_RISCV_RVC_JUMP + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: 6F0000806FF0FF7F6F0000000120 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_JAL + Addend: 1048576 + - Offset: 0x0000000000000004 + Symbol: L2 + Type: R_RISCV_JAL + Addend: -1048578 + - Offset: 0x0000000000000008 + Symbol: L3 + Type: R_RISCV_JAL + Addend: 1 + - Offset: 0x000000000000000C + Symbol: L4 + Type: R_RISCV_RVC_JUMP + Addend: 1 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: L1 + Section: .text + - Name: L2 + Section: .text + Value: 0x0000000000000004 + - Name: L3 + Section: .text + Value: 0x0000000000000008 + - Name: L4 + Section: .text + Value: 0x000000000000000C + Global: + - Name: _start + Section: .text +... Index: lld/trunk/test/ELF/riscv-jal.test =================================================================== --- lld/trunk/test/ELF/riscv-jal.test +++ lld/trunk/test/ELF/riscv-jal.test @@ -0,0 +1,161 @@ +# .option norelax +# .global _start +# +# .section .reloc_zero, "ax", @progbits +# _start: +# L1: +# jal x0, L1 +# L2: +# c.jal L2 +# +# .section .reloc_max, "ax", @progbits +# L3: +# jal x0, L3 + 0xffffe +# L4: +# c.jal L4 + 0x7fe +# +# .section .reloc_min, "ax", @progbits +# L5: +# jal x0, L5 - 0x100000 +# L6: +# c.jal L6 - 0x800 +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .reloc_zero +# CHECK: Content: 6F0000000120 +# 11000: 0000006f j 11000 +# 11004: 2001 jal 11004 +# +# CHECK: - Name: .reloc_max +# CHECK: Content: 6FF0FF7FFD2F +# 11006: 7ffff06f j 111004 +# 1100a: 2ffd jal 11808 +# +# CHECK: - Name: .reloc_min +# CHECK: Content: 6F0000800130 +# 1100c: 8000006f j fff1100c +# 11010: 3001 jal 10810 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_zero + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: 6F0000000120 + - Name: .rela.reloc_zero + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_zero + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_JAL + - Offset: 0x0000000000000004 + Symbol: L2 + Type: R_RISCV_RVC_JUMP + - Name: .reloc_max + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: 6FF0FF7FFD2F + - Name: .rela.reloc_max + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_max + Relocations: + - Offset: 0x0000000000000000 + Symbol: L3 + Type: R_RISCV_JAL + Addend: 1048574 + - Offset: 0x0000000000000004 + Symbol: L4 + Type: R_RISCV_RVC_JUMP + Addend: 2046 + - Name: .reloc_min + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: 6F0000800130 + - Name: .rela.reloc_min + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_min + Relocations: + - Offset: 0x0000000000000000 + Symbol: L5 + Type: R_RISCV_JAL + Addend: -1048576 + - Offset: 0x0000000000000004 + Symbol: L6 + Type: R_RISCV_RVC_JUMP + Addend: -2048 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_zero + Type: STT_SECTION + Section: .reloc_zero + - Name: L1 + Section: .reloc_zero + - Name: L2 + Section: .reloc_zero + Value: 0x0000000000000004 + - Name: .reloc_max + Type: STT_SECTION + Section: .reloc_max + - Name: L3 + Section: .reloc_max + - Name: L4 + Section: .reloc_max + Value: 0x0000000000000004 + - Name: .reloc_min + Type: STT_SECTION + Section: .reloc_min + - Name: L5 + Section: .reloc_min + - Name: L6 + Section: .reloc_min + Value: 0x0000000000000004 + Global: + - Name: _start + Section: .reloc_zero +... Index: lld/trunk/test/ELF/riscv-pcrel-hilo.test =================================================================== --- lld/trunk/test/ELF/riscv-pcrel-hilo.test +++ lld/trunk/test/ELF/riscv-pcrel-hilo.test @@ -0,0 +1,103 @@ +# .option norelax +# .global _start +# +# _start: +# auipc a0, %pcrel_hi(_start + 4) +# addi a0, a0, %pcrel_lo(_start) +# +# .section .reloc_neg, "ax", @progbits +# L1: +# auipc a0, %pcrel_hi(L1 - 2) +# addi a0, a0, %pcrel_lo(L1) +# +# +# REQUIRES: riscv +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: obj2yaml %t | FileCheck %s +# +# CHECK: - Name: .text +# CHECK: Content: '1705000013054500' +# 11000: 00000517 auipc a0,0x0 +# 11004: 00450513 addi a0,a0,4 # 11004 <_start+0x4> +# +# CHECK: - Name: .reloc_neg +# CHECK: Content: 170500001305E5FF +# 11008: 00000517 auipc a0,0x0 +# 1100c: ffe50513 addi a0,a0,-2 # 11006 <_start+0x6> + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000002 + Content: '1705000013050500' + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: _start + Type: R_RISCV_PCREL_HI20 + Addend: 4 + - Offset: 0x0000000000000004 + Symbol: _start + Type: R_RISCV_PCREL_LO12_I + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + - Name: .reloc_neg + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000001 + Content: '1705000013050500' + - Name: .rela.reloc_neg + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .reloc_neg + Relocations: + - Offset: 0x0000000000000000 + Symbol: L1 + Type: R_RISCV_PCREL_HI20 + Addend: -2 + - Offset: 0x0000000000000004 + Symbol: L1 + Type: R_RISCV_PCREL_LO12_I +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .reloc_neg + Type: STT_SECTION + Section: .reloc_neg + - Name: L1 + Section: .reloc_neg + Global: + - Name: _start + Section: .text +... Index: lld/trunk/test/lit.cfg.py =================================================================== --- lld/trunk/test/lit.cfg.py +++ lld/trunk/test/lit.cfg.py @@ -68,6 +68,7 @@ 'Hexagon': 'hexagon', 'Mips': 'mips', 'PowerPC': 'ppc', + 'RISCV': 'riscv', 'Sparc': 'sparc', 'WebAssembly': 'wasm', 'X86': 'x86'})