Path: blob/main/contrib/llvm-project/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
35266 views
//===-- SparcTargetMachine.cpp - Define TargetMachine for Sparc -----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8//9//===----------------------------------------------------------------------===//1011#include "SparcTargetMachine.h"12#include "LeonPasses.h"13#include "Sparc.h"14#include "SparcMachineFunctionInfo.h"15#include "SparcTargetObjectFile.h"16#include "TargetInfo/SparcTargetInfo.h"17#include "llvm/CodeGen/Passes.h"18#include "llvm/CodeGen/TargetPassConfig.h"19#include "llvm/MC/TargetRegistry.h"20#include <optional>21using namespace llvm;2223extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcTarget() {24// Register the target.25RegisterTargetMachine<SparcV8TargetMachine> X(getTheSparcTarget());26RegisterTargetMachine<SparcV9TargetMachine> Y(getTheSparcV9Target());27RegisterTargetMachine<SparcelTargetMachine> Z(getTheSparcelTarget());2829PassRegistry &PR = *PassRegistry::getPassRegistry();30initializeSparcDAGToDAGISelLegacyPass(PR);31}3233static cl::opt<bool>34BranchRelaxation("sparc-enable-branch-relax", cl::Hidden, cl::init(true),35cl::desc("Relax out of range conditional branches"));3637static std::string computeDataLayout(const Triple &T, bool is64Bit) {38// Sparc is typically big endian, but some are little.39std::string Ret = T.getArch() == Triple::sparcel ? "e" : "E";40Ret += "-m:e";4142// Some ABIs have 32bit pointers.43if (!is64Bit)44Ret += "-p:32:32";4546// Alignments for 64 bit integers.47Ret += "-i64:64";4849// On SparcV9 128 floats are aligned to 128 bits, on others only to 64.50// On SparcV9 registers can hold 64 or 32 bits, on others only 32.51if (is64Bit)52Ret += "-n32:64";53else54Ret += "-f128:64-n32";5556if (is64Bit)57Ret += "-S128";58else59Ret += "-S64";6061return Ret;62}6364static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {65return RM.value_or(Reloc::Static);66}6768// Code models. Some only make sense for 64-bit code.69//70// SunCC Reloc CodeModel Constraints71// abs32 Static Small text+data+bss linked below 2^32 bytes72// abs44 Static Medium text+data+bss linked below 2^44 bytes73// abs64 Static Large text smaller than 2^31 bytes74// pic13 PIC_ Small GOT < 2^13 bytes75// pic32 PIC_ Medium GOT < 2^32 bytes76//77// All code models require that the text segment is smaller than 2GB.78static CodeModel::Model79getEffectiveSparcCodeModel(std::optional<CodeModel::Model> CM, Reloc::Model RM,80bool Is64Bit, bool JIT) {81if (CM) {82if (*CM == CodeModel::Tiny)83report_fatal_error("Target does not support the tiny CodeModel", false);84if (*CM == CodeModel::Kernel)85report_fatal_error("Target does not support the kernel CodeModel", false);86return *CM;87}88if (Is64Bit) {89if (JIT)90return CodeModel::Large;91return RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium;92}93return CodeModel::Small;94}9596/// Create an ILP32 architecture model97SparcTargetMachine::SparcTargetMachine(const Target &T, const Triple &TT,98StringRef CPU, StringRef FS,99const TargetOptions &Options,100std::optional<Reloc::Model> RM,101std::optional<CodeModel::Model> CM,102CodeGenOptLevel OL, bool JIT,103bool is64bit)104: LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options,105getEffectiveRelocModel(RM),106getEffectiveSparcCodeModel(107CM, getEffectiveRelocModel(RM), is64bit, JIT),108OL),109TLOF(std::make_unique<SparcELFTargetObjectFile>()), is64Bit(is64bit) {110initAsmInfo();111}112113SparcTargetMachine::~SparcTargetMachine() = default;114115const SparcSubtarget *116SparcTargetMachine::getSubtargetImpl(const Function &F) const {117Attribute CPUAttr = F.getFnAttribute("target-cpu");118Attribute TuneAttr = F.getFnAttribute("tune-cpu");119Attribute FSAttr = F.getFnAttribute("target-features");120121std::string CPU =122CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;123std::string TuneCPU =124TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;125std::string FS =126FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;127128// FIXME: This is related to the code below to reset the target options,129// we need to know whether or not the soft float flag is set on the130// function, so we can enable it as a subtarget feature.131bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();132133if (softFloat)134FS += FS.empty() ? "+soft-float" : ",+soft-float";135136auto &I = SubtargetMap[CPU + FS];137if (!I) {138// This needs to be done before we create a new subtarget since any139// creation will depend on the TM and the code generation flags on the140// function that reside in TargetOptions.141resetTargetOptions(F);142I = std::make_unique<SparcSubtarget>(CPU, TuneCPU, FS, *this,143this->is64Bit);144}145return I.get();146}147148MachineFunctionInfo *SparcTargetMachine::createMachineFunctionInfo(149BumpPtrAllocator &Allocator, const Function &F,150const TargetSubtargetInfo *STI) const {151return SparcMachineFunctionInfo::create<SparcMachineFunctionInfo>(Allocator,152F, STI);153}154155namespace {156/// Sparc Code Generator Pass Configuration Options.157class SparcPassConfig : public TargetPassConfig {158public:159SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM)160: TargetPassConfig(TM, PM) {}161162SparcTargetMachine &getSparcTargetMachine() const {163return getTM<SparcTargetMachine>();164}165166void addIRPasses() override;167bool addInstSelector() override;168void addPreEmitPass() override;169};170} // namespace171172TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) {173return new SparcPassConfig(*this, PM);174}175176void SparcPassConfig::addIRPasses() {177addPass(createAtomicExpandLegacyPass());178179TargetPassConfig::addIRPasses();180}181182bool SparcPassConfig::addInstSelector() {183addPass(createSparcISelDag(getSparcTargetMachine()));184return false;185}186187void SparcPassConfig::addPreEmitPass(){188if (BranchRelaxation)189addPass(&BranchRelaxationPassID);190191addPass(createSparcDelaySlotFillerPass());192addPass(new InsertNOPLoad());193addPass(new DetectRoundChange());194addPass(new FixAllFDIVSQRT());195}196197void SparcV8TargetMachine::anchor() { }198199SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT,200StringRef CPU, StringRef FS,201const TargetOptions &Options,202std::optional<Reloc::Model> RM,203std::optional<CodeModel::Model> CM,204CodeGenOptLevel OL, bool JIT)205: SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {}206207void SparcV9TargetMachine::anchor() { }208209SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT,210StringRef CPU, StringRef FS,211const TargetOptions &Options,212std::optional<Reloc::Model> RM,213std::optional<CodeModel::Model> CM,214CodeGenOptLevel OL, bool JIT)215: SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {}216217void SparcelTargetMachine::anchor() {}218219SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT,220StringRef CPU, StringRef FS,221const TargetOptions &Options,222std::optional<Reloc::Model> RM,223std::optional<CodeModel::Model> CM,224CodeGenOptLevel OL, bool JIT)225: SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {}226227228