10b57cec5SDimitry Andric //===-- SparcTargetMachine.cpp - Define TargetMachine for Sparc -----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // 100b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "SparcTargetMachine.h" 130b57cec5SDimitry Andric #include "LeonPasses.h" 140b57cec5SDimitry Andric #include "Sparc.h" 150b57cec5SDimitry Andric #include "SparcTargetObjectFile.h" 160b57cec5SDimitry Andric #include "TargetInfo/SparcTargetInfo.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 190b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManager.h" 200b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h" 210b57cec5SDimitry Andric using namespace llvm; 220b57cec5SDimitry Andric 23480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcTarget() { 240b57cec5SDimitry Andric // Register the target. 250b57cec5SDimitry Andric RegisterTargetMachine<SparcV8TargetMachine> X(getTheSparcTarget()); 260b57cec5SDimitry Andric RegisterTargetMachine<SparcV9TargetMachine> Y(getTheSparcV9Target()); 270b57cec5SDimitry Andric RegisterTargetMachine<SparcelTargetMachine> Z(getTheSparcelTarget()); 280b57cec5SDimitry Andric } 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric static std::string computeDataLayout(const Triple &T, bool is64Bit) { 310b57cec5SDimitry Andric // Sparc is typically big endian, but some are little. 320b57cec5SDimitry Andric std::string Ret = T.getArch() == Triple::sparcel ? "e" : "E"; 330b57cec5SDimitry Andric Ret += "-m:e"; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric // Some ABIs have 32bit pointers. 360b57cec5SDimitry Andric if (!is64Bit) 370b57cec5SDimitry Andric Ret += "-p:32:32"; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric // Alignments for 64 bit integers. 400b57cec5SDimitry Andric Ret += "-i64:64"; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric // On SparcV9 128 floats are aligned to 128 bits, on others only to 64. 430b57cec5SDimitry Andric // On SparcV9 registers can hold 64 or 32 bits, on others only 32. 440b57cec5SDimitry Andric if (is64Bit) 450b57cec5SDimitry Andric Ret += "-n32:64"; 460b57cec5SDimitry Andric else 470b57cec5SDimitry Andric Ret += "-f128:64-n32"; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric if (is64Bit) 500b57cec5SDimitry Andric Ret += "-S128"; 510b57cec5SDimitry Andric else 520b57cec5SDimitry Andric Ret += "-S64"; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric return Ret; 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) { 58e8d8bef9SDimitry Andric return RM.getValueOr(Reloc::Static); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // Code models. Some only make sense for 64-bit code. 620b57cec5SDimitry Andric // 630b57cec5SDimitry Andric // SunCC Reloc CodeModel Constraints 640b57cec5SDimitry Andric // abs32 Static Small text+data+bss linked below 2^32 bytes 650b57cec5SDimitry Andric // abs44 Static Medium text+data+bss linked below 2^44 bytes 660b57cec5SDimitry Andric // abs64 Static Large text smaller than 2^31 bytes 670b57cec5SDimitry Andric // pic13 PIC_ Small GOT < 2^13 bytes 680b57cec5SDimitry Andric // pic32 PIC_ Medium GOT < 2^32 bytes 690b57cec5SDimitry Andric // 700b57cec5SDimitry Andric // All code models require that the text segment is smaller than 2GB. 710b57cec5SDimitry Andric static CodeModel::Model 720b57cec5SDimitry Andric getEffectiveSparcCodeModel(Optional<CodeModel::Model> CM, Reloc::Model RM, 730b57cec5SDimitry Andric bool Is64Bit, bool JIT) { 740b57cec5SDimitry Andric if (CM) { 750b57cec5SDimitry Andric if (*CM == CodeModel::Tiny) 760b57cec5SDimitry Andric report_fatal_error("Target does not support the tiny CodeModel", false); 770b57cec5SDimitry Andric if (*CM == CodeModel::Kernel) 780b57cec5SDimitry Andric report_fatal_error("Target does not support the kernel CodeModel", false); 790b57cec5SDimitry Andric return *CM; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric if (Is64Bit) { 820b57cec5SDimitry Andric if (JIT) 830b57cec5SDimitry Andric return CodeModel::Large; 840b57cec5SDimitry Andric return RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric return CodeModel::Small; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric /// Create an ILP32 architecture model 900b57cec5SDimitry Andric SparcTargetMachine::SparcTargetMachine( 910b57cec5SDimitry Andric const Target &T, const Triple &TT, StringRef CPU, StringRef FS, 920b57cec5SDimitry Andric const TargetOptions &Options, Optional<Reloc::Model> RM, 930b57cec5SDimitry Andric Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT, bool is64bit) 940b57cec5SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options, 950b57cec5SDimitry Andric getEffectiveRelocModel(RM), 960b57cec5SDimitry Andric getEffectiveSparcCodeModel( 970b57cec5SDimitry Andric CM, getEffectiveRelocModel(RM), is64bit, JIT), 980b57cec5SDimitry Andric OL), 998bcb0991SDimitry Andric TLOF(std::make_unique<SparcELFTargetObjectFile>()), 1005ffd83dbSDimitry Andric Subtarget(TT, std::string(CPU), std::string(FS), *this, is64bit), 1015ffd83dbSDimitry Andric is64Bit(is64bit) { 1020b57cec5SDimitry Andric initAsmInfo(); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric SparcTargetMachine::~SparcTargetMachine() {} 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric const SparcSubtarget * 1080b57cec5SDimitry Andric SparcTargetMachine::getSubtargetImpl(const Function &F) const { 1090b57cec5SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 1100b57cec5SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 1110b57cec5SDimitry Andric 112e8d8bef9SDimitry Andric std::string CPU = 113e8d8bef9SDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 114e8d8bef9SDimitry Andric std::string FS = 115e8d8bef9SDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric // FIXME: This is related to the code below to reset the target options, 1180b57cec5SDimitry Andric // we need to know whether or not the soft float flag is set on the 1190b57cec5SDimitry Andric // function, so we can enable it as a subtarget feature. 120*fe6060f1SDimitry Andric bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool(); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric if (softFloat) 1230b57cec5SDimitry Andric FS += FS.empty() ? "+soft-float" : ",+soft-float"; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric auto &I = SubtargetMap[CPU + FS]; 1260b57cec5SDimitry Andric if (!I) { 1270b57cec5SDimitry Andric // This needs to be done before we create a new subtarget since any 1280b57cec5SDimitry Andric // creation will depend on the TM and the code generation flags on the 1290b57cec5SDimitry Andric // function that reside in TargetOptions. 1300b57cec5SDimitry Andric resetTargetOptions(F); 1318bcb0991SDimitry Andric I = std::make_unique<SparcSubtarget>(TargetTriple, CPU, FS, *this, 1320b57cec5SDimitry Andric this->is64Bit); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric return I.get(); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric namespace { 1380b57cec5SDimitry Andric /// Sparc Code Generator Pass Configuration Options. 1390b57cec5SDimitry Andric class SparcPassConfig : public TargetPassConfig { 1400b57cec5SDimitry Andric public: 1410b57cec5SDimitry Andric SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM) 1420b57cec5SDimitry Andric : TargetPassConfig(TM, PM) {} 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric SparcTargetMachine &getSparcTargetMachine() const { 1450b57cec5SDimitry Andric return getTM<SparcTargetMachine>(); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric void addIRPasses() override; 1490b57cec5SDimitry Andric bool addInstSelector() override; 1500b57cec5SDimitry Andric void addPreEmitPass() override; 1510b57cec5SDimitry Andric }; 1520b57cec5SDimitry Andric } // namespace 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) { 1550b57cec5SDimitry Andric return new SparcPassConfig(*this, PM); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric void SparcPassConfig::addIRPasses() { 1590b57cec5SDimitry Andric addPass(createAtomicExpandPass()); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric TargetPassConfig::addIRPasses(); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric bool SparcPassConfig::addInstSelector() { 1650b57cec5SDimitry Andric addPass(createSparcISelDag(getSparcTargetMachine())); 1660b57cec5SDimitry Andric return false; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric void SparcPassConfig::addPreEmitPass(){ 1700b57cec5SDimitry Andric addPass(createSparcDelaySlotFillerPass()); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) 1730b57cec5SDimitry Andric { 1740b57cec5SDimitry Andric addPass(new InsertNOPLoad()); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric if (this->getSparcTargetMachine().getSubtargetImpl()->detectRoundChange()) { 1770b57cec5SDimitry Andric addPass(new DetectRoundChange()); 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT()) 1800b57cec5SDimitry Andric { 1810b57cec5SDimitry Andric addPass(new FixAllFDIVSQRT()); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric void SparcV8TargetMachine::anchor() { } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT, 1880b57cec5SDimitry Andric StringRef CPU, StringRef FS, 1890b57cec5SDimitry Andric const TargetOptions &Options, 1900b57cec5SDimitry Andric Optional<Reloc::Model> RM, 1910b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 1920b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 1930b57cec5SDimitry Andric : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric void SparcV9TargetMachine::anchor() { } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT, 1980b57cec5SDimitry Andric StringRef CPU, StringRef FS, 1990b57cec5SDimitry Andric const TargetOptions &Options, 2000b57cec5SDimitry Andric Optional<Reloc::Model> RM, 2010b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 2020b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 2030b57cec5SDimitry Andric : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {} 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric void SparcelTargetMachine::anchor() {} 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT, 2080b57cec5SDimitry Andric StringRef CPU, StringRef FS, 2090b57cec5SDimitry Andric const TargetOptions &Options, 2100b57cec5SDimitry Andric Optional<Reloc::Model> RM, 2110b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 2120b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 2130b57cec5SDimitry Andric : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} 214