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 I = std::make_unique<SparcSubtarget>(args&: CPU, args&: TuneCPU, args&: FS, args: *this);
117 return I.get();
118}
119
120MachineFunctionInfo *SparcTargetMachine::createMachineFunctionInfo(
121 BumpPtrAllocator &Allocator, const Function &F,
122 const TargetSubtargetInfo *STI) const {
123 return SparcMachineFunctionInfo::create<SparcMachineFunctionInfo>(Allocator,
124 F, STI);
125}
126
127namespace {
128/// Sparc Code Generator Pass Configuration Options.
129class SparcPassConfig : public TargetPassConfig {
130public:
131 SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM)
132 : TargetPassConfig(TM, PM) {}
133
134 SparcTargetMachine &getSparcTargetMachine() const {
135 return getTM<SparcTargetMachine>();
136 }
137
138 void addIRPasses() override;
139 bool addInstSelector() override;
140 void addPreEmitPass() override;
141};
142} // namespace
143
144TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) {
145 return new SparcPassConfig(*this, PM);
146}
147
148TargetTransformInfo
149SparcTargetMachine::getTargetTransformInfo(const Function &F) const {
150 return TargetTransformInfo(std::make_unique<SparcTTIImpl>(args: this, args: F));
151}
152
153void SparcPassConfig::addIRPasses() {
154 addPass(P: createAtomicExpandLegacyPass());
155
156 TargetPassConfig::addIRPasses();
157}
158
159bool SparcPassConfig::addInstSelector() {
160 addPass(P: createSparcISelDag(TM&: getSparcTargetMachine()));
161 return false;
162}
163
164void SparcPassConfig::addPreEmitPass(){
165 if (BranchRelaxation)
166 addPass(PassID: &BranchRelaxationPassID);
167
168 addPass(P: createSparcDelaySlotFillerPass());
169 addPass(P: new InsertNOPLoad());
170 addPass(P: new DetectRoundChange());
171 addPass(P: new FixAllFDIVSQRT());
172 addPass(P: new ErrataWorkaround());
173}
174
175void SparcV8TargetMachine::anchor() { }
176
177SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT,
178 StringRef CPU, StringRef FS,
179 const TargetOptions &Options,
180 std::optional<Reloc::Model> RM,
181 std::optional<CodeModel::Model> CM,
182 CodeGenOptLevel OL, bool JIT)
183 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT) {}
184
185void SparcV9TargetMachine::anchor() { }
186
187SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT,
188 StringRef CPU, StringRef FS,
189 const TargetOptions &Options,
190 std::optional<Reloc::Model> RM,
191 std::optional<CodeModel::Model> CM,
192 CodeGenOptLevel OL, bool JIT)
193 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT) {}
194
195void SparcelTargetMachine::anchor() {}
196
197SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT,
198 StringRef CPU, StringRef FS,
199 const TargetOptions &Options,
200 std::optional<Reloc::Model> RM,
201 std::optional<CodeModel::Model> CM,
202 CodeGenOptLevel OL, bool JIT)
203 : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT) {}
204