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 initializeM68kAsmPrinterPass(*PR); 41 initializeM68kDAGToDAGISelLegacyPass(*PR); 42 initializeM68kExpandPseudoPass(*PR); 43 initializeM68kGlobalBaseRegPass(*PR); 44 initializeM68kCollapseMOVEMPass(*PR); 45 } 46 47 namespace { 48 49 std::string computeDataLayout(const Triple &TT, StringRef CPU, 50 const TargetOptions &Options) { 51 std::string Ret = ""; 52 // M68k is Big Endian 53 Ret += "E"; 54 55 // FIXME how to wire it with the used object format? 56 Ret += "-m:e"; 57 58 // M68k pointers are always 32 bit wide even for 16-bit CPUs. 59 // The ABI only specifies 16-bit alignment. 60 // On at least the 68020+ with a 32-bit bus, there is a performance benefit 61 // to having 32-bit alignment. 62 Ret += "-p:32:16:32"; 63 64 // Bytes do not require special alignment, words are word aligned and 65 // long words are word aligned at minimum. 66 Ret += "-i8:8:8-i16:16:16-i32:16:32"; 67 68 // FIXME no floats at the moment 69 70 // The registers can hold 8, 16, 32 bits 71 Ret += "-n8:16:32"; 72 73 Ret += "-a:0:16-S16"; 74 75 return Ret; 76 } 77 78 Reloc::Model getEffectiveRelocModel(const Triple &TT, 79 std::optional<Reloc::Model> RM) { 80 // If not defined we default to static 81 if (!RM.has_value()) 82 return Reloc::Static; 83 84 return *RM; 85 } 86 87 CodeModel::Model getEffectiveCodeModel(std::optional<CodeModel::Model> CM, 88 bool JIT) { 89 if (!CM) { 90 return CodeModel::Small; 91 } else if (CM == CodeModel::Kernel) { 92 llvm_unreachable("Kernel code model is not implemented yet"); 93 } 94 return CM.value(); 95 } 96 } // end anonymous namespace 97 98 M68kTargetMachine::M68kTargetMachine(const Target &T, const Triple &TT, 99 StringRef CPU, StringRef FS, 100 const TargetOptions &Options, 101 std::optional<Reloc::Model> RM, 102 std::optional<CodeModel::Model> CM, 103 CodeGenOptLevel OL, bool JIT) 104 : CodeGenTargetMachineImpl(T, computeDataLayout(TT, CPU, Options), TT, CPU, 105 FS, Options, getEffectiveRelocModel(TT, RM), 106 ::getEffectiveCodeModel(CM, JIT), OL), 107 TLOF(std::make_unique<M68kELFTargetObjectFile>()), 108 Subtarget(TT, CPU, FS, *this) { 109 initAsmInfo(); 110 } 111 112 M68kTargetMachine::~M68kTargetMachine() {} 113 114 const M68kSubtarget * 115 M68kTargetMachine::getSubtargetImpl(const Function &F) const { 116 Attribute CPUAttr = F.getFnAttribute("target-cpu"); 117 Attribute FSAttr = F.getFnAttribute("target-features"); 118 119 auto CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 120 auto FS = FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 121 122 auto &I = SubtargetMap[CPU + FS]; 123 if (!I) { 124 // This needs to be done before we create a new subtarget since any 125 // creation will depend on the TM and the code generation flags on the 126 // function that reside in TargetOptions. 127 resetTargetOptions(F); 128 I = std::make_unique<M68kSubtarget>(TargetTriple, CPU, FS, *this); 129 } 130 return I.get(); 131 } 132 133 MachineFunctionInfo *M68kTargetMachine::createMachineFunctionInfo( 134 BumpPtrAllocator &Allocator, const Function &F, 135 const TargetSubtargetInfo *STI) const { 136 return M68kMachineFunctionInfo::create<M68kMachineFunctionInfo>(Allocator, F, 137 STI); 138 } 139 140 //===----------------------------------------------------------------------===// 141 // Pass Pipeline Configuration 142 //===----------------------------------------------------------------------===// 143 144 namespace { 145 class M68kPassConfig : public TargetPassConfig { 146 public: 147 M68kPassConfig(M68kTargetMachine &TM, PassManagerBase &PM) 148 : TargetPassConfig(TM, PM) {} 149 150 M68kTargetMachine &getM68kTargetMachine() const { 151 return getTM<M68kTargetMachine>(); 152 } 153 154 const M68kSubtarget &getM68kSubtarget() const { 155 return *getM68kTargetMachine().getSubtargetImpl(); 156 } 157 void addIRPasses() override; 158 bool addIRTranslator() override; 159 bool addLegalizeMachineIR() override; 160 bool addRegBankSelect() override; 161 bool addGlobalInstructionSelect() override; 162 bool addInstSelector() override; 163 void addPreSched2() override; 164 void addPreEmitPass() override; 165 }; 166 } // namespace 167 168 TargetPassConfig *M68kTargetMachine::createPassConfig(PassManagerBase &PM) { 169 return new M68kPassConfig(*this, PM); 170 } 171 172 void M68kPassConfig::addIRPasses() { 173 addPass(createAtomicExpandLegacyPass()); 174 TargetPassConfig::addIRPasses(); 175 } 176 177 bool M68kPassConfig::addInstSelector() { 178 // Install an instruction selector. 179 addPass(createM68kISelDag(getM68kTargetMachine())); 180 addPass(createM68kGlobalBaseRegPass()); 181 return false; 182 } 183 184 bool M68kPassConfig::addIRTranslator() { 185 addPass(new IRTranslator()); 186 return false; 187 } 188 189 bool M68kPassConfig::addLegalizeMachineIR() { 190 addPass(new Legalizer()); 191 return false; 192 } 193 194 bool M68kPassConfig::addRegBankSelect() { 195 addPass(new RegBankSelect()); 196 return false; 197 } 198 199 bool M68kPassConfig::addGlobalInstructionSelect() { 200 addPass(new InstructionSelect()); 201 return false; 202 } 203 204 void M68kPassConfig::addPreSched2() { addPass(createM68kExpandPseudoPass()); } 205 206 void M68kPassConfig::addPreEmitPass() { 207 addPass(createM68kCollapseMOVEMPass()); 208 } 209