|  | //===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // Implements the info about LoongArch target spec. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "LoongArchTargetMachine.h" | 
|  | #include "LoongArch.h" | 
|  | #include "MCTargetDesc/LoongArchBaseInfo.h" | 
|  | #include "TargetInfo/LoongArchTargetInfo.h" | 
|  | #include "llvm/CodeGen/Passes.h" | 
|  | #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" | 
|  | #include "llvm/CodeGen/TargetPassConfig.h" | 
|  | #include "llvm/MC/TargetRegistry.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | #define DEBUG_TYPE "loongarch" | 
|  |  | 
|  | extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() { | 
|  | // Register the target. | 
|  | RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target()); | 
|  | RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target()); | 
|  | } | 
|  |  | 
|  | static std::string computeDataLayout(const Triple &TT) { | 
|  | if (TT.isArch64Bit()) | 
|  | return "e-m:e-p:64:64-i64:64-i128:128-n64-S128"; | 
|  | assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported"); | 
|  | return "e-m:e-p:32:32-i64:64-n32-S128"; | 
|  | } | 
|  |  | 
|  | static Reloc::Model getEffectiveRelocModel(const Triple &TT, | 
|  | Optional<Reloc::Model> RM) { | 
|  | return RM.value_or(Reloc::Static); | 
|  | } | 
|  |  | 
|  | LoongArchTargetMachine::LoongArchTargetMachine( | 
|  | const Target &T, const Triple &TT, StringRef CPU, StringRef FS, | 
|  | const TargetOptions &Options, Optional<Reloc::Model> RM, | 
|  | Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT) | 
|  | : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, | 
|  | getEffectiveRelocModel(TT, RM), | 
|  | getEffectiveCodeModel(CM, CodeModel::Small), OL), | 
|  | TLOF(std::make_unique<TargetLoweringObjectFileELF>()) { | 
|  | initAsmInfo(); | 
|  | } | 
|  |  | 
|  | LoongArchTargetMachine::~LoongArchTargetMachine() = default; | 
|  |  | 
|  | const LoongArchSubtarget * | 
|  | LoongArchTargetMachine::getSubtargetImpl(const Function &F) const { | 
|  | Attribute CPUAttr = F.getFnAttribute("target-cpu"); | 
|  | Attribute TuneAttr = F.getFnAttribute("tune-cpu"); | 
|  | Attribute FSAttr = F.getFnAttribute("target-features"); | 
|  |  | 
|  | std::string CPU = | 
|  | CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; | 
|  | std::string TuneCPU = | 
|  | TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; | 
|  | std::string FS = | 
|  | FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; | 
|  |  | 
|  | std::string Key = CPU + TuneCPU + FS; | 
|  | auto &I = SubtargetMap[Key]; | 
|  | if (!I) { | 
|  | // This needs to be done before we create a new subtarget since any | 
|  | // creation will depend on the TM and the code generation flags on the | 
|  | // function that reside in TargetOptions. | 
|  | resetTargetOptions(F); | 
|  | auto ABIName = Options.MCOptions.getABIName(); | 
|  | if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>( | 
|  | F.getParent()->getModuleFlag("target-abi"))) { | 
|  | auto TargetABI = LoongArchABI::getTargetABI(ABIName); | 
|  | if (TargetABI != LoongArchABI::ABI_Unknown && | 
|  | ModuleTargetABI->getString() != ABIName) { | 
|  | report_fatal_error("-target-abi option != target-abi module flag"); | 
|  | } | 
|  | ABIName = ModuleTargetABI->getString(); | 
|  | } | 
|  | I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS, | 
|  | ABIName, *this); | 
|  | } | 
|  | return I.get(); | 
|  | } | 
|  |  | 
|  | namespace { | 
|  | class LoongArchPassConfig : public TargetPassConfig { | 
|  | public: | 
|  | LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM) | 
|  | : TargetPassConfig(TM, PM) {} | 
|  |  | 
|  | LoongArchTargetMachine &getLoongArchTargetMachine() const { | 
|  | return getTM<LoongArchTargetMachine>(); | 
|  | } | 
|  |  | 
|  | void addIRPasses() override; | 
|  | bool addInstSelector() override; | 
|  | }; | 
|  | } // end namespace | 
|  |  | 
|  | TargetPassConfig * | 
|  | LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) { | 
|  | return new LoongArchPassConfig(*this, PM); | 
|  | } | 
|  |  | 
|  | void LoongArchPassConfig::addIRPasses() { | 
|  | addPass(createAtomicExpandPass()); | 
|  |  | 
|  | TargetPassConfig::addIRPasses(); | 
|  | } | 
|  |  | 
|  | bool LoongArchPassConfig::addInstSelector() { | 
|  | addPass(createLoongArchISelDag(getLoongArchTargetMachine())); | 
|  |  | 
|  | return false; | 
|  | } |