Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
35294 views
//===-- RISCVMCTargetDesc.cpp - RISC-V Target Descriptions ----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// This file provides RISC-V specific target descriptions.9///10//===----------------------------------------------------------------------===//1112#include "RISCVMCTargetDesc.h"13#include "RISCVBaseInfo.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/ADT/STLExtras.h"21#include "llvm/MC/MCAsmBackend.h"22#include "llvm/MC/MCAsmInfo.h"23#include "llvm/MC/MCCodeEmitter.h"24#include "llvm/MC/MCInstrAnalysis.h"25#include "llvm/MC/MCInstrInfo.h"26#include "llvm/MC/MCObjectFileInfo.h"27#include "llvm/MC/MCObjectWriter.h"28#include "llvm/MC/MCRegisterInfo.h"29#include "llvm/MC/MCStreamer.h"30#include "llvm/MC/MCSubtargetInfo.h"31#include "llvm/MC/TargetRegistry.h"32#include "llvm/Support/ErrorHandling.h"33#include <bitset>3435#define GET_INSTRINFO_MC_DESC36#define ENABLE_INSTR_PREDICATE_VERIFIER37#include "RISCVGenInstrInfo.inc"3839#define GET_REGINFO_MC_DESC40#include "RISCVGenRegisterInfo.inc"4142#define GET_SUBTARGETINFO_MC_DESC43#include "RISCVGenSubtargetInfo.inc"4445namespace llvm::RISCVVInversePseudosTable {4647using namespace RISCV;4849#define GET_RISCVVInversePseudosTable_IMPL50#include "RISCVGenSearchableTables.inc"5152} // namespace llvm::RISCVVInversePseudosTable5354using namespace llvm;5556static MCInstrInfo *createRISCVMCInstrInfo() {57MCInstrInfo *X = new MCInstrInfo();58InitRISCVMCInstrInfo(X);59return X;60}6162static MCRegisterInfo *createRISCVMCRegisterInfo(const Triple &TT) {63MCRegisterInfo *X = new MCRegisterInfo();64InitRISCVMCRegisterInfo(X, RISCV::X1);65return X;66}6768static MCAsmInfo *createRISCVMCAsmInfo(const MCRegisterInfo &MRI,69const Triple &TT,70const MCTargetOptions &Options) {71MCAsmInfo *MAI = new RISCVMCAsmInfo(TT);7273MCRegister SP = MRI.getDwarfRegNum(RISCV::X2, true);74MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0);75MAI->addInitialFrameState(Inst);7677return MAI;78}7980static MCObjectFileInfo *81createRISCVMCObjectFileInfo(MCContext &Ctx, bool PIC,82bool LargeCodeModel = false) {83MCObjectFileInfo *MOFI = new RISCVMCObjectFileInfo();84MOFI->initMCObjectFileInfo(Ctx, PIC, LargeCodeModel);85return MOFI;86}8788static MCSubtargetInfo *createRISCVMCSubtargetInfo(const Triple &TT,89StringRef CPU, StringRef FS) {90if (CPU.empty() || CPU == "generic")91CPU = TT.isArch64Bit() ? "generic-rv64" : "generic-rv32";9293return createRISCVMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);94}9596static MCInstPrinter *createRISCVMCInstPrinter(const Triple &T,97unsigned SyntaxVariant,98const MCAsmInfo &MAI,99const MCInstrInfo &MII,100const MCRegisterInfo &MRI) {101return new RISCVInstPrinter(MAI, MII, MRI);102}103104static MCTargetStreamer *105createRISCVObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {106const Triple &TT = STI.getTargetTriple();107if (TT.isOSBinFormatELF())108return new RISCVTargetELFStreamer(S, STI);109return nullptr;110}111112static MCTargetStreamer *113createRISCVAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,114MCInstPrinter *InstPrint) {115return new RISCVTargetAsmStreamer(S, OS);116}117118static MCTargetStreamer *createRISCVNullTargetStreamer(MCStreamer &S) {119return new RISCVTargetStreamer(S);120}121122namespace {123124class RISCVMCInstrAnalysis : public MCInstrAnalysis {125int64_t GPRState[31] = {};126std::bitset<31> GPRValidMask;127128static bool isGPR(unsigned Reg) {129return Reg >= RISCV::X0 && Reg <= RISCV::X31;130}131132static unsigned getRegIndex(unsigned Reg) {133assert(isGPR(Reg) && Reg != RISCV::X0 && "Invalid GPR reg");134return Reg - RISCV::X1;135}136137void setGPRState(unsigned Reg, std::optional<int64_t> Value) {138if (Reg == RISCV::X0)139return;140141auto Index = getRegIndex(Reg);142143if (Value) {144GPRState[Index] = *Value;145GPRValidMask.set(Index);146} else {147GPRValidMask.reset(Index);148}149}150151std::optional<int64_t> getGPRState(unsigned Reg) const {152if (Reg == RISCV::X0)153return 0;154155auto Index = getRegIndex(Reg);156157if (GPRValidMask.test(Index))158return GPRState[Index];159return std::nullopt;160}161162public:163explicit RISCVMCInstrAnalysis(const MCInstrInfo *Info)164: MCInstrAnalysis(Info) {}165166void resetState() override { GPRValidMask.reset(); }167168void updateState(const MCInst &Inst, uint64_t Addr) override {169// Terminators mark the end of a basic block which means the sequentially170// next instruction will be the first of another basic block and the current171// state will typically not be valid anymore. For calls, we assume all172// registers may be clobbered by the callee (TODO: should we take the173// calling convention into account?).174if (isTerminator(Inst) || isCall(Inst)) {175resetState();176return;177}178179switch (Inst.getOpcode()) {180default: {181// Clear the state of all defined registers for instructions that we don't182// explicitly support.183auto NumDefs = Info->get(Inst.getOpcode()).getNumDefs();184for (unsigned I = 0; I < NumDefs; ++I) {185auto DefReg = Inst.getOperand(I).getReg();186if (isGPR(DefReg))187setGPRState(DefReg, std::nullopt);188}189break;190}191case RISCV::AUIPC:192setGPRState(Inst.getOperand(0).getReg(),193Addr + (Inst.getOperand(1).getImm() << 12));194break;195}196}197198bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,199uint64_t &Target) const override {200if (isConditionalBranch(Inst)) {201int64_t Imm;202if (Size == 2)203Imm = Inst.getOperand(1).getImm();204else205Imm = Inst.getOperand(2).getImm();206Target = Addr + Imm;207return true;208}209210if (Inst.getOpcode() == RISCV::C_JAL || Inst.getOpcode() == RISCV::C_J) {211Target = Addr + Inst.getOperand(0).getImm();212return true;213}214215if (Inst.getOpcode() == RISCV::JAL) {216Target = Addr + Inst.getOperand(1).getImm();217return true;218}219220if (Inst.getOpcode() == RISCV::JALR) {221if (auto TargetRegState = getGPRState(Inst.getOperand(1).getReg())) {222Target = *TargetRegState + Inst.getOperand(2).getImm();223return true;224}225226return false;227}228229return false;230}231232bool isTerminator(const MCInst &Inst) const override {233if (MCInstrAnalysis::isTerminator(Inst))234return true;235236switch (Inst.getOpcode()) {237default:238return false;239case RISCV::JAL:240case RISCV::JALR:241return Inst.getOperand(0).getReg() == RISCV::X0;242}243}244245bool isCall(const MCInst &Inst) const override {246if (MCInstrAnalysis::isCall(Inst))247return true;248249switch (Inst.getOpcode()) {250default:251return false;252case RISCV::JAL:253case RISCV::JALR:254return Inst.getOperand(0).getReg() != RISCV::X0;255}256}257258bool isReturn(const MCInst &Inst) const override {259if (MCInstrAnalysis::isReturn(Inst))260return true;261262switch (Inst.getOpcode()) {263default:264return false;265case RISCV::JALR:266return Inst.getOperand(0).getReg() == RISCV::X0 &&267maybeReturnAddress(Inst.getOperand(1).getReg());268case RISCV::C_JR:269return maybeReturnAddress(Inst.getOperand(0).getReg());270}271}272273bool isBranch(const MCInst &Inst) const override {274if (MCInstrAnalysis::isBranch(Inst))275return true;276277return isBranchImpl(Inst);278}279280bool isUnconditionalBranch(const MCInst &Inst) const override {281if (MCInstrAnalysis::isUnconditionalBranch(Inst))282return true;283284return isBranchImpl(Inst);285}286287bool isIndirectBranch(const MCInst &Inst) const override {288if (MCInstrAnalysis::isIndirectBranch(Inst))289return true;290291switch (Inst.getOpcode()) {292default:293return false;294case RISCV::JALR:295return Inst.getOperand(0).getReg() == RISCV::X0 &&296!maybeReturnAddress(Inst.getOperand(1).getReg());297case RISCV::C_JR:298return !maybeReturnAddress(Inst.getOperand(0).getReg());299}300}301302private:303static bool maybeReturnAddress(unsigned Reg) {304// X1 is used for normal returns, X5 for returns from outlined functions.305return Reg == RISCV::X1 || Reg == RISCV::X5;306}307308static bool isBranchImpl(const MCInst &Inst) {309switch (Inst.getOpcode()) {310default:311return false;312case RISCV::JAL:313return Inst.getOperand(0).getReg() == RISCV::X0;314case RISCV::JALR:315return Inst.getOperand(0).getReg() == RISCV::X0 &&316!maybeReturnAddress(Inst.getOperand(1).getReg());317case RISCV::C_JR:318return !maybeReturnAddress(Inst.getOperand(0).getReg());319}320}321};322323} // end anonymous namespace324325static MCInstrAnalysis *createRISCVInstrAnalysis(const MCInstrInfo *Info) {326return new RISCVMCInstrAnalysis(Info);327}328329namespace {330MCStreamer *createRISCVELFStreamer(const Triple &T, MCContext &Context,331std::unique_ptr<MCAsmBackend> &&MAB,332std::unique_ptr<MCObjectWriter> &&MOW,333std::unique_ptr<MCCodeEmitter> &&MCE) {334return createRISCVELFStreamer(Context, std::move(MAB), std::move(MOW),335std::move(MCE));336}337} // end anonymous namespace338339extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMC() {340for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target()}) {341TargetRegistry::RegisterMCAsmInfo(*T, createRISCVMCAsmInfo);342TargetRegistry::RegisterMCObjectFileInfo(*T, createRISCVMCObjectFileInfo);343TargetRegistry::RegisterMCInstrInfo(*T, createRISCVMCInstrInfo);344TargetRegistry::RegisterMCRegInfo(*T, createRISCVMCRegisterInfo);345TargetRegistry::RegisterMCAsmBackend(*T, createRISCVAsmBackend);346TargetRegistry::RegisterMCCodeEmitter(*T, createRISCVMCCodeEmitter);347TargetRegistry::RegisterMCInstPrinter(*T, createRISCVMCInstPrinter);348TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo);349TargetRegistry::RegisterELFStreamer(*T, createRISCVELFStreamer);350TargetRegistry::RegisterObjectTargetStreamer(351*T, createRISCVObjectTargetStreamer);352TargetRegistry::RegisterMCInstrAnalysis(*T, createRISCVInstrAnalysis);353354// Register the asm target streamer.355TargetRegistry::RegisterAsmTargetStreamer(*T, createRISCVAsmTargetStreamer);356// Register the null target streamer.357TargetRegistry::RegisterNullTargetStreamer(*T,358createRISCVNullTargetStreamer);359}360}361362363