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