xref: /freebsd/contrib/llvm-project/llvm/lib/Target/M68k/M68kTargetMachine.cpp (revision 723da5d92f40a413585107f8455280ea575fe410)
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    initializeM68kDAGToDAGISelLegacyPass(*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(createAtomicExpandLegacyPass());
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