xref: /llvm-project-15.0.7/lld/ELF/Arch/RISCV.cpp (revision 303c9861)
1 //===- RISCV.cpp ----------------------------------------------------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "InputFiles.h"
10 #include "Target.h"
11 
12 using namespace llvm;
13 using namespace llvm::object;
14 using namespace llvm::support::endian;
15 using namespace llvm::ELF;
16 using namespace lld;
17 using namespace lld::elf;
18 
19 namespace {
20 
21 class RISCV final : public TargetInfo {
22 public:
23   RISCV();
24   uint32_t calcEFlags() const override;
25   RelExpr getRelExpr(RelType Type, const Symbol &S,
26                      const uint8_t *Loc) const override;
27   void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
28 };
29 
30 } // end anonymous namespace
31 
32 RISCV::RISCV() { NoneRel = R_RISCV_NONE; }
33 
34 static uint32_t getEFlags(InputFile *F) {
35   if (Config->Is64)
36     return cast<ObjFile<ELF64LE>>(F)->getObj().getHeader()->e_flags;
37   return cast<ObjFile<ELF32LE>>(F)->getObj().getHeader()->e_flags;
38 }
39 
40 uint32_t RISCV::calcEFlags() const {
41   assert(!ObjectFiles.empty());
42 
43   uint32_t Target = getEFlags(ObjectFiles.front());
44 
45   for (InputFile *F : ObjectFiles) {
46     uint32_t EFlags = getEFlags(F);
47     if (EFlags & EF_RISCV_RVC)
48       Target |= EF_RISCV_RVC;
49 
50     if ((EFlags & EF_RISCV_FLOAT_ABI) != (Target & EF_RISCV_FLOAT_ABI))
51       error(toString(F) +
52             ": cannot link object files with different floating-point ABI");
53 
54     if ((EFlags & EF_RISCV_RVE) != (Target & EF_RISCV_RVE))
55       error(toString(F) +
56             ": cannot link object files with different EF_RISCV_RVE");
57   }
58 
59   return Target;
60 }
61 
62 RelExpr RISCV::getRelExpr(const RelType Type, const Symbol &S,
63                           const uint8_t *Loc) const {
64   switch (Type) {
65   case R_RISCV_ADD8:
66   case R_RISCV_ADD16:
67   case R_RISCV_ADD32:
68   case R_RISCV_ADD64:
69   case R_RISCV_SET6:
70   case R_RISCV_SET8:
71   case R_RISCV_SET16:
72   case R_RISCV_SET32:
73   case R_RISCV_SUB6:
74   case R_RISCV_SUB8:
75   case R_RISCV_SUB16:
76   case R_RISCV_SUB32:
77   case R_RISCV_SUB64:
78     return R_RISCV_ADD;
79   case R_RISCV_JAL:
80   case R_RISCV_BRANCH:
81   case R_RISCV_CALL:
82   case R_RISCV_PCREL_HI20:
83   case R_RISCV_RVC_BRANCH:
84   case R_RISCV_RVC_JUMP:
85   case R_RISCV_32_PCREL:
86     return R_PC;
87   case R_RISCV_PCREL_LO12_I:
88   case R_RISCV_PCREL_LO12_S:
89     return R_RISCV_PC_INDIRECT;
90   case R_RISCV_RELAX:
91   case R_RISCV_ALIGN:
92     return R_HINT;
93   default:
94     return R_ABS;
95   }
96 }
97 
98 // Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63.
99 static uint32_t extractBits(uint64_t V, uint32_t Begin, uint32_t End) {
100   return (V & ((1ULL << (Begin + 1)) - 1)) >> End;
101 }
102 
103 void RISCV::relocateOne(uint8_t *Loc, const RelType Type,
104                         const uint64_t Val) const {
105   const unsigned Bits = Config->Wordsize * 8;
106 
107   switch (Type) {
108   case R_RISCV_32:
109     write32le(Loc, Val);
110     return;
111   case R_RISCV_64:
112     write64le(Loc, Val);
113     return;
114 
115   case R_RISCV_RVC_BRANCH: {
116     checkInt(Loc, static_cast<int64_t>(Val) >> 1, 8, Type);
117     checkAlignment(Loc, Val, 2, Type);
118     uint16_t Insn = read16le(Loc) & 0xE383;
119     uint16_t Imm8 = extractBits(Val, 8, 8) << 12;
120     uint16_t Imm4_3 = extractBits(Val, 4, 3) << 10;
121     uint16_t Imm7_6 = extractBits(Val, 7, 6) << 5;
122     uint16_t Imm2_1 = extractBits(Val, 2, 1) << 3;
123     uint16_t Imm5 = extractBits(Val, 5, 5) << 2;
124     Insn |= Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5;
125 
126     write16le(Loc, Insn);
127     return;
128   }
129 
130   case R_RISCV_RVC_JUMP: {
131     checkInt(Loc, static_cast<int64_t>(Val) >> 1, 11, Type);
132     checkAlignment(Loc, Val, 2, Type);
133     uint16_t Insn = read16le(Loc) & 0xE003;
134     uint16_t Imm11 = extractBits(Val, 11, 11) << 12;
135     uint16_t Imm4 = extractBits(Val, 4, 4) << 11;
136     uint16_t Imm9_8 = extractBits(Val, 9, 8) << 9;
137     uint16_t Imm10 = extractBits(Val, 10, 10) << 8;
138     uint16_t Imm6 = extractBits(Val, 6, 6) << 7;
139     uint16_t Imm7 = extractBits(Val, 7, 7) << 6;
140     uint16_t Imm3_1 = extractBits(Val, 3, 1) << 3;
141     uint16_t Imm5 = extractBits(Val, 5, 5) << 2;
142     Insn |= Imm11 | Imm4 | Imm9_8 | Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5;
143 
144     write16le(Loc, Insn);
145     return;
146   }
147 
148   case R_RISCV_RVC_LUI: {
149     int64_t Imm = SignExtend64(Val + 0x800, Bits) >> 12;
150     checkInt(Loc, Imm, 6, Type);
151     if (Imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0`
152       write16le(Loc, (read16le(Loc) & 0x0F83) | 0x4000);
153     } else {
154       uint16_t Imm17 = extractBits(Val + 0x800, 17, 17) << 12;
155       uint16_t Imm16_12 = extractBits(Val + 0x800, 16, 12) << 2;
156       write16le(Loc, (read16le(Loc) & 0xEF83) | Imm17 | Imm16_12);
157     }
158     return;
159   }
160 
161   case R_RISCV_JAL: {
162     checkInt(Loc, static_cast<int64_t>(Val) >> 1, 20, Type);
163     checkAlignment(Loc, Val, 2, Type);
164 
165     uint32_t Insn = read32le(Loc) & 0xFFF;
166     uint32_t Imm20 = extractBits(Val, 20, 20) << 31;
167     uint32_t Imm10_1 = extractBits(Val, 10, 1) << 21;
168     uint32_t Imm11 = extractBits(Val, 11, 11) << 20;
169     uint32_t Imm19_12 = extractBits(Val, 19, 12) << 12;
170     Insn |= Imm20 | Imm10_1 | Imm11 | Imm19_12;
171 
172     write32le(Loc, Insn);
173     return;
174   }
175 
176   case R_RISCV_BRANCH: {
177     checkInt(Loc, static_cast<int64_t>(Val) >> 1, 12, Type);
178     checkAlignment(Loc, Val, 2, Type);
179 
180     uint32_t Insn = read32le(Loc) & 0x1FFF07F;
181     uint32_t Imm12 = extractBits(Val, 12, 12) << 31;
182     uint32_t Imm10_5 = extractBits(Val, 10, 5) << 25;
183     uint32_t Imm4_1 = extractBits(Val, 4, 1) << 8;
184     uint32_t Imm11 = extractBits(Val, 11, 11) << 7;
185     Insn |= Imm12 | Imm10_5 | Imm4_1 | Imm11;
186 
187     write32le(Loc, Insn);
188     return;
189   }
190 
191   // auipc + jalr pair
192   case R_RISCV_CALL: {
193     int64_t Hi = SignExtend64(Val + 0x800, Bits) >> 12;
194     checkInt(Loc, Hi, 20, Type);
195     if (isInt<20>(Hi)) {
196       relocateOne(Loc, R_RISCV_PCREL_HI20, Val);
197       relocateOne(Loc + 4, R_RISCV_PCREL_LO12_I, Val);
198     }
199     return;
200   }
201 
202   case R_RISCV_PCREL_HI20:
203   case R_RISCV_HI20: {
204     uint64_t Hi = Val + 0x800;
205     checkInt(Loc, SignExtend64(Hi, Bits) >> 12, 20, Type);
206     write32le(Loc, (read32le(Loc) & 0xFFF) | (Hi & 0xFFFFF000));
207     return;
208   }
209 
210   case R_RISCV_PCREL_LO12_I:
211   case R_RISCV_LO12_I: {
212     uint64_t Hi = (Val + 0x800) >> 12;
213     uint64_t Lo = Val - (Hi << 12);
214     write32le(Loc, (read32le(Loc) & 0xFFFFF) | ((Lo & 0xFFF) << 20));
215     return;
216   }
217 
218   case R_RISCV_PCREL_LO12_S:
219   case R_RISCV_LO12_S: {
220     uint64_t Hi = (Val + 0x800) >> 12;
221     uint64_t Lo = Val - (Hi << 12);
222     uint32_t Imm11_5 = extractBits(Lo, 11, 5) << 25;
223     uint32_t Imm4_0 = extractBits(Lo, 4, 0) << 7;
224     write32le(Loc, (read32le(Loc) & 0x1FFF07F) | Imm11_5 | Imm4_0);
225     return;
226   }
227 
228   case R_RISCV_ADD8:
229     *Loc += Val;
230     return;
231   case R_RISCV_ADD16:
232     write16le(Loc, read16le(Loc) + Val);
233     return;
234   case R_RISCV_ADD32:
235     write32le(Loc, read32le(Loc) + Val);
236     return;
237   case R_RISCV_ADD64:
238     write64le(Loc, read64le(Loc) + Val);
239     return;
240   case R_RISCV_SUB6:
241     *Loc = (*Loc & 0xc0) | (((*Loc & 0x3f) - Val) & 0x3f);
242     return;
243   case R_RISCV_SUB8:
244     *Loc -= Val;
245     return;
246   case R_RISCV_SUB16:
247     write16le(Loc, read16le(Loc) - Val);
248     return;
249   case R_RISCV_SUB32:
250     write32le(Loc, read32le(Loc) - Val);
251     return;
252   case R_RISCV_SUB64:
253     write64le(Loc, read64le(Loc) - Val);
254     return;
255   case R_RISCV_SET6:
256     *Loc = (*Loc & 0xc0) | (Val & 0x3f);
257     return;
258   case R_RISCV_SET8:
259     *Loc = Val;
260     return;
261   case R_RISCV_SET16:
262     write16le(Loc, Val);
263     return;
264   case R_RISCV_SET32:
265   case R_RISCV_32_PCREL:
266     write32le(Loc, Val);
267     return;
268 
269   case R_RISCV_ALIGN:
270   case R_RISCV_RELAX:
271     return; // Ignored (for now)
272   case R_RISCV_NONE:
273     return; // Do nothing
274 
275   // These are handled by the dynamic linker
276   case R_RISCV_RELATIVE:
277   case R_RISCV_COPY:
278   case R_RISCV_JUMP_SLOT:
279   // GP-relative relocations are only produced after relaxation, which
280   // we don't support for now
281   case R_RISCV_GPREL_I:
282   case R_RISCV_GPREL_S:
283   default:
284     error(getErrorLocation(Loc) +
285           "unimplemented relocation: " + toString(Type));
286     return;
287   }
288 }
289 
290 TargetInfo *elf::getRISCVTargetInfo() {
291   static RISCV Target;
292   return &Target;
293 }
294