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