xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/M68kTargetMachine.cpp (revision 22d7dd834bc5cd189810e414701e3ad1e98102e4)
1 //===-- M68kTargetMachine.cpp - M68k Target Machine -------------*- C++ -*-===//
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 /// \file
10 /// This file contains implementation for M68k target machine.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "M68kTargetMachine.h"
15 #include "M68k.h"
16 #include "M68kMachineFunction.h"
17 #include "M68kSubtarget.h"
18 #include "M68kTargetObjectFile.h"
19 #include "TargetInfo/M68kTargetInfo.h"
20 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
21 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
22 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
23 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
24 #include "llvm/CodeGen/Passes.h"
25 #include "llvm/CodeGen/TargetPassConfig.h"
26 #include "llvm/IR/LegacyPassManager.h"
27 #include "llvm/InitializePasses.h"
28 #include "llvm/MC/TargetRegistry.h"
29 #include "llvm/PassRegistry.h"
30 #include <memory>
31 #include <optional>
32 
33 using namespace llvm;
34 
35 #define DEBUG_TYPE "m68k"
36 
37 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kTarget() {
38   RegisterTargetMachine<M68kTargetMachine> X(getTheM68kTarget());
39   auto *PR = PassRegistry::getPassRegistry();
40   initializeGlobalISel(*PR);
41   initializeM68kDAGToDAGISelPass(*PR);
42 }
43 
44 namespace {
45 
46 std::string computeDataLayout(const Triple &TT, StringRef CPU,
47                               const TargetOptions &Options) {
48   std::string Ret = "";
49   // M68k is Big Endian
50   Ret += "E";
51 
52   // FIXME how to wire it with the used object format?
53   Ret += "-m:e";
54 
55   // M68k pointers are always 32 bit wide even for 16-bit CPUs.
56   // The ABI only specifies 16-bit alignment.
57   // On at least the 68020+ with a 32-bit bus, there is a performance benefit
58   // to having 32-bit alignment.
59   Ret += "-p:32:16:32";
60 
61   // Bytes do not require special alignment, words are word aligned and
62   // long words are word aligned at minimum.
63   Ret += "-i8:8:8-i16:16:16-i32:16:32";
64 
65   // FIXME no floats at the moment
66 
67   // The registers can hold 8, 16, 32 bits
68   Ret += "-n8:16:32";
69 
70   Ret += "-a:0:16-S16";
71 
72   return Ret;
73 }
74 
75 Reloc::Model getEffectiveRelocModel(const Triple &TT,
76                                     std::optional<Reloc::Model> RM) {
77   // If not defined we default to static
78   if (!RM.has_value())
79     return Reloc::Static;
80 
81   return *RM;
82 }
83 
84 CodeModel::Model getEffectiveCodeModel(std::optional<CodeModel::Model> CM,
85                                        bool JIT) {
86   if (!CM) {
87     return CodeModel::Small;
88   } else if (CM == CodeModel::Large) {
89     llvm_unreachable("Large code model is not supported");
90   } else if (CM == CodeModel::Kernel) {
91     llvm_unreachable("Kernel code model is not implemented yet");
92   }
93   return CM.value();
94 }
95 } // end anonymous namespace
96 
97 M68kTargetMachine::M68kTargetMachine(const Target &T, const Triple &TT,
98                                      StringRef CPU, StringRef FS,
99                                      const TargetOptions &Options,
100                                      std::optional<Reloc::Model> RM,
101                                      std::optional<CodeModel::Model> CM,
102                                      CodeGenOpt::Level OL, bool JIT)
103     : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options), TT, CPU, FS,
104                         Options, getEffectiveRelocModel(TT, RM),
105                         ::getEffectiveCodeModel(CM, JIT), OL),
106       TLOF(std::make_unique<M68kELFTargetObjectFile>()),
107       Subtarget(TT, CPU, FS, *this) {
108   initAsmInfo();
109 }
110 
111 M68kTargetMachine::~M68kTargetMachine() {}
112 
113 const M68kSubtarget *
114 M68kTargetMachine::getSubtargetImpl(const Function &F) const {
115   Attribute CPUAttr = F.getFnAttribute("target-cpu");
116   Attribute FSAttr = F.getFnAttribute("target-features");
117 
118   auto CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
119   auto FS = FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
120 
121   auto &I = SubtargetMap[CPU + FS];
122   if (!I) {
123     // This needs to be done before we create a new subtarget since any
124     // creation will depend on the TM and the code generation flags on the
125     // function that reside in TargetOptions.
126     resetTargetOptions(F);
127     I = std::make_unique<M68kSubtarget>(TargetTriple, CPU, FS, *this);
128   }
129   return I.get();
130 }
131 
132 MachineFunctionInfo *M68kTargetMachine::createMachineFunctionInfo(
133     BumpPtrAllocator &Allocator, const Function &F,
134     const TargetSubtargetInfo *STI) const {
135   return M68kMachineFunctionInfo::create<M68kMachineFunctionInfo>(Allocator, F,
136                                                                   STI);
137 }
138 
139 //===----------------------------------------------------------------------===//
140 // Pass Pipeline Configuration
141 //===----------------------------------------------------------------------===//
142 
143 namespace {
144 class M68kPassConfig : public TargetPassConfig {
145 public:
146   M68kPassConfig(M68kTargetMachine &TM, PassManagerBase &PM)
147       : TargetPassConfig(TM, PM) {}
148 
149   M68kTargetMachine &getM68kTargetMachine() const {
150     return getTM<M68kTargetMachine>();
151   }
152 
153   const M68kSubtarget &getM68kSubtarget() const {
154     return *getM68kTargetMachine().getSubtargetImpl();
155   }
156   void addIRPasses() override;
157   bool addIRTranslator() override;
158   bool addLegalizeMachineIR() override;
159   bool addRegBankSelect() override;
160   bool addGlobalInstructionSelect() override;
161   bool addInstSelector() override;
162   void addPreSched2() override;
163   void addPreEmitPass() override;
164 };
165 } // namespace
166 
167 TargetPassConfig *M68kTargetMachine::createPassConfig(PassManagerBase &PM) {
168   return new M68kPassConfig(*this, PM);
169 }
170 
171 void M68kPassConfig::addIRPasses() {
172   addPass(createAtomicExpandPass());
173   TargetPassConfig::addIRPasses();
174 }
175 
176 bool M68kPassConfig::addInstSelector() {
177   // Install an instruction selector.
178   addPass(createM68kISelDag(getM68kTargetMachine()));
179   addPass(createM68kGlobalBaseRegPass());
180   return false;
181 }
182 
183 bool M68kPassConfig::addIRTranslator() {
184   addPass(new IRTranslator());
185   return false;
186 }
187 
188 bool M68kPassConfig::addLegalizeMachineIR() {
189   addPass(new Legalizer());
190   return false;
191 }
192 
193 bool M68kPassConfig::addRegBankSelect() {
194   addPass(new RegBankSelect());
195   return false;
196 }
197 
198 bool M68kPassConfig::addGlobalInstructionSelect() {
199   addPass(new InstructionSelect());
200   return false;
201 }
202 
203 void M68kPassConfig::addPreSched2() { addPass(createM68kExpandPseudoPass()); }
204 
205 void M68kPassConfig::addPreEmitPass() {
206   addPass(createM68kCollapseMOVEMPass());
207 }
208