1//===-- RISCVMCTargetDesc.cpp - RISC-V Target Descriptions ----------------===//
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/// This file provides RISC-V specific target descriptions.
10///
11//===----------------------------------------------------------------------===//
12
13#include "RISCVMCTargetDesc.h"
14#include "RISCVELFStreamer.h"
15#include "RISCVInstPrinter.h"
16#include "RISCVMCAsmInfo.h"
17#include "RISCVMCObjectFileInfo.h"
18#include "RISCVTargetStreamer.h"
19#include "TargetInfo/RISCVTargetInfo.h"
20#include "llvm/MC/MCAsmBackend.h"
21#include "llvm/MC/MCAsmInfo.h"
22#include "llvm/MC/MCCodeEmitter.h"
23#include "llvm/MC/MCInstrAnalysis.h"
24#include "llvm/MC/MCInstrInfo.h"
25#include "llvm/MC/MCObjectFileInfo.h"
26#include "llvm/MC/MCObjectWriter.h"
27#include "llvm/MC/MCRegisterInfo.h"
28#include "llvm/MC/MCStreamer.h"
29#include "llvm/MC/MCSubtargetInfo.h"
30#include "llvm/MC/TargetRegistry.h"
31#include "llvm/Support/Compiler.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/MathExtras.h"
34#include <bitset>
35
36#define GET_INSTRINFO_MC_DESC
37#define ENABLE_INSTR_PREDICATE_VERIFIER
38#define GET_INSTRINFO_NAMED_OPS
39#include "RISCVGenInstrInfo.inc"
40
41#define GET_REGINFO_MC_DESC
42#include "RISCVGenRegisterInfo.inc"
43
44#define GET_SUBTARGETINFO_MC_DESC
45#include "RISCVGenSubtargetInfo.inc"
46
47using namespace llvm;
48
49static MCInstrInfo *createRISCVMCInstrInfo() {
50 MCInstrInfo *X = new MCInstrInfo();
51 InitRISCVMCInstrInfo(II: X);
52 return X;
53}
54
55static MCRegisterInfo *createRISCVMCRegisterInfo(const Triple &TT) {
56 MCRegisterInfo *X = new MCRegisterInfo();
57 InitRISCVMCRegisterInfo(RI: X, RA: RISCV::X1);
58 return X;
59}
60
61static MCAsmInfo *createRISCVMCAsmInfo(const MCRegisterInfo &MRI,
62 const Triple &TT,
63 const MCTargetOptions &Options) {
64 MCAsmInfo *MAI = nullptr;
65 if (TT.isOSBinFormatELF())
66 MAI = new RISCVMCAsmInfo(TT);
67 else if (TT.isOSBinFormatMachO())
68 MAI = new RISCVMCAsmInfoDarwin();
69 else
70 reportFatalUsageError(reason: "unsupported object format");
71
72 unsigned SP = MRI.getDwarfRegNum(Reg: RISCV::X2, isEH: true);
73 MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(L: nullptr, Register: SP, Offset: 0);
74 MAI->addInitialFrameState(Inst);
75
76 return MAI;
77}
78
79static MCObjectFileInfo *
80createRISCVMCObjectFileInfo(MCContext &Ctx, bool PIC,
81 bool LargeCodeModel = false) {
82 MCObjectFileInfo *MOFI = new RISCVMCObjectFileInfo();
83 MOFI->initMCObjectFileInfo(MCCtx&: Ctx, PIC, LargeCodeModel);
84 return MOFI;
85}
86
87void RISCV::updateCZceFeatureImplications(MCSubtargetInfo &STI) {
88 // Add Zcd if C and D are enabled.
89 if (STI.hasFeature(Feature: RISCV::FeatureStdExtC) &&
90 STI.hasFeature(Feature: RISCV::FeatureStdExtD) &&
91 !STI.hasFeature(Feature: RISCV::FeatureStdExtZcd))
92 STI.ToggleFeature(FB: RISCV::FeatureStdExtZcd);
93
94 // Add Zcf if F and C or Zce are enabled on RV32.
95 if (!STI.hasFeature(Feature: RISCV::FeatureStdExtZcf) &&
96 !STI.hasFeature(Feature: RISCV::Feature64Bit) &&
97 STI.hasFeature(Feature: RISCV::FeatureStdExtF) &&
98 (STI.hasFeature(Feature: RISCV::FeatureStdExtC) ||
99 STI.hasFeature(Feature: RISCV::FeatureStdExtZce)))
100 STI.ToggleFeature(FB: RISCV::FeatureStdExtZcf);
101
102 // Add C if Zca is enabled and the conditions are met.
103 // This follows the RISC-V spec rules for MISA.C and matches GCC behavior
104 // (PR119122). The rule is:
105 // For RV32:
106 // - No F and no D: Zca alone implies C
107 // - F but no D: Zca + Zcf implies C
108 // - F and D: Zca + Zcf + Zcd implies C
109 // For RV64:
110 // - No D: Zca alone implies C
111 // - D: Zca + Zcd implies C
112 if (!STI.hasFeature(Feature: RISCV::FeatureStdExtC) &&
113 STI.hasFeature(Feature: RISCV::FeatureStdExtZca)) {
114 bool ShouldAddC = false;
115 if (!STI.hasFeature(Feature: RISCV::Feature64Bit))
116 ShouldAddC = (!STI.hasFeature(Feature: RISCV::FeatureStdExtD) ||
117 STI.hasFeature(Feature: RISCV::FeatureStdExtZcd)) &&
118 (!STI.hasFeature(Feature: RISCV::FeatureStdExtF) ||
119 STI.hasFeature(Feature: RISCV::FeatureStdExtZcf));
120 else
121 ShouldAddC = (!STI.hasFeature(Feature: RISCV::FeatureStdExtD) ||
122 STI.hasFeature(Feature: RISCV::FeatureStdExtZcd));
123 if (ShouldAddC)
124 STI.ToggleFeature(FB: RISCV::FeatureStdExtC);
125 }
126
127 // Add Zce if Zca+Zcb+Zcmp+Zcmt are enabled and the conditions are met.
128 // For RV32:
129 // - No F and no D: Zca+Zcb+Zcmp+Zcmt alone implies Zce
130 // - F: Zca+Zcb+Zcmp+Zcmt + Zcf implies Zce
131 // For RV64:
132 // - Zca+Zcb+Zcmp+Zcmt alone implies Zce
133 if (!STI.hasFeature(Feature: RISCV::FeatureStdExtZce) &&
134 STI.hasFeature(Feature: RISCV::FeatureStdExtZca) &&
135 STI.hasFeature(Feature: RISCV::FeatureStdExtZcb) &&
136 STI.hasFeature(Feature: RISCV::FeatureStdExtZcmp) &&
137 STI.hasFeature(Feature: RISCV::FeatureStdExtZcmt)) {
138 if (STI.hasFeature(Feature: RISCV::Feature64Bit) ||
139 !STI.hasFeature(Feature: RISCV::FeatureStdExtF) ||
140 STI.hasFeature(Feature: RISCV::FeatureStdExtZcf))
141 STI.ToggleFeature(FB: RISCV::FeatureStdExtZce);
142 }
143}
144
145static MCSubtargetInfo *
146createRISCVMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
147 if (CPU.empty() || CPU == "generic")
148 CPU = TT.isArch64Bit() ? "generic-rv64" : "generic-rv32";
149
150 MCSubtargetInfo *X =
151 createRISCVMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
152
153 // If the CPU is "help" fill in 64 or 32 bit feature so we can pass
154 // RISCVFeatures::validate.
155 // FIXME: Why does llvm-mc still expect a source file with -mcpu=help?
156 if (CPU == "help") {
157 llvm::FeatureBitset Features = X->getFeatureBits();
158 if (TT.isArch64Bit())
159 Features.set(RISCV::Feature64Bit);
160 else
161 Features.set(RISCV::Feature32Bit);
162 X->setFeatureBits(Features);
163 }
164
165 RISCV::updateCZceFeatureImplications(STI&: *X);
166
167 return X;
168}
169
170static MCInstPrinter *createRISCVMCInstPrinter(const Triple &T,
171 unsigned SyntaxVariant,
172 const MCAsmInfo &MAI,
173 const MCInstrInfo &MII,
174 const MCRegisterInfo &MRI) {
175 return new RISCVInstPrinter(MAI, MII, MRI);
176}
177
178static MCTargetStreamer *
179createRISCVObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
180 const Triple &TT = STI.getTargetTriple();
181 if (TT.isOSBinFormatELF())
182 return new RISCVTargetELFStreamer(S, STI);
183 return new RISCVTargetStreamer(S);
184}
185
186static MCStreamer *
187createMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB,
188 std::unique_ptr<MCObjectWriter> &&OW,
189 std::unique_ptr<MCCodeEmitter> &&Emitter) {
190 return createMachOStreamer(Ctx, TAB: std::move(TAB), OW: std::move(OW),
191 CE: std::move(Emitter),
192 /*DWARFMustBeAtTheEnd*/ false,
193 /*LabelSections*/ true);
194}
195
196static MCTargetStreamer *
197createRISCVAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
198 MCInstPrinter *InstPrint) {
199 return new RISCVTargetAsmStreamer(S, OS);
200}
201
202static MCTargetStreamer *createRISCVNullTargetStreamer(MCStreamer &S) {
203 return new RISCVTargetStreamer(S);
204}
205
206namespace {
207
208class RISCVMCInstrAnalysis : public MCInstrAnalysis {
209 int64_t GPRState[31] = {};
210 std::bitset<31> GPRValidMask;
211
212 static bool isGPR(MCRegister Reg) {
213 return Reg >= RISCV::X0 && Reg <= RISCV::X31;
214 }
215 static bool isYGPR(MCRegister Reg) {
216 return Reg >= RISCV::X0_Y && Reg <= RISCV::X31_Y;
217 }
218 static bool isZeroReg(MCRegister Reg) {
219 return Reg == RISCV::X0 || Reg == RISCV::X0_Y;
220 }
221
222 static unsigned getRegIndex(MCRegister Reg) {
223 if (isYGPR(Reg)) {
224 assert(Reg != RISCV::X0_Y && "Invalid GPR reg");
225 return Reg - RISCV::X1_Y;
226 }
227 assert(isGPR(Reg) && Reg != RISCV::X0 && "Invalid GPR reg");
228 return Reg - RISCV::X1;
229 }
230
231 void setGPRState(MCRegister Reg, std::optional<int64_t> Value) {
232 if (isZeroReg(Reg))
233 return;
234
235 auto Index = getRegIndex(Reg);
236
237 if (Value) {
238 GPRState[Index] = *Value;
239 GPRValidMask.set(position: Index);
240 } else {
241 GPRValidMask.reset(position: Index);
242 }
243 }
244
245 std::optional<int64_t> getGPRState(MCRegister Reg) const {
246 if (isZeroReg(Reg))
247 return 0;
248
249 auto Index = getRegIndex(Reg);
250
251 if (GPRValidMask.test(position: Index))
252 return GPRState[Index];
253 return std::nullopt;
254 }
255
256public:
257 explicit RISCVMCInstrAnalysis(const MCInstrInfo *Info)
258 : MCInstrAnalysis(Info) {}
259
260 void resetState() override { GPRValidMask.reset(); }
261
262 void updateState(const MCInst &Inst, uint64_t Addr) override {
263 // Terminators mark the end of a basic block which means the sequentially
264 // next instruction will be the first of another basic block and the current
265 // state will typically not be valid anymore. For calls, we assume all
266 // registers may be clobbered by the callee (TODO: should we take the
267 // calling convention into account?).
268 if (isTerminator(Inst) || isCall(Inst)) {
269 resetState();
270 return;
271 }
272
273 switch (Inst.getOpcode()) {
274 default: {
275 // Clear the state of all defined registers for instructions that we don't
276 // explicitly support.
277 auto NumDefs = Info->get(Opcode: Inst.getOpcode()).getNumDefs();
278 for (unsigned I = 0; I < NumDefs; ++I) {
279 auto DefReg = Inst.getOperand(i: I).getReg();
280 if (isGPR(Reg: DefReg))
281 setGPRState(Reg: DefReg, Value: std::nullopt);
282 }
283 break;
284 }
285 case RISCV::AUIPC:
286 setGPRState(Reg: Inst.getOperand(i: 0).getReg(),
287 Value: Addr + SignExtend64<32>(x: Inst.getOperand(i: 1).getImm() << 12));
288 break;
289 }
290 }
291
292 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
293 uint64_t &Target) const override {
294 if (isConditionalBranch(Inst)) {
295 int64_t Imm;
296 if (Size == 2)
297 Imm = Inst.getOperand(i: 1).getImm();
298 else
299 Imm = Inst.getOperand(i: 2).getImm();
300 Target = Addr + Imm;
301 return true;
302 }
303
304 switch (Inst.getOpcode()) {
305 case RISCV::C_J:
306 case RISCV::C_JAL:
307 case RISCV::QC_E_J:
308 case RISCV::QC_E_JAL:
309 Target = Addr + Inst.getOperand(i: 0).getImm();
310 return true;
311 case RISCV::JAL:
312 Target = Addr + Inst.getOperand(i: 1).getImm();
313 return true;
314 case RISCV::JALR: {
315 if (auto TargetRegState = getGPRState(Reg: Inst.getOperand(i: 1).getReg())) {
316 Target = *TargetRegState + Inst.getOperand(i: 2).getImm();
317 return true;
318 }
319 return false;
320 }
321 }
322
323 return false;
324 }
325
326 bool isTerminator(const MCInst &Inst) const override {
327 if (MCInstrAnalysis::isTerminator(Inst))
328 return true;
329
330 switch (Inst.getOpcode()) {
331 default:
332 return false;
333 case RISCV::JAL:
334 case RISCV::JALR:
335 return Inst.getOperand(i: 0).getReg() == RISCV::X0;
336 }
337 }
338
339 bool isCall(const MCInst &Inst) const override {
340 if (MCInstrAnalysis::isCall(Inst))
341 return true;
342
343 switch (Inst.getOpcode()) {
344 default:
345 return false;
346 case RISCV::JAL:
347 case RISCV::JALR:
348 return Inst.getOperand(i: 0).getReg() != RISCV::X0;
349 }
350 }
351
352 bool isReturn(const MCInst &Inst) const override {
353 if (MCInstrAnalysis::isReturn(Inst))
354 return true;
355
356 switch (Inst.getOpcode()) {
357 default:
358 return false;
359 case RISCV::JALR:
360 return Inst.getOperand(i: 0).getReg() == RISCV::X0 &&
361 maybeReturnAddress(Reg: Inst.getOperand(i: 1).getReg());
362 case RISCV::C_JR:
363 return maybeReturnAddress(Reg: Inst.getOperand(i: 0).getReg());
364 }
365 }
366
367 bool isBranch(const MCInst &Inst) const override {
368 if (MCInstrAnalysis::isBranch(Inst))
369 return true;
370
371 return isBranchImpl(Inst);
372 }
373
374 bool isUnconditionalBranch(const MCInst &Inst) const override {
375 if (MCInstrAnalysis::isUnconditionalBranch(Inst))
376 return true;
377
378 return isBranchImpl(Inst);
379 }
380
381 bool isIndirectBranch(const MCInst &Inst) const override {
382 if (MCInstrAnalysis::isIndirectBranch(Inst))
383 return true;
384
385 switch (Inst.getOpcode()) {
386 default:
387 return false;
388 case RISCV::JALR:
389 return Inst.getOperand(i: 0).getReg() == RISCV::X0 &&
390 !maybeReturnAddress(Reg: Inst.getOperand(i: 1).getReg());
391 case RISCV::C_JR:
392 return !maybeReturnAddress(Reg: Inst.getOperand(i: 0).getReg());
393 }
394 }
395
396 /// Returns (PLT virtual address, GOT virtual address) pairs for PLT entries.
397 std::vector<std::pair<uint64_t, uint64_t>>
398 findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,
399 const MCSubtargetInfo &STI) const override {
400 uint32_t LoadInsnOpCode;
401 if (const Triple &T = STI.getTargetTriple(); T.isRISCV64())
402 LoadInsnOpCode = 0x3003; // ld
403 else if (T.isRISCV32())
404 LoadInsnOpCode = 0x2003; // lw
405 else
406 return {};
407
408 constexpr uint64_t FirstEntryAt = 32, EntrySize = 16;
409 if (PltContents.size() < FirstEntryAt + EntrySize)
410 return {};
411
412 std::vector<std::pair<uint64_t, uint64_t>> Results;
413 for (uint64_t EntryStart = FirstEntryAt,
414 EntryStartEnd = PltContents.size() - EntrySize;
415 EntryStart <= EntryStartEnd; EntryStart += EntrySize) {
416 const uint32_t AuipcInsn =
417 support::endian::read32le(P: PltContents.data() + EntryStart);
418 const bool IsAuipc = (AuipcInsn & 0x7F) == 0x17;
419 if (!IsAuipc)
420 continue;
421
422 const uint32_t LoadInsn =
423 support::endian::read32le(P: PltContents.data() + EntryStart + 4);
424 const bool IsLoad = (LoadInsn & 0x707F) == LoadInsnOpCode;
425 if (!IsLoad)
426 continue;
427
428 const uint64_t GotPltSlotVA = PltSectionVA + EntryStart +
429 (AuipcInsn & 0xFFFFF000) +
430 SignExtend64<12>(x: LoadInsn >> 20);
431 Results.emplace_back(args: PltSectionVA + EntryStart, args: GotPltSlotVA);
432 }
433
434 return Results;
435 }
436
437private:
438 static bool maybeReturnAddress(MCRegister Reg) {
439 // X1 is used for normal returns, X5 for returns from outlined functions.
440 return Reg == RISCV::X1 || Reg == RISCV::X5;
441 }
442
443 static bool isBranchImpl(const MCInst &Inst) {
444 switch (Inst.getOpcode()) {
445 default:
446 return false;
447 case RISCV::JAL:
448 return Inst.getOperand(i: 0).getReg() == RISCV::X0;
449 case RISCV::JALR:
450 return Inst.getOperand(i: 0).getReg() == RISCV::X0 &&
451 !maybeReturnAddress(Reg: Inst.getOperand(i: 1).getReg());
452 case RISCV::C_JR:
453 return !maybeReturnAddress(Reg: Inst.getOperand(i: 0).getReg());
454 }
455 }
456};
457
458} // end anonymous namespace
459
460static MCInstrAnalysis *createRISCVInstrAnalysis(const MCInstrInfo *Info) {
461 return new RISCVMCInstrAnalysis(Info);
462}
463
464extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
465LLVMInitializeRISCVTargetMC() {
466 for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target(),
467 &getTheRISCV32beTarget(), &getTheRISCV64beTarget()}) {
468 TargetRegistry::RegisterMCAsmInfo(T&: *T, Fn: createRISCVMCAsmInfo);
469 TargetRegistry::RegisterMCObjectFileInfo(T&: *T, Fn: createRISCVMCObjectFileInfo);
470 TargetRegistry::RegisterMCInstrInfo(T&: *T, Fn: createRISCVMCInstrInfo);
471 TargetRegistry::RegisterMCRegInfo(T&: *T, Fn: createRISCVMCRegisterInfo);
472 TargetRegistry::RegisterMCAsmBackend(T&: *T, Fn: createRISCVAsmBackend);
473 TargetRegistry::RegisterMCCodeEmitter(T&: *T, Fn: createRISCVMCCodeEmitter);
474 TargetRegistry::RegisterMCInstPrinter(T&: *T, Fn: createRISCVMCInstPrinter);
475 TargetRegistry::RegisterMCSubtargetInfo(T&: *T, Fn: createRISCVMCSubtargetInfo);
476 TargetRegistry::RegisterELFStreamer(T&: *T, Fn: createRISCVELFStreamer);
477 TargetRegistry::RegisterMachOStreamer(T&: *T, Fn: createMachOStreamer);
478 TargetRegistry::RegisterObjectTargetStreamer(
479 T&: *T, Fn: createRISCVObjectTargetStreamer);
480 TargetRegistry::RegisterMCInstrAnalysis(T&: *T, Fn: createRISCVInstrAnalysis);
481
482 // Register the asm target streamer.
483 TargetRegistry::RegisterAsmTargetStreamer(T&: *T, Fn: createRISCVAsmTargetStreamer);
484 // Register the null target streamer.
485 TargetRegistry::RegisterNullTargetStreamer(T&: *T,
486 Fn: createRISCVNullTargetStreamer);
487 }
488}
489