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