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-exception
6 //
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/IR/LegacyPassManager.h"
21 #include "llvm/MC/TargetRegistry.h"
22 #include <optional>
23 using namespace llvm;
24
LLVMInitializeSparcTarget()25 extern "C" 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 initializeSparcDAGToDAGISelPass(PR);
33 }
34
35 static cl::opt<bool>
36 BranchRelaxation("sparc-enable-branch-relax", cl::Hidden, cl::init(true),
37 cl::desc("Relax out of range conditional branches"));
38
computeDataLayout(const Triple & T,bool is64Bit)39 static std::string computeDataLayout(const Triple &T, bool is64Bit) {
40 // Sparc is typically big endian, but some are little.
41 std::string Ret = T.getArch() == Triple::sparcel ? "e" : "E";
42 Ret += "-m:e";
43
44 // Some ABIs have 32bit pointers.
45 if (!is64Bit)
46 Ret += "-p:32:32";
47
48 // Alignments for 64 bit integers.
49 Ret += "-i64:64";
50
51 // On SparcV9 128 floats are aligned to 128 bits, on others only to 64.
52 // On SparcV9 registers can hold 64 or 32 bits, on others only 32.
53 if (is64Bit)
54 Ret += "-n32:64";
55 else
56 Ret += "-f128:64-n32";
57
58 if (is64Bit)
59 Ret += "-S128";
60 else
61 Ret += "-S64";
62
63 return Ret;
64 }
65
getEffectiveRelocModel(std::optional<Reloc::Model> RM)66 static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
67 return RM.value_or(Reloc::Static);
68 }
69
70 // Code models. Some only make sense for 64-bit code.
71 //
72 // SunCC Reloc CodeModel Constraints
73 // abs32 Static Small text+data+bss linked below 2^32 bytes
74 // abs44 Static Medium text+data+bss linked below 2^44 bytes
75 // abs64 Static Large text smaller than 2^31 bytes
76 // pic13 PIC_ Small GOT < 2^13 bytes
77 // pic32 PIC_ Medium GOT < 2^32 bytes
78 //
79 // All code models require that the text segment is smaller than 2GB.
80 static CodeModel::Model
getEffectiveSparcCodeModel(std::optional<CodeModel::Model> CM,Reloc::Model RM,bool Is64Bit,bool JIT)81 getEffectiveSparcCodeModel(std::optional<CodeModel::Model> CM, Reloc::Model RM,
82 bool Is64Bit, bool JIT) {
83 if (CM) {
84 if (*CM == CodeModel::Tiny)
85 report_fatal_error("Target does not support the tiny CodeModel", false);
86 if (*CM == CodeModel::Kernel)
87 report_fatal_error("Target does not support the kernel CodeModel", false);
88 return *CM;
89 }
90 if (Is64Bit) {
91 if (JIT)
92 return CodeModel::Large;
93 return RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium;
94 }
95 return CodeModel::Small;
96 }
97
98 /// Create an ILP32 architecture model
SparcTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT,bool is64bit)99 SparcTargetMachine::SparcTargetMachine(const Target &T, const Triple &TT,
100 StringRef CPU, StringRef FS,
101 const TargetOptions &Options,
102 std::optional<Reloc::Model> RM,
103 std::optional<CodeModel::Model> CM,
104 CodeGenOpt::Level OL, bool JIT,
105 bool is64bit)
106 : LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options,
107 getEffectiveRelocModel(RM),
108 getEffectiveSparcCodeModel(
109 CM, getEffectiveRelocModel(RM), is64bit, JIT),
110 OL),
111 TLOF(std::make_unique<SparcELFTargetObjectFile>()),
112 Subtarget(TT, std::string(CPU), std::string(FS), *this, is64bit),
113 is64Bit(is64bit) {
114 initAsmInfo();
115 }
116
117 SparcTargetMachine::~SparcTargetMachine() = default;
118
119 const SparcSubtarget *
getSubtargetImpl(const Function & F) const120 SparcTargetMachine::getSubtargetImpl(const Function &F) const {
121 Attribute CPUAttr = F.getFnAttribute("target-cpu");
122 Attribute FSAttr = F.getFnAttribute("target-features");
123
124 std::string CPU =
125 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
126 std::string FS =
127 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
128
129 // FIXME: This is related to the code below to reset the target options,
130 // we need to know whether or not the soft float flag is set on the
131 // function, so we can enable it as a subtarget feature.
132 bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
133
134 if (softFloat)
135 FS += FS.empty() ? "+soft-float" : ",+soft-float";
136
137 auto &I = SubtargetMap[CPU + FS];
138 if (!I) {
139 // This needs to be done before we create a new subtarget since any
140 // creation will depend on the TM and the code generation flags on the
141 // function that reside in TargetOptions.
142 resetTargetOptions(F);
143 I = std::make_unique<SparcSubtarget>(TargetTriple, CPU, FS, *this,
144 this->is64Bit);
145 }
146 return I.get();
147 }
148
createMachineFunctionInfo(BumpPtrAllocator & Allocator,const Function & F,const TargetSubtargetInfo * STI) const149 MachineFunctionInfo *SparcTargetMachine::createMachineFunctionInfo(
150 BumpPtrAllocator &Allocator, const Function &F,
151 const TargetSubtargetInfo *STI) const {
152 return SparcMachineFunctionInfo::create<SparcMachineFunctionInfo>(Allocator,
153 F, STI);
154 }
155
156 namespace {
157 /// Sparc Code Generator Pass Configuration Options.
158 class SparcPassConfig : public TargetPassConfig {
159 public:
SparcPassConfig(SparcTargetMachine & TM,PassManagerBase & PM)160 SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM)
161 : TargetPassConfig(TM, PM) {}
162
getSparcTargetMachine() const163 SparcTargetMachine &getSparcTargetMachine() const {
164 return getTM<SparcTargetMachine>();
165 }
166
167 void addIRPasses() override;
168 bool addInstSelector() override;
169 void addPreEmitPass() override;
170 };
171 } // namespace
172
createPassConfig(PassManagerBase & PM)173 TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) {
174 return new SparcPassConfig(*this, PM);
175 }
176
addIRPasses()177 void SparcPassConfig::addIRPasses() {
178 addPass(createAtomicExpandPass());
179
180 TargetPassConfig::addIRPasses();
181 }
182
addInstSelector()183 bool SparcPassConfig::addInstSelector() {
184 addPass(createSparcISelDag(getSparcTargetMachine()));
185 return false;
186 }
187
addPreEmitPass()188 void SparcPassConfig::addPreEmitPass(){
189 if (BranchRelaxation)
190 addPass(&BranchRelaxationPassID);
191
192 addPass(createSparcDelaySlotFillerPass());
193
194 if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad())
195 {
196 addPass(new InsertNOPLoad());
197 }
198 if (this->getSparcTargetMachine().getSubtargetImpl()->detectRoundChange()) {
199 addPass(new DetectRoundChange());
200 }
201 if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT())
202 {
203 addPass(new FixAllFDIVSQRT());
204 }
205 }
206
anchor()207 void SparcV8TargetMachine::anchor() { }
208
SparcV8TargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)209 SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT,
210 StringRef CPU, StringRef FS,
211 const TargetOptions &Options,
212 std::optional<Reloc::Model> RM,
213 std::optional<CodeModel::Model> CM,
214 CodeGenOpt::Level OL, bool JIT)
215 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {}
216
anchor()217 void SparcV9TargetMachine::anchor() { }
218
SparcV9TargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)219 SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT,
220 StringRef CPU, StringRef FS,
221 const TargetOptions &Options,
222 std::optional<Reloc::Model> RM,
223 std::optional<CodeModel::Model> CM,
224 CodeGenOpt::Level OL, bool JIT)
225 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {}
226
anchor()227 void SparcelTargetMachine::anchor() {}
228
SparcelTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)229 SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT,
230 StringRef CPU, StringRef FS,
231 const TargetOptions &Options,
232 std::optional<Reloc::Model> RM,
233 std::optional<CodeModel::Model> CM,
234 CodeGenOpt::Level OL, bool JIT)
235 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {}
236