brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.4 KiB · d917ef4 Raw
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