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