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