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("target-cpu"); 118 Attribute FSAttr = F.getFnAttribute("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>(TargetTriple, CPU, FS, *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(createAtomicExpandPass()); 175 TargetPassConfig::addIRPasses(); 176 } 177 178 bool M68kPassConfig::addInstSelector() { 179 // Install an instruction selector. 180 addPass(createM68kISelDag(getM68kTargetMachine())); 181 addPass(createM68kGlobalBaseRegPass()); 182 return false; 183 } 184 185 bool M68kPassConfig::addIRTranslator() { 186 addPass(new IRTranslator()); 187 return false; 188 } 189 190 bool M68kPassConfig::addLegalizeMachineIR() { 191 addPass(new Legalizer()); 192 return false; 193 } 194 195 bool M68kPassConfig::addRegBankSelect() { 196 addPass(new RegBankSelect()); 197 return false; 198 } 199 200 bool M68kPassConfig::addGlobalInstructionSelect() { 201 addPass(new InstructionSelect()); 202 return false; 203 } 204 205 void M68kPassConfig::addPreSched2() { addPass(createM68kExpandPseudoPass()); } 206 207 void M68kPassConfig::addPreEmitPass() { 208 addPass(createM68kCollapseMOVEMPass()); 209 } 210