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