1444c6d26SLu Weining //===-- LoongArchTargetMachine.cpp - Define TargetMachine for LoongArch ---===//
2444c6d26SLu Weining //
3444c6d26SLu Weining // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4444c6d26SLu Weining // See https://llvm.org/LICENSE.txt for license information.
5444c6d26SLu Weining // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6444c6d26SLu Weining //
7444c6d26SLu Weining //===----------------------------------------------------------------------===//
8444c6d26SLu Weining //
9444c6d26SLu Weining // Implements the info about LoongArch target spec.
10444c6d26SLu Weining //
11444c6d26SLu Weining //===----------------------------------------------------------------------===//
12444c6d26SLu Weining 
13444c6d26SLu Weining #include "LoongArchTargetMachine.h"
1433388ae8SLu Weining #include "LoongArch.h"
1533388ae8SLu Weining #include "MCTargetDesc/LoongArchBaseInfo.h"
16444c6d26SLu Weining #include "TargetInfo/LoongArchTargetInfo.h"
1733388ae8SLu Weining #include "llvm/CodeGen/Passes.h"
1833388ae8SLu Weining #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
1933388ae8SLu Weining #include "llvm/CodeGen/TargetPassConfig.h"
20444c6d26SLu Weining #include "llvm/MC/TargetRegistry.h"
21444c6d26SLu Weining 
22444c6d26SLu Weining using namespace llvm;
23444c6d26SLu Weining 
24444c6d26SLu Weining #define DEBUG_TYPE "loongarch"
25444c6d26SLu Weining 
LLVMInitializeLoongArchTarget()26444c6d26SLu Weining extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {
27444c6d26SLu Weining   // Register the target.
28444c6d26SLu Weining   RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target());
29444c6d26SLu Weining   RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
30444c6d26SLu Weining }
31444c6d26SLu Weining 
computeDataLayout(const Triple & TT)32444c6d26SLu Weining static std::string computeDataLayout(const Triple &TT) {
33a1c67439Swanglei   if (TT.isArch64Bit())
34a1c67439Swanglei     return "e-m:e-p:64:64-i64:64-i128:128-n64-S128";
35a1c67439Swanglei   assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported");
36a1c67439Swanglei   return "e-m:e-p:32:32-i64:64-n32-S128";
37444c6d26SLu Weining }
38444c6d26SLu Weining 
getEffectiveRelocModel(const Triple & TT,Optional<Reloc::Model> RM)39444c6d26SLu Weining static Reloc::Model getEffectiveRelocModel(const Triple &TT,
40444c6d26SLu Weining                                            Optional<Reloc::Model> RM) {
413c849d0aSFangrui Song   return RM.value_or(Reloc::Static);
42444c6d26SLu Weining }
43444c6d26SLu Weining 
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)44444c6d26SLu Weining LoongArchTargetMachine::LoongArchTargetMachine(
45444c6d26SLu Weining     const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
46444c6d26SLu Weining     const TargetOptions &Options, Optional<Reloc::Model> RM,
47444c6d26SLu Weining     Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
48444c6d26SLu Weining     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
49444c6d26SLu Weining                         getEffectiveRelocModel(TT, RM),
5033388ae8SLu Weining                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
5133388ae8SLu Weining       TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
52444c6d26SLu Weining   initAsmInfo();
53444c6d26SLu Weining }
54444c6d26SLu Weining 
55444c6d26SLu Weining LoongArchTargetMachine::~LoongArchTargetMachine() = default;
5633388ae8SLu Weining 
5733388ae8SLu Weining const LoongArchSubtarget *
getSubtargetImpl(const Function & F) const5833388ae8SLu Weining LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {
5933388ae8SLu Weining   Attribute CPUAttr = F.getFnAttribute("target-cpu");
6033388ae8SLu Weining   Attribute TuneAttr = F.getFnAttribute("tune-cpu");
6133388ae8SLu Weining   Attribute FSAttr = F.getFnAttribute("target-features");
6233388ae8SLu Weining 
6333388ae8SLu Weining   std::string CPU =
6433388ae8SLu Weining       CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
6533388ae8SLu Weining   std::string TuneCPU =
6633388ae8SLu Weining       TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
6733388ae8SLu Weining   std::string FS =
6833388ae8SLu Weining       FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
6933388ae8SLu Weining 
7033388ae8SLu Weining   std::string Key = CPU + TuneCPU + FS;
7133388ae8SLu Weining   auto &I = SubtargetMap[Key];
7233388ae8SLu Weining   if (!I) {
7333388ae8SLu Weining     // This needs to be done before we create a new subtarget since any
7433388ae8SLu Weining     // creation will depend on the TM and the code generation flags on the
7533388ae8SLu Weining     // function that reside in TargetOptions.
7633388ae8SLu Weining     resetTargetOptions(F);
7733388ae8SLu Weining     auto ABIName = Options.MCOptions.getABIName();
7833388ae8SLu Weining     if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(
7933388ae8SLu Weining             F.getParent()->getModuleFlag("target-abi"))) {
8033388ae8SLu Weining       auto TargetABI = LoongArchABI::getTargetABI(ABIName);
8133388ae8SLu Weining       if (TargetABI != LoongArchABI::ABI_Unknown &&
8233388ae8SLu Weining           ModuleTargetABI->getString() != ABIName) {
8333388ae8SLu Weining         report_fatal_error("-target-abi option != target-abi module flag");
8433388ae8SLu Weining       }
8533388ae8SLu Weining       ABIName = ModuleTargetABI->getString();
8633388ae8SLu Weining     }
8733388ae8SLu Weining     I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS,
8833388ae8SLu Weining                                              ABIName, *this);
8933388ae8SLu Weining   }
9033388ae8SLu Weining   return I.get();
9133388ae8SLu Weining }
9233388ae8SLu Weining 
9333388ae8SLu Weining namespace {
9433388ae8SLu Weining class LoongArchPassConfig : public TargetPassConfig {
9533388ae8SLu Weining public:
LoongArchPassConfig(LoongArchTargetMachine & TM,PassManagerBase & PM)9633388ae8SLu Weining   LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)
9733388ae8SLu Weining       : TargetPassConfig(TM, PM) {}
9833388ae8SLu Weining 
getLoongArchTargetMachine() const9933388ae8SLu Weining   LoongArchTargetMachine &getLoongArchTargetMachine() const {
10033388ae8SLu Weining     return getTM<LoongArchTargetMachine>();
10133388ae8SLu Weining   }
10233388ae8SLu Weining 
10347f3dc6dSgonglingqin   void addIRPasses() override;
10433388ae8SLu Weining   bool addInstSelector() override;
10533388ae8SLu Weining };
106*904a87acSWeining Lu } // end namespace
10733388ae8SLu Weining 
10833388ae8SLu Weining TargetPassConfig *
createPassConfig(PassManagerBase & PM)10933388ae8SLu Weining LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {
11033388ae8SLu Weining   return new LoongArchPassConfig(*this, PM);
11133388ae8SLu Weining }
11233388ae8SLu Weining 
addIRPasses()11347f3dc6dSgonglingqin void LoongArchPassConfig::addIRPasses() {
11447f3dc6dSgonglingqin   addPass(createAtomicExpandPass());
11547f3dc6dSgonglingqin 
11647f3dc6dSgonglingqin   TargetPassConfig::addIRPasses();
11747f3dc6dSgonglingqin }
11847f3dc6dSgonglingqin 
addInstSelector()11933388ae8SLu Weining bool LoongArchPassConfig::addInstSelector() {
12033388ae8SLu Weining   addPass(createLoongArchISelDag(getLoongArchTargetMachine()));
12133388ae8SLu Weining 
12233388ae8SLu Weining   return false;
12333388ae8SLu Weining }
124