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 31 extern "C" void LLVMInitializeM68kTarget() { 32 RegisterTargetMachine<M68kTargetMachine> X(getTheM68kTarget()); 33 } 34 35 namespace { 36 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 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 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 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 99 M68kTargetMachine::~M68kTargetMachine() {} 100 101 const M68kSubtarget * 102 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: 127 M68kPassConfig(M68kTargetMachine &TM, PassManagerBase &PM) 128 : TargetPassConfig(TM, PM) {} 129 130 M68kTargetMachine &getM68kTargetMachine() const { 131 return getTM<M68kTargetMachine>(); 132 } 133 134 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 144 TargetPassConfig *M68kTargetMachine::createPassConfig(PassManagerBase &PM) { 145 return new M68kPassConfig(*this, PM); 146 } 147 148 bool M68kPassConfig::addInstSelector() { 149 // Install an instruction selector. 150 addPass(createM68kISelDag(getM68kTargetMachine())); 151 addPass(createM68kGlobalBaseRegPass()); 152 return false; 153 } 154 155 void M68kPassConfig::addPreSched2() { addPass(createM68kExpandPseudoPass()); } 156 157 void M68kPassConfig::addPreEmitPass() { 158 addPass(createM68kCollapseMOVEMPass()); 159 } 160