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