1e8d8bef9SDimitry Andric //===--- CSKYTargetMachine.cpp - Define TargetMachine for CSKY ------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric // 9e8d8bef9SDimitry Andric // Implements the info about CSKY target spec. 10e8d8bef9SDimitry Andric // 11e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 12e8d8bef9SDimitry Andric 13e8d8bef9SDimitry Andric #include "CSKYTargetMachine.h" 14349cc55cSDimitry Andric #include "CSKY.h" 15bdd1243dSDimitry Andric #include "CSKYMachineFunctionInfo.h" 16349cc55cSDimitry Andric #include "CSKYSubtarget.h" 1781ad6265SDimitry Andric #include "CSKYTargetObjectFile.h" 18e8d8bef9SDimitry Andric #include "TargetInfo/CSKYTargetInfo.h" 1981ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 20e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 21e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 22349cc55cSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 23349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 24bdd1243dSDimitry Andric #include <optional> 25e8d8bef9SDimitry Andric 26e8d8bef9SDimitry Andric using namespace llvm; 27e8d8bef9SDimitry Andric 28e8d8bef9SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYTarget() { 29e8d8bef9SDimitry Andric RegisterTargetMachine<CSKYTargetMachine> X(getTheCSKYTarget()); 3004eeddc0SDimitry Andric 3104eeddc0SDimitry Andric PassRegistry *Registry = PassRegistry::getPassRegistry(); 3204eeddc0SDimitry Andric initializeCSKYConstantIslandsPass(*Registry); 33*0fca6ea1SDimitry Andric initializeCSKYDAGToDAGISelLegacyPass(*Registry); 34e8d8bef9SDimitry Andric } 35e8d8bef9SDimitry Andric 36e8d8bef9SDimitry Andric static std::string computeDataLayout(const Triple &TT) { 37e8d8bef9SDimitry Andric std::string Ret; 38e8d8bef9SDimitry Andric 39e8d8bef9SDimitry Andric // Only support little endian for now. 40e8d8bef9SDimitry Andric // TODO: Add support for big endian. 41e8d8bef9SDimitry Andric Ret += "e"; 42e8d8bef9SDimitry Andric 43e8d8bef9SDimitry Andric // CSKY is always 32-bit target with the CSKYv2 ABI as prefer now. 44e8d8bef9SDimitry Andric // It's a 4-byte aligned stack with ELF mangling only. 45e8d8bef9SDimitry Andric Ret += "-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32" 46e8d8bef9SDimitry Andric "-v128:32:32-a:0:32-Fi32-n32"; 47e8d8bef9SDimitry Andric 48e8d8bef9SDimitry Andric return Ret; 49e8d8bef9SDimitry Andric } 50e8d8bef9SDimitry Andric 51e8d8bef9SDimitry Andric CSKYTargetMachine::CSKYTargetMachine(const Target &T, const Triple &TT, 52e8d8bef9SDimitry Andric StringRef CPU, StringRef FS, 53e8d8bef9SDimitry Andric const TargetOptions &Options, 54bdd1243dSDimitry Andric std::optional<Reloc::Model> RM, 55bdd1243dSDimitry Andric std::optional<CodeModel::Model> CM, 565f757f3fSDimitry Andric CodeGenOptLevel OL, bool JIT) 57e8d8bef9SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, 5881ad6265SDimitry Andric RM.value_or(Reloc::Static), 59e8d8bef9SDimitry Andric getEffectiveCodeModel(CM, CodeModel::Small), OL), 6081ad6265SDimitry Andric TLOF(std::make_unique<CSKYELFTargetObjectFile>()) { 61e8d8bef9SDimitry Andric initAsmInfo(); 62e8d8bef9SDimitry Andric } 63e8d8bef9SDimitry Andric 64349cc55cSDimitry Andric const CSKYSubtarget * 65349cc55cSDimitry Andric CSKYTargetMachine::getSubtargetImpl(const Function &F) const { 66349cc55cSDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 67349cc55cSDimitry Andric Attribute TuneAttr = F.getFnAttribute("tune-cpu"); 68349cc55cSDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 69349cc55cSDimitry Andric 70349cc55cSDimitry Andric std::string CPU = 71349cc55cSDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 72349cc55cSDimitry Andric std::string TuneCPU = 73349cc55cSDimitry Andric TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; 74349cc55cSDimitry Andric std::string FS = 75349cc55cSDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 76349cc55cSDimitry Andric 77349cc55cSDimitry Andric std::string Key = CPU + TuneCPU + FS; 78349cc55cSDimitry Andric auto &I = SubtargetMap[Key]; 79349cc55cSDimitry Andric if (!I) { 80349cc55cSDimitry Andric // This needs to be done before we create a new subtarget since any 81349cc55cSDimitry Andric // creation will depend on the TM and the code generation flags on the 82349cc55cSDimitry Andric // function that reside in TargetOptions. 83349cc55cSDimitry Andric resetTargetOptions(F); 84349cc55cSDimitry Andric I = std::make_unique<CSKYSubtarget>(TargetTriple, CPU, TuneCPU, FS, *this); 85349cc55cSDimitry Andric if (I->useHardFloat() && !I->hasAnyFloatExt()) 86349cc55cSDimitry Andric errs() << "Hard-float can't be used with current CPU," 87349cc55cSDimitry Andric " set to Soft-float\n"; 88349cc55cSDimitry Andric } 89349cc55cSDimitry Andric return I.get(); 90349cc55cSDimitry Andric } 91349cc55cSDimitry Andric 92bdd1243dSDimitry Andric MachineFunctionInfo *CSKYTargetMachine::createMachineFunctionInfo( 93bdd1243dSDimitry Andric BumpPtrAllocator &Allocator, const Function &F, 94bdd1243dSDimitry Andric const TargetSubtargetInfo *STI) const { 95bdd1243dSDimitry Andric return CSKYMachineFunctionInfo::create<CSKYMachineFunctionInfo>(Allocator, F, 96bdd1243dSDimitry Andric STI); 97bdd1243dSDimitry Andric } 98bdd1243dSDimitry Andric 99e8d8bef9SDimitry Andric namespace { 100e8d8bef9SDimitry Andric class CSKYPassConfig : public TargetPassConfig { 101e8d8bef9SDimitry Andric public: 102e8d8bef9SDimitry Andric CSKYPassConfig(CSKYTargetMachine &TM, PassManagerBase &PM) 103e8d8bef9SDimitry Andric : TargetPassConfig(TM, PM) {} 104e8d8bef9SDimitry Andric 105e8d8bef9SDimitry Andric CSKYTargetMachine &getCSKYTargetMachine() const { 106e8d8bef9SDimitry Andric return getTM<CSKYTargetMachine>(); 107e8d8bef9SDimitry Andric } 108349cc55cSDimitry Andric 10981ad6265SDimitry Andric void addIRPasses() override; 110349cc55cSDimitry Andric bool addInstSelector() override; 11104eeddc0SDimitry Andric void addPreEmitPass() override; 112e8d8bef9SDimitry Andric }; 113e8d8bef9SDimitry Andric 114e8d8bef9SDimitry Andric } // namespace 115e8d8bef9SDimitry Andric 116e8d8bef9SDimitry Andric TargetPassConfig *CSKYTargetMachine::createPassConfig(PassManagerBase &PM) { 117e8d8bef9SDimitry Andric return new CSKYPassConfig(*this, PM); 118e8d8bef9SDimitry Andric } 119349cc55cSDimitry Andric 12081ad6265SDimitry Andric void CSKYPassConfig::addIRPasses() { 121*0fca6ea1SDimitry Andric addPass(createAtomicExpandLegacyPass()); 12281ad6265SDimitry Andric TargetPassConfig::addIRPasses(); 12381ad6265SDimitry Andric } 12481ad6265SDimitry Andric 125349cc55cSDimitry Andric bool CSKYPassConfig::addInstSelector() { 126bdd1243dSDimitry Andric addPass(createCSKYISelDag(getCSKYTargetMachine(), getOptLevel())); 127349cc55cSDimitry Andric 128349cc55cSDimitry Andric return false; 129349cc55cSDimitry Andric } 13004eeddc0SDimitry Andric 13104eeddc0SDimitry Andric void CSKYPassConfig::addPreEmitPass() { 13204eeddc0SDimitry Andric addPass(createCSKYConstantIslandPass()); 13304eeddc0SDimitry Andric } 134