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