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