1 //===-- LoongArchMCTargetDesc.cpp - LoongArch 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 LoongArch specific target descriptions. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LoongArchMCTargetDesc.h" 14 #include "LoongArchELFStreamer.h" 15 #include "LoongArchInstPrinter.h" 16 #include "LoongArchMCAsmInfo.h" 17 #include "TargetInfo/LoongArchTargetInfo.h" 18 #include "llvm/MC/MCAsmBackend.h" 19 #include "llvm/MC/MCAsmInfo.h" 20 #include "llvm/MC/MCCodeEmitter.h" 21 #include "llvm/MC/MCDwarf.h" 22 #include "llvm/MC/MCInstrAnalysis.h" 23 #include "llvm/MC/MCInstrInfo.h" 24 #include "llvm/MC/MCObjectWriter.h" 25 #include "llvm/MC/MCRegisterInfo.h" 26 #include "llvm/MC/MCSubtargetInfo.h" 27 #include "llvm/MC/TargetRegistry.h" 28 #include "llvm/Support/Compiler.h" 29 30 #define GET_INSTRINFO_MC_DESC 31 #define ENABLE_INSTR_PREDICATE_VERIFIER 32 #include "LoongArchGenInstrInfo.inc" 33 34 #define GET_REGINFO_MC_DESC 35 #include "LoongArchGenRegisterInfo.inc" 36 37 #define GET_SUBTARGETINFO_MC_DESC 38 #include "LoongArchGenSubtargetInfo.inc" 39 40 using namespace llvm; 41 42 static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) { 43 MCRegisterInfo *X = new MCRegisterInfo(); 44 InitLoongArchMCRegisterInfo(X, LoongArch::R1); 45 return X; 46 } 47 48 static MCInstrInfo *createLoongArchMCInstrInfo() { 49 MCInstrInfo *X = new MCInstrInfo(); 50 InitLoongArchMCInstrInfo(X); 51 return X; 52 } 53 54 static MCSubtargetInfo * 55 createLoongArchMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { 56 if (CPU.empty() || CPU == "generic") 57 CPU = TT.isArch64Bit() ? "generic-la64" : "generic-la32"; 58 return createLoongArchMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS); 59 } 60 61 static MCAsmInfo *createLoongArchMCAsmInfo(const MCRegisterInfo &MRI, 62 const Triple &TT, 63 const MCTargetOptions &Options) { 64 MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT); 65 66 // Initial state of the frame pointer is sp(r3). 67 unsigned SP = MRI.getDwarfRegNum(LoongArch::R3, true); 68 MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0); 69 MAI->addInitialFrameState(Inst); 70 71 return MAI; 72 } 73 74 static MCInstPrinter *createLoongArchMCInstPrinter(const Triple &T, 75 unsigned SyntaxVariant, 76 const MCAsmInfo &MAI, 77 const MCInstrInfo &MII, 78 const MCRegisterInfo &MRI) { 79 return new LoongArchInstPrinter(MAI, MII, MRI); 80 } 81 82 static MCTargetStreamer * 83 createLoongArchObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { 84 return STI.getTargetTriple().isOSBinFormatELF() 85 ? new LoongArchTargetELFStreamer(S, STI) 86 : nullptr; 87 } 88 89 static MCTargetStreamer * 90 createLoongArchAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, 91 MCInstPrinter *InstPrint) { 92 return new LoongArchTargetAsmStreamer(S, OS); 93 } 94 95 namespace { 96 97 class LoongArchMCInstrAnalysis : public MCInstrAnalysis { 98 public: 99 explicit LoongArchMCInstrAnalysis(const MCInstrInfo *Info) 100 : MCInstrAnalysis(Info) {} 101 102 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, 103 uint64_t &Target) const override { 104 unsigned NumOps = Inst.getNumOperands(); 105 if ((isBranch(Inst) && !isIndirectBranch(Inst)) || 106 Inst.getOpcode() == LoongArch::BL) { 107 Target = Addr + Inst.getOperand(NumOps - 1).getImm(); 108 return true; 109 } 110 111 return false; 112 } 113 114 bool isTerminator(const MCInst &Inst) const override { 115 if (MCInstrAnalysis::isTerminator(Inst)) 116 return true; 117 118 switch (Inst.getOpcode()) { 119 default: 120 return false; 121 case LoongArch::JIRL: 122 return Inst.getOperand(0).getReg() == LoongArch::R0; 123 } 124 } 125 126 bool isCall(const MCInst &Inst) const override { 127 if (MCInstrAnalysis::isCall(Inst)) 128 return true; 129 130 switch (Inst.getOpcode()) { 131 default: 132 return false; 133 case LoongArch::JIRL: 134 return Inst.getOperand(0).getReg() != LoongArch::R0; 135 } 136 } 137 138 bool isReturn(const MCInst &Inst) const override { 139 if (MCInstrAnalysis::isReturn(Inst)) 140 return true; 141 142 switch (Inst.getOpcode()) { 143 default: 144 return false; 145 case LoongArch::JIRL: 146 return Inst.getOperand(0).getReg() == LoongArch::R0 && 147 Inst.getOperand(1).getReg() == LoongArch::R1; 148 } 149 } 150 151 bool isBranch(const MCInst &Inst) const override { 152 if (MCInstrAnalysis::isBranch(Inst)) 153 return true; 154 155 switch (Inst.getOpcode()) { 156 default: 157 return false; 158 case LoongArch::JIRL: 159 return Inst.getOperand(0).getReg() == LoongArch::R0 && 160 Inst.getOperand(1).getReg() != LoongArch::R1; 161 } 162 } 163 164 bool isUnconditionalBranch(const MCInst &Inst) const override { 165 if (MCInstrAnalysis::isUnconditionalBranch(Inst)) 166 return true; 167 168 switch (Inst.getOpcode()) { 169 default: 170 return false; 171 case LoongArch::JIRL: 172 return Inst.getOperand(0).getReg() == LoongArch::R0 && 173 Inst.getOperand(1).getReg() != LoongArch::R1; 174 } 175 } 176 177 bool isIndirectBranch(const MCInst &Inst) const override { 178 if (MCInstrAnalysis::isIndirectBranch(Inst)) 179 return true; 180 181 switch (Inst.getOpcode()) { 182 default: 183 return false; 184 case LoongArch::JIRL: 185 return Inst.getOperand(0).getReg() == LoongArch::R0 && 186 Inst.getOperand(1).getReg() != LoongArch::R1; 187 } 188 } 189 }; 190 191 } // end namespace 192 193 static MCInstrAnalysis *createLoongArchInstrAnalysis(const MCInstrInfo *Info) { 194 return new LoongArchMCInstrAnalysis(Info); 195 } 196 197 namespace { 198 MCStreamer *createLoongArchELFStreamer(const Triple &T, MCContext &Context, 199 std::unique_ptr<MCAsmBackend> &&MAB, 200 std::unique_ptr<MCObjectWriter> &&MOW, 201 std::unique_ptr<MCCodeEmitter> &&MCE) { 202 return createLoongArchELFStreamer(Context, std::move(MAB), std::move(MOW), 203 std::move(MCE)); 204 } 205 } // end namespace 206 207 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() { 208 for (Target *T : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) { 209 TargetRegistry::RegisterMCRegInfo(*T, createLoongArchMCRegisterInfo); 210 TargetRegistry::RegisterMCInstrInfo(*T, createLoongArchMCInstrInfo); 211 TargetRegistry::RegisterMCSubtargetInfo(*T, createLoongArchMCSubtargetInfo); 212 TargetRegistry::RegisterMCAsmInfo(*T, createLoongArchMCAsmInfo); 213 TargetRegistry::RegisterMCCodeEmitter(*T, createLoongArchMCCodeEmitter); 214 TargetRegistry::RegisterMCAsmBackend(*T, createLoongArchAsmBackend); 215 TargetRegistry::RegisterMCInstPrinter(*T, createLoongArchMCInstPrinter); 216 TargetRegistry::RegisterMCInstrAnalysis(*T, createLoongArchInstrAnalysis); 217 TargetRegistry::RegisterELFStreamer(*T, createLoongArchELFStreamer); 218 TargetRegistry::RegisterObjectTargetStreamer( 219 *T, createLoongArchObjectTargetStreamer); 220 TargetRegistry::RegisterAsmTargetStreamer(*T, 221 createLoongArchAsmTargetStreamer); 222 } 223 } 224