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 23*480093f4SDimitry 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) { 580b57cec5SDimitry Andric if (!RM.hasValue()) 590b57cec5SDimitry Andric return Reloc::Static; 600b57cec5SDimitry Andric return *RM; 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // Code models. Some only make sense for 64-bit code. 640b57cec5SDimitry Andric // 650b57cec5SDimitry Andric // SunCC Reloc CodeModel Constraints 660b57cec5SDimitry Andric // abs32 Static Small text+data+bss linked below 2^32 bytes 670b57cec5SDimitry Andric // abs44 Static Medium text+data+bss linked below 2^44 bytes 680b57cec5SDimitry Andric // abs64 Static Large text smaller than 2^31 bytes 690b57cec5SDimitry Andric // pic13 PIC_ Small GOT < 2^13 bytes 700b57cec5SDimitry Andric // pic32 PIC_ Medium GOT < 2^32 bytes 710b57cec5SDimitry Andric // 720b57cec5SDimitry Andric // All code models require that the text segment is smaller than 2GB. 730b57cec5SDimitry Andric static CodeModel::Model 740b57cec5SDimitry Andric getEffectiveSparcCodeModel(Optional<CodeModel::Model> CM, Reloc::Model RM, 750b57cec5SDimitry Andric bool Is64Bit, bool JIT) { 760b57cec5SDimitry Andric if (CM) { 770b57cec5SDimitry Andric if (*CM == CodeModel::Tiny) 780b57cec5SDimitry Andric report_fatal_error("Target does not support the tiny CodeModel", false); 790b57cec5SDimitry Andric if (*CM == CodeModel::Kernel) 800b57cec5SDimitry Andric report_fatal_error("Target does not support the kernel CodeModel", false); 810b57cec5SDimitry Andric return *CM; 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric if (Is64Bit) { 840b57cec5SDimitry Andric if (JIT) 850b57cec5SDimitry Andric return CodeModel::Large; 860b57cec5SDimitry Andric return RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric return CodeModel::Small; 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric /// Create an ILP32 architecture model 920b57cec5SDimitry Andric SparcTargetMachine::SparcTargetMachine( 930b57cec5SDimitry Andric const Target &T, const Triple &TT, StringRef CPU, StringRef FS, 940b57cec5SDimitry Andric const TargetOptions &Options, Optional<Reloc::Model> RM, 950b57cec5SDimitry Andric Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT, bool is64bit) 960b57cec5SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options, 970b57cec5SDimitry Andric getEffectiveRelocModel(RM), 980b57cec5SDimitry Andric getEffectiveSparcCodeModel( 990b57cec5SDimitry Andric CM, getEffectiveRelocModel(RM), is64bit, JIT), 1000b57cec5SDimitry Andric OL), 1018bcb0991SDimitry Andric TLOF(std::make_unique<SparcELFTargetObjectFile>()), 1020b57cec5SDimitry Andric Subtarget(TT, CPU, FS, *this, is64bit), is64Bit(is64bit) { 1030b57cec5SDimitry Andric initAsmInfo(); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric SparcTargetMachine::~SparcTargetMachine() {} 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric const SparcSubtarget * 1090b57cec5SDimitry Andric SparcTargetMachine::getSubtargetImpl(const Function &F) const { 1100b57cec5SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 1110b57cec5SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric std::string CPU = !CPUAttr.hasAttribute(Attribute::None) 1140b57cec5SDimitry Andric ? CPUAttr.getValueAsString().str() 1150b57cec5SDimitry Andric : TargetCPU; 1160b57cec5SDimitry Andric std::string FS = !FSAttr.hasAttribute(Attribute::None) 1170b57cec5SDimitry Andric ? FSAttr.getValueAsString().str() 1180b57cec5SDimitry Andric : TargetFS; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // FIXME: This is related to the code below to reset the target options, 1210b57cec5SDimitry Andric // we need to know whether or not the soft float flag is set on the 1220b57cec5SDimitry Andric // function, so we can enable it as a subtarget feature. 1230b57cec5SDimitry Andric bool softFloat = 1240b57cec5SDimitry Andric F.hasFnAttribute("use-soft-float") && 1250b57cec5SDimitry Andric F.getFnAttribute("use-soft-float").getValueAsString() == "true"; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric if (softFloat) 1280b57cec5SDimitry Andric FS += FS.empty() ? "+soft-float" : ",+soft-float"; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric auto &I = SubtargetMap[CPU + FS]; 1310b57cec5SDimitry Andric if (!I) { 1320b57cec5SDimitry Andric // This needs to be done before we create a new subtarget since any 1330b57cec5SDimitry Andric // creation will depend on the TM and the code generation flags on the 1340b57cec5SDimitry Andric // function that reside in TargetOptions. 1350b57cec5SDimitry Andric resetTargetOptions(F); 1368bcb0991SDimitry Andric I = std::make_unique<SparcSubtarget>(TargetTriple, CPU, FS, *this, 1370b57cec5SDimitry Andric this->is64Bit); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric return I.get(); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric namespace { 1430b57cec5SDimitry Andric /// Sparc Code Generator Pass Configuration Options. 1440b57cec5SDimitry Andric class SparcPassConfig : public TargetPassConfig { 1450b57cec5SDimitry Andric public: 1460b57cec5SDimitry Andric SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM) 1470b57cec5SDimitry Andric : TargetPassConfig(TM, PM) {} 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric SparcTargetMachine &getSparcTargetMachine() const { 1500b57cec5SDimitry Andric return getTM<SparcTargetMachine>(); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric void addIRPasses() override; 1540b57cec5SDimitry Andric bool addInstSelector() override; 1550b57cec5SDimitry Andric void addPreEmitPass() override; 1560b57cec5SDimitry Andric }; 1570b57cec5SDimitry Andric } // namespace 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) { 1600b57cec5SDimitry Andric return new SparcPassConfig(*this, PM); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric void SparcPassConfig::addIRPasses() { 1640b57cec5SDimitry Andric addPass(createAtomicExpandPass()); 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric TargetPassConfig::addIRPasses(); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric bool SparcPassConfig::addInstSelector() { 1700b57cec5SDimitry Andric addPass(createSparcISelDag(getSparcTargetMachine())); 1710b57cec5SDimitry Andric return false; 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric void SparcPassConfig::addPreEmitPass(){ 1750b57cec5SDimitry Andric addPass(createSparcDelaySlotFillerPass()); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) 1780b57cec5SDimitry Andric { 1790b57cec5SDimitry Andric addPass(new InsertNOPLoad()); 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric if (this->getSparcTargetMachine().getSubtargetImpl()->detectRoundChange()) { 1820b57cec5SDimitry Andric addPass(new DetectRoundChange()); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT()) 1850b57cec5SDimitry Andric { 1860b57cec5SDimitry Andric addPass(new FixAllFDIVSQRT()); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric void SparcV8TargetMachine::anchor() { } 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT, 1930b57cec5SDimitry Andric StringRef CPU, StringRef FS, 1940b57cec5SDimitry Andric const TargetOptions &Options, 1950b57cec5SDimitry Andric Optional<Reloc::Model> RM, 1960b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 1970b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 1980b57cec5SDimitry Andric : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric void SparcV9TargetMachine::anchor() { } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT, 2030b57cec5SDimitry Andric StringRef CPU, StringRef FS, 2040b57cec5SDimitry Andric const TargetOptions &Options, 2050b57cec5SDimitry Andric Optional<Reloc::Model> RM, 2060b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 2070b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 2080b57cec5SDimitry Andric : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {} 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric void SparcelTargetMachine::anchor() {} 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT, 2130b57cec5SDimitry Andric StringRef CPU, StringRef FS, 2140b57cec5SDimitry Andric const TargetOptions &Options, 2150b57cec5SDimitry Andric Optional<Reloc::Model> RM, 2160b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 2170b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 2180b57cec5SDimitry Andric : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} 219