401 lines · cpp
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-exception6//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_DESC37#define ENABLE_INSTR_PREDICATE_VERIFIER38#include "RISCVGenInstrInfo.inc"39 40#define GET_REGINFO_MC_DESC41#include "RISCVGenRegisterInfo.inc"42 43#define GET_SUBTARGETINFO_MC_DESC44#include "RISCVGenSubtargetInfo.inc"45 46using namespace llvm;47 48static MCInstrInfo *createRISCVMCInstrInfo() {49 MCInstrInfo *X = new MCInstrInfo();50 InitRISCVMCInstrInfo(X);51 return X;52}53 54static MCRegisterInfo *createRISCVMCRegisterInfo(const Triple &TT) {55 MCRegisterInfo *X = new MCRegisterInfo();56 InitRISCVMCRegisterInfo(X, RISCV::X1);57 return X;58}59 60static MCAsmInfo *createRISCVMCAsmInfo(const MCRegisterInfo &MRI,61 const Triple &TT,62 const MCTargetOptions &Options) {63 MCAsmInfo *MAI = new RISCVMCAsmInfo(TT);64 65 unsigned SP = MRI.getDwarfRegNum(RISCV::X2, true);66 MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0);67 MAI->addInitialFrameState(Inst);68 69 return MAI;70}71 72static MCObjectFileInfo *73createRISCVMCObjectFileInfo(MCContext &Ctx, bool PIC,74 bool LargeCodeModel = false) {75 MCObjectFileInfo *MOFI = new RISCVMCObjectFileInfo();76 MOFI->initMCObjectFileInfo(Ctx, PIC, LargeCodeModel);77 return MOFI;78}79 80static MCSubtargetInfo *createRISCVMCSubtargetInfo(const Triple &TT,81 StringRef CPU, StringRef FS) {82 if (CPU.empty() || CPU == "generic")83 CPU = TT.isArch64Bit() ? "generic-rv64" : "generic-rv32";84 85 MCSubtargetInfo *X =86 createRISCVMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);87 88 // If the CPU is "help" fill in 64 or 32 bit feature so we can pass89 // RISCVFeatures::validate.90 // FIXME: Why does llvm-mc still expect a source file with -mcpu=help?91 if (CPU == "help") {92 llvm::FeatureBitset Features = X->getFeatureBits();93 if (TT.isArch64Bit())94 Features.set(RISCV::Feature64Bit);95 else96 Features.set(RISCV::Feature32Bit);97 X->setFeatureBits(Features);98 }99 100 return X;101}102 103static MCInstPrinter *createRISCVMCInstPrinter(const Triple &T,104 unsigned SyntaxVariant,105 const MCAsmInfo &MAI,106 const MCInstrInfo &MII,107 const MCRegisterInfo &MRI) {108 return new RISCVInstPrinter(MAI, MII, MRI);109}110 111static MCTargetStreamer *112createRISCVObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {113 const Triple &TT = STI.getTargetTriple();114 if (TT.isOSBinFormatELF())115 return new RISCVTargetELFStreamer(S, STI);116 return nullptr;117}118 119static MCTargetStreamer *120createRISCVAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,121 MCInstPrinter *InstPrint) {122 return new RISCVTargetAsmStreamer(S, OS);123}124 125static MCTargetStreamer *createRISCVNullTargetStreamer(MCStreamer &S) {126 return new RISCVTargetStreamer(S);127}128 129namespace {130 131class RISCVMCInstrAnalysis : public MCInstrAnalysis {132 int64_t GPRState[31] = {};133 std::bitset<31> GPRValidMask;134 135 static bool isGPR(MCRegister Reg) {136 return Reg >= RISCV::X0 && Reg <= RISCV::X31;137 }138 139 static unsigned getRegIndex(MCRegister Reg) {140 assert(isGPR(Reg) && Reg != RISCV::X0 && "Invalid GPR reg");141 return Reg - RISCV::X1;142 }143 144 void setGPRState(MCRegister Reg, std::optional<int64_t> Value) {145 if (Reg == RISCV::X0)146 return;147 148 auto Index = getRegIndex(Reg);149 150 if (Value) {151 GPRState[Index] = *Value;152 GPRValidMask.set(Index);153 } else {154 GPRValidMask.reset(Index);155 }156 }157 158 std::optional<int64_t> getGPRState(MCRegister Reg) const {159 if (Reg == RISCV::X0)160 return 0;161 162 auto Index = getRegIndex(Reg);163 164 if (GPRValidMask.test(Index))165 return GPRState[Index];166 return std::nullopt;167 }168 169public:170 explicit RISCVMCInstrAnalysis(const MCInstrInfo *Info)171 : MCInstrAnalysis(Info) {}172 173 void resetState() override { GPRValidMask.reset(); }174 175 void updateState(const MCInst &Inst, uint64_t Addr) override {176 // Terminators mark the end of a basic block which means the sequentially177 // next instruction will be the first of another basic block and the current178 // state will typically not be valid anymore. For calls, we assume all179 // registers may be clobbered by the callee (TODO: should we take the180 // calling convention into account?).181 if (isTerminator(Inst) || isCall(Inst)) {182 resetState();183 return;184 }185 186 switch (Inst.getOpcode()) {187 default: {188 // Clear the state of all defined registers for instructions that we don't189 // explicitly support.190 auto NumDefs = Info->get(Inst.getOpcode()).getNumDefs();191 for (unsigned I = 0; I < NumDefs; ++I) {192 auto DefReg = Inst.getOperand(I).getReg();193 if (isGPR(DefReg))194 setGPRState(DefReg, std::nullopt);195 }196 break;197 }198 case RISCV::AUIPC:199 setGPRState(Inst.getOperand(0).getReg(),200 Addr + SignExtend64<32>(Inst.getOperand(1).getImm() << 12));201 break;202 }203 }204 205 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,206 uint64_t &Target) const override {207 if (isConditionalBranch(Inst)) {208 int64_t Imm;209 if (Size == 2)210 Imm = Inst.getOperand(1).getImm();211 else212 Imm = Inst.getOperand(2).getImm();213 Target = Addr + Imm;214 return true;215 }216 217 switch (Inst.getOpcode()) {218 case RISCV::C_J:219 case RISCV::C_JAL:220 case RISCV::QC_E_J:221 case RISCV::QC_E_JAL:222 Target = Addr + Inst.getOperand(0).getImm();223 return true;224 case RISCV::JAL:225 Target = Addr + Inst.getOperand(1).getImm();226 return true;227 case RISCV::JALR: {228 if (auto TargetRegState = getGPRState(Inst.getOperand(1).getReg())) {229 Target = *TargetRegState + Inst.getOperand(2).getImm();230 return true;231 }232 return false;233 }234 }235 236 return false;237 }238 239 bool isTerminator(const MCInst &Inst) const override {240 if (MCInstrAnalysis::isTerminator(Inst))241 return true;242 243 switch (Inst.getOpcode()) {244 default:245 return false;246 case RISCV::JAL:247 case RISCV::JALR:248 return Inst.getOperand(0).getReg() == RISCV::X0;249 }250 }251 252 bool isCall(const MCInst &Inst) const override {253 if (MCInstrAnalysis::isCall(Inst))254 return true;255 256 switch (Inst.getOpcode()) {257 default:258 return false;259 case RISCV::JAL:260 case RISCV::JALR:261 return Inst.getOperand(0).getReg() != RISCV::X0;262 }263 }264 265 bool isReturn(const MCInst &Inst) const override {266 if (MCInstrAnalysis::isReturn(Inst))267 return true;268 269 switch (Inst.getOpcode()) {270 default:271 return false;272 case RISCV::JALR:273 return Inst.getOperand(0).getReg() == RISCV::X0 &&274 maybeReturnAddress(Inst.getOperand(1).getReg());275 case RISCV::C_JR:276 return maybeReturnAddress(Inst.getOperand(0).getReg());277 }278 }279 280 bool isBranch(const MCInst &Inst) const override {281 if (MCInstrAnalysis::isBranch(Inst))282 return true;283 284 return isBranchImpl(Inst);285 }286 287 bool isUnconditionalBranch(const MCInst &Inst) const override {288 if (MCInstrAnalysis::isUnconditionalBranch(Inst))289 return true;290 291 return isBranchImpl(Inst);292 }293 294 bool isIndirectBranch(const MCInst &Inst) const override {295 if (MCInstrAnalysis::isIndirectBranch(Inst))296 return true;297 298 switch (Inst.getOpcode()) {299 default:300 return false;301 case RISCV::JALR:302 return Inst.getOperand(0).getReg() == RISCV::X0 &&303 !maybeReturnAddress(Inst.getOperand(1).getReg());304 case RISCV::C_JR:305 return !maybeReturnAddress(Inst.getOperand(0).getReg());306 }307 }308 309 /// Returns (PLT virtual address, GOT virtual address) pairs for PLT entries.310 std::vector<std::pair<uint64_t, uint64_t>>311 findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,312 const MCSubtargetInfo &STI) const override {313 uint32_t LoadInsnOpCode;314 if (const Triple &T = STI.getTargetTriple(); T.isRISCV64())315 LoadInsnOpCode = 0x3003; // ld316 else if (T.isRISCV32())317 LoadInsnOpCode = 0x2003; // lw318 else319 return {};320 321 constexpr uint64_t FirstEntryAt = 32, EntrySize = 16;322 if (PltContents.size() < FirstEntryAt + EntrySize)323 return {};324 325 std::vector<std::pair<uint64_t, uint64_t>> Results;326 for (uint64_t EntryStart = FirstEntryAt,327 EntryStartEnd = PltContents.size() - EntrySize;328 EntryStart <= EntryStartEnd; EntryStart += EntrySize) {329 const uint32_t AuipcInsn =330 support::endian::read32le(PltContents.data() + EntryStart);331 const bool IsAuipc = (AuipcInsn & 0x7F) == 0x17;332 if (!IsAuipc)333 continue;334 335 const uint32_t LoadInsn =336 support::endian::read32le(PltContents.data() + EntryStart + 4);337 const bool IsLoad = (LoadInsn & 0x707F) == LoadInsnOpCode;338 if (!IsLoad)339 continue;340 341 const uint64_t GotPltSlotVA = PltSectionVA + EntryStart +342 (AuipcInsn & 0xFFFFF000) +343 SignExtend64<12>(LoadInsn >> 20);344 Results.emplace_back(PltSectionVA + EntryStart, GotPltSlotVA);345 }346 347 return Results;348 }349 350private:351 static bool maybeReturnAddress(MCRegister Reg) {352 // X1 is used for normal returns, X5 for returns from outlined functions.353 return Reg == RISCV::X1 || Reg == RISCV::X5;354 }355 356 static bool isBranchImpl(const MCInst &Inst) {357 switch (Inst.getOpcode()) {358 default:359 return false;360 case RISCV::JAL:361 return Inst.getOperand(0).getReg() == RISCV::X0;362 case RISCV::JALR:363 return Inst.getOperand(0).getReg() == RISCV::X0 &&364 !maybeReturnAddress(Inst.getOperand(1).getReg());365 case RISCV::C_JR:366 return !maybeReturnAddress(Inst.getOperand(0).getReg());367 }368 }369};370 371} // end anonymous namespace372 373static MCInstrAnalysis *createRISCVInstrAnalysis(const MCInstrInfo *Info) {374 return new RISCVMCInstrAnalysis(Info);375}376 377extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void378LLVMInitializeRISCVTargetMC() {379 for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target(),380 &getTheRISCV32beTarget(), &getTheRISCV64beTarget()}) {381 TargetRegistry::RegisterMCAsmInfo(*T, createRISCVMCAsmInfo);382 TargetRegistry::RegisterMCObjectFileInfo(*T, createRISCVMCObjectFileInfo);383 TargetRegistry::RegisterMCInstrInfo(*T, createRISCVMCInstrInfo);384 TargetRegistry::RegisterMCRegInfo(*T, createRISCVMCRegisterInfo);385 TargetRegistry::RegisterMCAsmBackend(*T, createRISCVAsmBackend);386 TargetRegistry::RegisterMCCodeEmitter(*T, createRISCVMCCodeEmitter);387 TargetRegistry::RegisterMCInstPrinter(*T, createRISCVMCInstPrinter);388 TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo);389 TargetRegistry::RegisterELFStreamer(*T, createRISCVELFStreamer);390 TargetRegistry::RegisterObjectTargetStreamer(391 *T, createRISCVObjectTargetStreamer);392 TargetRegistry::RegisterMCInstrAnalysis(*T, createRISCVInstrAnalysis);393 394 // Register the asm target streamer.395 TargetRegistry::RegisterAsmTargetStreamer(*T, createRISCVAsmTargetStreamer);396 // Register the null target streamer.397 TargetRegistry::RegisterNullTargetStreamer(*T,398 createRISCVNullTargetStreamer);399 }400}401