203 lines · cpp
1//===-- SparcTargetMachine.cpp - Define TargetMachine for Sparc -----------===//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-exception6//7//===----------------------------------------------------------------------===//8//9//10//===----------------------------------------------------------------------===//11 12#include "SparcTargetMachine.h"13#include "LeonPasses.h"14#include "Sparc.h"15#include "SparcMachineFunctionInfo.h"16#include "SparcTargetObjectFile.h"17#include "TargetInfo/SparcTargetInfo.h"18#include "llvm/CodeGen/Passes.h"19#include "llvm/CodeGen/TargetPassConfig.h"20#include "llvm/MC/TargetRegistry.h"21#include "llvm/Support/Compiler.h"22#include <optional>23using namespace llvm;24 25extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcTarget() {26 // Register the target.27 RegisterTargetMachine<SparcV8TargetMachine> X(getTheSparcTarget());28 RegisterTargetMachine<SparcV9TargetMachine> Y(getTheSparcV9Target());29 RegisterTargetMachine<SparcelTargetMachine> Z(getTheSparcelTarget());30 31 PassRegistry &PR = *PassRegistry::getPassRegistry();32 initializeSparcAsmPrinterPass(PR);33 initializeSparcDAGToDAGISelLegacyPass(PR);34 initializeErrataWorkaroundPass(PR);35}36 37static cl::opt<bool>38 BranchRelaxation("sparc-enable-branch-relax", cl::Hidden, cl::init(true),39 cl::desc("Relax out of range conditional branches"));40 41static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {42 return RM.value_or(Reloc::Static);43}44 45// Code models. Some only make sense for 64-bit code.46//47// SunCC Reloc CodeModel Constraints48// abs32 Static Small text+data+bss linked below 2^32 bytes49// abs44 Static Medium text+data+bss linked below 2^44 bytes50// abs64 Static Large text smaller than 2^31 bytes51// pic13 PIC_ Small GOT < 2^13 bytes52// pic32 PIC_ Medium GOT < 2^32 bytes53//54// All code models require that the text segment is smaller than 2GB.55static CodeModel::Model56getEffectiveSparcCodeModel(std::optional<CodeModel::Model> CM, Reloc::Model RM,57 bool Is64Bit, bool JIT) {58 if (CM) {59 if (*CM == CodeModel::Tiny)60 report_fatal_error("Target does not support the tiny CodeModel", false);61 if (*CM == CodeModel::Kernel)62 report_fatal_error("Target does not support the kernel CodeModel", false);63 return *CM;64 }65 if (Is64Bit) {66 if (JIT)67 return CodeModel::Large;68 return RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium;69 }70 return CodeModel::Small;71}72 73/// Create an ILP32 architecture model74SparcTargetMachine::SparcTargetMachine(const Target &T, const Triple &TT,75 StringRef CPU, StringRef FS,76 const TargetOptions &Options,77 std::optional<Reloc::Model> RM,78 std::optional<CodeModel::Model> CM,79 CodeGenOptLevel OL, bool JIT)80 : CodeGenTargetMachineImpl(81 T, TT.computeDataLayout(), TT, CPU, FS, Options,82 getEffectiveRelocModel(RM),83 getEffectiveSparcCodeModel(CM, getEffectiveRelocModel(RM),84 TT.isSPARC64(), JIT),85 OL),86 TLOF(std::make_unique<SparcELFTargetObjectFile>()) {87 initAsmInfo();88}89 90SparcTargetMachine::~SparcTargetMachine() = default;91 92const SparcSubtarget *93SparcTargetMachine::getSubtargetImpl(const Function &F) const {94 Attribute CPUAttr = F.getFnAttribute("target-cpu");95 Attribute TuneAttr = F.getFnAttribute("tune-cpu");96 Attribute FSAttr = F.getFnAttribute("target-features");97 98 std::string CPU =99 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;100 std::string TuneCPU =101 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;102 std::string FS =103 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;104 105 // FIXME: This is related to the code below to reset the target options,106 // we need to know whether or not the soft float flag is set on the107 // function, so we can enable it as a subtarget feature.108 bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();109 110 if (softFloat)111 FS += FS.empty() ? "+soft-float" : ",+soft-float";112 113 auto &I = SubtargetMap[CPU + FS];114 if (!I) {115 // This needs to be done before we create a new subtarget since any116 // creation will depend on the TM and the code generation flags on the117 // function that reside in TargetOptions.118 resetTargetOptions(F);119 I = std::make_unique<SparcSubtarget>(CPU, TuneCPU, FS, *this);120 }121 return I.get();122}123 124MachineFunctionInfo *SparcTargetMachine::createMachineFunctionInfo(125 BumpPtrAllocator &Allocator, const Function &F,126 const TargetSubtargetInfo *STI) const {127 return SparcMachineFunctionInfo::create<SparcMachineFunctionInfo>(Allocator,128 F, STI);129}130 131namespace {132/// Sparc Code Generator Pass Configuration Options.133class SparcPassConfig : public TargetPassConfig {134public:135 SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM)136 : TargetPassConfig(TM, PM) {}137 138 SparcTargetMachine &getSparcTargetMachine() const {139 return getTM<SparcTargetMachine>();140 }141 142 void addIRPasses() override;143 bool addInstSelector() override;144 void addPreEmitPass() override;145};146} // namespace147 148TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) {149 return new SparcPassConfig(*this, PM);150}151 152void SparcPassConfig::addIRPasses() {153 addPass(createAtomicExpandLegacyPass());154 155 TargetPassConfig::addIRPasses();156}157 158bool SparcPassConfig::addInstSelector() {159 addPass(createSparcISelDag(getSparcTargetMachine()));160 return false;161}162 163void SparcPassConfig::addPreEmitPass(){164 if (BranchRelaxation)165 addPass(&BranchRelaxationPassID);166 167 addPass(createSparcDelaySlotFillerPass());168 addPass(new InsertNOPLoad());169 addPass(new DetectRoundChange());170 addPass(new FixAllFDIVSQRT());171 addPass(new ErrataWorkaround());172}173 174void SparcV8TargetMachine::anchor() { }175 176SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT,177 StringRef CPU, StringRef FS,178 const TargetOptions &Options,179 std::optional<Reloc::Model> RM,180 std::optional<CodeModel::Model> CM,181 CodeGenOptLevel OL, bool JIT)182 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT) {}183 184void SparcV9TargetMachine::anchor() { }185 186SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT,187 StringRef CPU, StringRef FS,188 const TargetOptions &Options,189 std::optional<Reloc::Model> RM,190 std::optional<CodeModel::Model> CM,191 CodeGenOptLevel OL, bool JIT)192 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT) {}193 194void SparcelTargetMachine::anchor() {}195 196SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT,197 StringRef CPU, StringRef FS,198 const TargetOptions &Options,199 std::optional<Reloc::Model> RM,200 std::optional<CodeModel::Model> CM,201 CodeGenOptLevel OL, bool JIT)202 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT) {}203