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 "SparcTargetTransformInfo.h"
18#include "TargetInfo/SparcTargetInfo.h"
19#include "llvm/CodeGen/Passes.h"
20#include "llvm/CodeGen/TargetPassConfig.h"
21#include "llvm/MC/TargetRegistry.h"
22#include "llvm/Support/Compiler.h"
23#include <optional>
24using namespace llvm;
25
26extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcTarget() {
27 // Register the target.
28 RegisterTargetMachine<SparcV8TargetMachine> X(getTheSparcTarget());
29 RegisterTargetMachine<SparcV9TargetMachine> Y(getTheSparcV9Target());
30 RegisterTargetMachine<SparcelTargetMachine> Z(getTheSparcelTarget());
31
32 PassRegistry &PR = *PassRegistry::getPassRegistry();
33 initializeSparcAsmPrinterPass(PR);
34 initializeSparcDAGToDAGISelLegacyPass(PR);
35 initializeErrataWorkaroundPass(PR);
36}
37
38static cl::opt<bool>
39 BranchRelaxation("sparc-enable-branch-relax", cl::Hidden, cl::init(Val: true),
40 cl::desc("Relax out of range conditional branches"));
41
42static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
43 return RM.value_or(u: Reloc::Static);
44}
45
46// Code models. Some only make sense for 64-bit code.
47//
48// SunCC Reloc CodeModel Constraints
49// abs32 Static Small text+data+bss linked below 2^32 bytes
50// abs44 Static Medium text+data+bss linked below 2^44 bytes
51// abs64 Static Large text smaller than 2^31 bytes
52// pic13 PIC_ Small GOT < 2^13 bytes
53// pic32 PIC_ Medium GOT < 2^32 bytes
54//
55// All code models require that the text segment is smaller than 2GB.
56static CodeModel::Model
57getEffectiveSparcCodeModel(std::optional<CodeModel::Model> CM, Reloc::Model RM,
58 bool Is64Bit, bool JIT) {
59 if (CM) {
60 if (*CM == CodeModel::Tiny)
61 report_fatal_error(reason: "Target does not support the tiny CodeModel", gen_crash_diag: false);
62 if (*CM == CodeModel::Kernel)
63 report_fatal_error(reason: "Target does not support the kernel CodeModel", gen_crash_diag: false);
64 return *CM;
65 }
66 if (Is64Bit) {
67 if (JIT)
68 return CodeModel::Large;
69 return RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium;
70 }
71 return CodeModel::Small;
72}
73
74/// Create an ILP32 architecture model
75SparcTargetMachine::SparcTargetMachine(const Target &T, const Triple &TT,
76 StringRef CPU, StringRef FS,
77 const TargetOptions &Options,
78 std::optional<Reloc::Model> RM,
79 std::optional<CodeModel::Model> CM,
80 CodeGenOptLevel OL, bool JIT)
81 : CodeGenTargetMachineImpl(
82 T, TT.computeDataLayout(), TT, CPU, FS, Options,
83 getEffectiveRelocModel(RM),
84 getEffectiveSparcCodeModel(CM, RM: getEffectiveRelocModel(RM),
85 Is64Bit: TT.isSPARC64(), JIT),
86 OL),
87 TLOF(std::make_unique<SparcELFTargetObjectFile>()) {
88 initAsmInfo();
89}
90
91SparcTargetMachine::~SparcTargetMachine() = default;
92
93const SparcSubtarget *
94SparcTargetMachine::getSubtargetImpl(const Function &F) const {
95 Attribute CPUAttr = F.getFnAttribute(Kind: "target-cpu");
96 Attribute TuneAttr = F.getFnAttribute(Kind: "tune-cpu");
97 Attribute FSAttr = F.getFnAttribute(Kind: "target-features");
98
99 std::string CPU =
100 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
101 std::string TuneCPU =
102 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
103 std::string FS =
104 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
105
106 // FIXME: This is related to the code below to reset the target options,
107 // we need to know whether or not the soft float flag is set on the
108 // function, so we can enable it as a subtarget feature.
109 bool softFloat = F.getFnAttribute(Kind: "use-soft-float").getValueAsBool();
110
111 if (softFloat)
112 FS += FS.empty() ? "+soft-float" : ",+soft-float";
113
114 auto &I = SubtargetMap[CPU + FS];
115 if (!I) {
116 // This needs to be done before we create a new subtarget since any
117 // creation will depend on the TM and the code generation flags on the
118 // function that reside in TargetOptions.
119 resetTargetOptions(F);
120 I = std::make_unique<SparcSubtarget>(args&: CPU, args&: TuneCPU, args&: FS, args: *this);
121 }
122 return I.get();
123}
124
125MachineFunctionInfo *SparcTargetMachine::createMachineFunctionInfo(
126 BumpPtrAllocator &Allocator, const Function &F,
127 const TargetSubtargetInfo *STI) const {
128 return SparcMachineFunctionInfo::create<SparcMachineFunctionInfo>(Allocator,
129 F, STI);
130}
131
132namespace {
133/// Sparc Code Generator Pass Configuration Options.
134class SparcPassConfig : public TargetPassConfig {
135public:
136 SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM)
137 : TargetPassConfig(TM, PM) {}
138
139 SparcTargetMachine &getSparcTargetMachine() const {
140 return getTM<SparcTargetMachine>();
141 }
142
143 void addIRPasses() override;
144 bool addInstSelector() override;
145 void addPreEmitPass() override;
146};
147} // namespace
148
149TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) {
150 return new SparcPassConfig(*this, PM);
151}
152
153TargetTransformInfo
154SparcTargetMachine::getTargetTransformInfo(const Function &F) const {
155 return TargetTransformInfo(std::make_unique<SparcTTIImpl>(args: this, args: F));
156}
157
158void SparcPassConfig::addIRPasses() {
159 addPass(P: createAtomicExpandLegacyPass());
160
161 TargetPassConfig::addIRPasses();
162}
163
164bool SparcPassConfig::addInstSelector() {
165 addPass(P: createSparcISelDag(TM&: getSparcTargetMachine()));
166 return false;
167}
168
169void SparcPassConfig::addPreEmitPass(){
170 if (BranchRelaxation)
171 addPass(PassID: &BranchRelaxationPassID);
172
173 addPass(P: createSparcDelaySlotFillerPass());
174 addPass(P: new InsertNOPLoad());
175 addPass(P: new DetectRoundChange());
176 addPass(P: new FixAllFDIVSQRT());
177 addPass(P: new ErrataWorkaround());
178}
179
180void SparcV8TargetMachine::anchor() { }
181
182SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT,
183 StringRef CPU, StringRef FS,
184 const TargetOptions &Options,
185 std::optional<Reloc::Model> RM,
186 std::optional<CodeModel::Model> CM,
187 CodeGenOptLevel OL, bool JIT)
188 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT) {}
189
190void SparcV9TargetMachine::anchor() { }
191
192SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT,
193 StringRef CPU, StringRef FS,
194 const TargetOptions &Options,
195 std::optional<Reloc::Model> RM,
196 std::optional<CodeModel::Model> CM,
197 CodeGenOptLevel OL, bool JIT)
198 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT) {}
199
200void SparcelTargetMachine::anchor() {}
201
202SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT,
203 StringRef CPU, StringRef FS,
204 const TargetOptions &Options,
205 std::optional<Reloc::Model> RM,
206 std::optional<CodeModel::Model> CM,
207 CodeGenOptLevel OL, bool JIT)
208 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT) {}
209