1*81ad6265SDimitry Andric //===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric // 9*81ad6265SDimitry Andric // Implements the info about LoongArch target spec. 10*81ad6265SDimitry Andric // 11*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 12*81ad6265SDimitry Andric 13*81ad6265SDimitry Andric #include "LoongArchTargetMachine.h" 14*81ad6265SDimitry Andric #include "LoongArch.h" 15*81ad6265SDimitry Andric #include "MCTargetDesc/LoongArchBaseInfo.h" 16*81ad6265SDimitry Andric #include "TargetInfo/LoongArchTargetInfo.h" 17*81ad6265SDimitry Andric #include "llvm/CodeGen/Passes.h" 18*81ad6265SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 19*81ad6265SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 20*81ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 21*81ad6265SDimitry Andric 22*81ad6265SDimitry Andric using namespace llvm; 23*81ad6265SDimitry Andric 24*81ad6265SDimitry Andric #define DEBUG_TYPE "loongarch" 25*81ad6265SDimitry Andric 26*81ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() { 27*81ad6265SDimitry Andric // Register the target. 28*81ad6265SDimitry Andric RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target()); 29*81ad6265SDimitry Andric RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target()); 30*81ad6265SDimitry Andric } 31*81ad6265SDimitry Andric 32*81ad6265SDimitry Andric static std::string computeDataLayout(const Triple &TT) { 33*81ad6265SDimitry Andric if (TT.isArch64Bit()) 34*81ad6265SDimitry Andric return "e-m:e-p:64:64-i64:64-i128:128-n64-S128"; 35*81ad6265SDimitry Andric assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported"); 36*81ad6265SDimitry Andric return "e-m:e-p:32:32-i64:64-n32-S128"; 37*81ad6265SDimitry Andric } 38*81ad6265SDimitry Andric 39*81ad6265SDimitry Andric static Reloc::Model getEffectiveRelocModel(const Triple &TT, 40*81ad6265SDimitry Andric Optional<Reloc::Model> RM) { 41*81ad6265SDimitry Andric if (!RM.hasValue()) 42*81ad6265SDimitry Andric return Reloc::Static; 43*81ad6265SDimitry Andric return *RM; 44*81ad6265SDimitry Andric } 45*81ad6265SDimitry Andric 46*81ad6265SDimitry Andric LoongArchTargetMachine::LoongArchTargetMachine( 47*81ad6265SDimitry Andric const Target &T, const Triple &TT, StringRef CPU, StringRef FS, 48*81ad6265SDimitry Andric const TargetOptions &Options, Optional<Reloc::Model> RM, 49*81ad6265SDimitry Andric Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT) 50*81ad6265SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, 51*81ad6265SDimitry Andric getEffectiveRelocModel(TT, RM), 52*81ad6265SDimitry Andric getEffectiveCodeModel(CM, CodeModel::Small), OL), 53*81ad6265SDimitry Andric TLOF(std::make_unique<TargetLoweringObjectFileELF>()) { 54*81ad6265SDimitry Andric initAsmInfo(); 55*81ad6265SDimitry Andric } 56*81ad6265SDimitry Andric 57*81ad6265SDimitry Andric LoongArchTargetMachine::~LoongArchTargetMachine() = default; 58*81ad6265SDimitry Andric 59*81ad6265SDimitry Andric const LoongArchSubtarget * 60*81ad6265SDimitry Andric LoongArchTargetMachine::getSubtargetImpl(const Function &F) const { 61*81ad6265SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 62*81ad6265SDimitry Andric Attribute TuneAttr = F.getFnAttribute("tune-cpu"); 63*81ad6265SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 64*81ad6265SDimitry Andric 65*81ad6265SDimitry Andric std::string CPU = 66*81ad6265SDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 67*81ad6265SDimitry Andric std::string TuneCPU = 68*81ad6265SDimitry Andric TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; 69*81ad6265SDimitry Andric std::string FS = 70*81ad6265SDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 71*81ad6265SDimitry Andric 72*81ad6265SDimitry Andric std::string Key = CPU + TuneCPU + FS; 73*81ad6265SDimitry Andric auto &I = SubtargetMap[Key]; 74*81ad6265SDimitry Andric if (!I) { 75*81ad6265SDimitry Andric // This needs to be done before we create a new subtarget since any 76*81ad6265SDimitry Andric // creation will depend on the TM and the code generation flags on the 77*81ad6265SDimitry Andric // function that reside in TargetOptions. 78*81ad6265SDimitry Andric resetTargetOptions(F); 79*81ad6265SDimitry Andric auto ABIName = Options.MCOptions.getABIName(); 80*81ad6265SDimitry Andric if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>( 81*81ad6265SDimitry Andric F.getParent()->getModuleFlag("target-abi"))) { 82*81ad6265SDimitry Andric auto TargetABI = LoongArchABI::getTargetABI(ABIName); 83*81ad6265SDimitry Andric if (TargetABI != LoongArchABI::ABI_Unknown && 84*81ad6265SDimitry Andric ModuleTargetABI->getString() != ABIName) { 85*81ad6265SDimitry Andric report_fatal_error("-target-abi option != target-abi module flag"); 86*81ad6265SDimitry Andric } 87*81ad6265SDimitry Andric ABIName = ModuleTargetABI->getString(); 88*81ad6265SDimitry Andric } 89*81ad6265SDimitry Andric I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS, 90*81ad6265SDimitry Andric ABIName, *this); 91*81ad6265SDimitry Andric } 92*81ad6265SDimitry Andric return I.get(); 93*81ad6265SDimitry Andric } 94*81ad6265SDimitry Andric 95*81ad6265SDimitry Andric namespace { 96*81ad6265SDimitry Andric class LoongArchPassConfig : public TargetPassConfig { 97*81ad6265SDimitry Andric public: 98*81ad6265SDimitry Andric LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM) 99*81ad6265SDimitry Andric : TargetPassConfig(TM, PM) {} 100*81ad6265SDimitry Andric 101*81ad6265SDimitry Andric LoongArchTargetMachine &getLoongArchTargetMachine() const { 102*81ad6265SDimitry Andric return getTM<LoongArchTargetMachine>(); 103*81ad6265SDimitry Andric } 104*81ad6265SDimitry Andric 105*81ad6265SDimitry Andric bool addInstSelector() override; 106*81ad6265SDimitry Andric }; 107*81ad6265SDimitry Andric } // namespace 108*81ad6265SDimitry Andric 109*81ad6265SDimitry Andric TargetPassConfig * 110*81ad6265SDimitry Andric LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { 111*81ad6265SDimitry Andric return new LoongArchPassConfig(*this, PM); 112*81ad6265SDimitry Andric } 113*81ad6265SDimitry Andric 114*81ad6265SDimitry Andric bool LoongArchPassConfig::addInstSelector() { 115*81ad6265SDimitry Andric addPass(createLoongArchISelDag(getLoongArchTargetMachine())); 116*81ad6265SDimitry Andric 117*81ad6265SDimitry Andric return false; 118*81ad6265SDimitry Andric } 119