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