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