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