[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / M68k / M68kSubtarget.cpp
blob963e83cfbb07f2714a56761e677225776cdb35c2
1 //===-- M68kSubtarget.cpp - M68k Subtarget Information ------*- 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 implements the M68k specific subclass of TargetSubtargetInfo.
11 ///
12 //===----------------------------------------------------------------------===//
14 #include "M68kSubtarget.h"
15 #include "GlSel/M68kCallLowering.h"
16 #include "GlSel/M68kLegalizerInfo.h"
17 #include "GlSel/M68kRegisterBankInfo.h"
19 #include "M68k.h"
20 #include "M68kMachineFunction.h"
21 #include "M68kRegisterInfo.h"
22 #include "M68kTargetMachine.h"
24 #include "llvm/CodeGen/MachineJumpTableInfo.h"
25 #include "llvm/IR/Attributes.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/Support/CommandLine.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/TargetRegistry.h"
31 using namespace llvm;
33 #define DEBUG_TYPE "m68k-subtarget"
35 #define GET_SUBTARGETINFO_TARGET_DESC
36 #define GET_SUBTARGETINFO_CTOR
37 #include "M68kGenSubtargetInfo.inc"
39 extern bool FixGlobalBaseReg;
41 /// Select the M68k CPU for the given triple and cpu name.
42 static StringRef selectM68kCPU(Triple TT, StringRef CPU) {
43 if (CPU.empty() || CPU == "generic") {
44 CPU = "M68000";
46 return CPU;
49 void M68kSubtarget::anchor() {}
51 M68kSubtarget::M68kSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
52 const M68kTargetMachine &TM)
53 : M68kGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
54 UserReservedRegister(M68k::NUM_TARGET_REGS), TM(TM), TSInfo(),
55 InstrInfo(initializeSubtargetDependencies(CPU, TT, FS, TM)),
56 FrameLowering(*this, this->getStackAlignment()), TLInfo(TM, *this),
57 TargetTriple(TT) {
58 CallLoweringInfo.reset(new M68kCallLowering(*getTargetLowering()));
59 Legalizer.reset(new M68kLegalizerInfo(*this));
61 auto *RBI = new M68kRegisterBankInfo(*getRegisterInfo());
62 RegBankInfo.reset(RBI);
63 InstSelector.reset(createM68kInstructionSelector(TM, *this, *RBI));
66 const CallLowering *M68kSubtarget::getCallLowering() const {
67 return CallLoweringInfo.get();
70 InstructionSelector *M68kSubtarget::getInstructionSelector() const {
71 return InstSelector.get();
74 const LegalizerInfo *M68kSubtarget::getLegalizerInfo() const {
75 return Legalizer.get();
78 const RegisterBankInfo *M68kSubtarget::getRegBankInfo() const {
79 return RegBankInfo.get();
82 bool M68kSubtarget::isPositionIndependent() const {
83 return TM.isPositionIndependent();
86 bool M68kSubtarget::isLegalToCallImmediateAddr() const { return true; }
88 bool M68kSubtarget::abiUsesSoftFloat() const { return true; }
90 M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
91 StringRef CPU, Triple TT, StringRef FS, const M68kTargetMachine &TM) {
92 std::string CPUName = selectM68kCPU(TT, CPU).str();
94 // Parse features string.
95 ParseSubtargetFeatures(CPUName, CPUName, FS);
97 // Initialize scheduling itinerary for the specified CPU.
98 InstrItins = getInstrItineraryForCPU(CPUName);
100 stackAlignment = 8;
102 return *this;
105 //===----------------------------------------------------------------------===//
106 // Code Model
108 // Key assumptions:
109 // - Whenever possible we use pc-rel encoding since it is smaller(16 bit) than
110 // absolute(32 bit).
111 // - GOT is reachable within 16 bit offset for both Small and Medium models.
112 // - Code section is reachable within 16 bit offset for both models.
114 // ---------------------+-------------------------+--------------------------
115 // | Small | Medium
116 // +-------------------------+------------+-------------
117 // | Static | PIC | Static | PIC
118 // ---------------------+------------+------------+------------+-------------
119 // branch | pc-rel | pc-rel | pc-rel | pc-rel
120 // ---------------------+------------+------------+------------+-------------
121 // call global | @PLT | @PLT | @PLT | @PLT
122 // ---------------------+------------+------------+------------+-------------
123 // call internal | pc-rel | pc-rel | pc-rel | pc-rel
124 // ---------------------+------------+------------+------------+-------------
125 // data local | pc-rel | pc-rel | ~pc-rel | ^pc-rel
126 // ---------------------+------------+------------+------------+-------------
127 // data local big* | pc-rel | pc-rel | absolute | @GOTOFF
128 // ---------------------+------------+------------+------------+-------------
129 // data global | pc-rel | @GOTPCREL | ~pc-rel | @GOTPCREL
130 // ---------------------+------------+------------+------------+-------------
131 // data global big* | pc-rel | @GOTPCREL | absolute | @GOTPCREL
132 // ---------------------+------------+------------+------------+-------------
134 // * Big data potentially cannot be reached within 16 bit offset and requires
135 // special handling for old(x00 and x10) CPUs. Normally these symbols go into
136 // separate .ldata section which mapped after normal .data and .text, but I
137 // don't really know how this must be done for M68k atm... will try to dig
138 // this info out from GCC. For now CPUs prior to M68020 will use static ref
139 // for Static Model and @GOT based references for PIC.
141 // ~ These are absolute for older CPUs for now.
142 // ^ These are @GOTOFF for older CPUs for now.
143 //===----------------------------------------------------------------------===//
145 /// Classify a blockaddress reference for the current subtarget according to how
146 /// we should reference it in a non-pcrel context.
147 unsigned char M68kSubtarget::classifyBlockAddressReference() const {
148 // Unless we start to support Large Code Model branching is always pc-rel
149 return M68kII::MO_PC_RELATIVE_ADDRESS;
152 unsigned char
153 M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const {
154 switch (TM.getCodeModel()) {
155 default:
156 llvm_unreachable("Unsupported code model");
157 case CodeModel::Small:
158 case CodeModel::Kernel: {
159 return M68kII::MO_PC_RELATIVE_ADDRESS;
161 case CodeModel::Medium: {
162 if (isPositionIndependent()) {
163 // On M68020 and better we can fit big any data offset into dips field.
164 if (atLeastM68020()) {
165 return M68kII::MO_PC_RELATIVE_ADDRESS;
167 // Otherwise we could check the data size and make sure it will fit into
168 // 16 bit offset. For now we will be conservative and go with @GOTOFF
169 return M68kII::MO_GOTOFF;
170 } else {
171 if (atLeastM68020()) {
172 return M68kII::MO_PC_RELATIVE_ADDRESS;
174 return M68kII::MO_ABSOLUTE_ADDRESS;
180 unsigned char M68kSubtarget::classifyExternalReference(const Module &M) const {
181 if (TM.shouldAssumeDSOLocal(M, nullptr))
182 return classifyLocalReference(nullptr);
184 if (isPositionIndependent())
185 return M68kII::MO_GOTPCREL;
187 return M68kII::MO_GOT;
190 unsigned char
191 M68kSubtarget::classifyGlobalReference(const GlobalValue *GV) const {
192 return classifyGlobalReference(GV, *GV->getParent());
195 unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV,
196 const Module &M) const {
197 if (TM.shouldAssumeDSOLocal(M, GV))
198 return classifyLocalReference(GV);
200 switch (TM.getCodeModel()) {
201 default:
202 llvm_unreachable("Unsupported code model");
203 case CodeModel::Small:
204 case CodeModel::Kernel: {
205 if (isPositionIndependent())
206 return M68kII::MO_GOTPCREL;
207 return M68kII::MO_PC_RELATIVE_ADDRESS;
209 case CodeModel::Medium: {
210 if (isPositionIndependent())
211 return M68kII::MO_GOTPCREL;
213 if (atLeastM68020())
214 return M68kII::MO_PC_RELATIVE_ADDRESS;
216 return M68kII::MO_ABSOLUTE_ADDRESS;
221 unsigned M68kSubtarget::getJumpTableEncoding() const {
222 if (isPositionIndependent()) {
223 // The only time we want to use GOTOFF(used when with EK_Custom32) is when
224 // the potential delta between the jump target and table base can be larger
225 // than displacement field, which is True for older CPUs(16 bit disp)
226 // in Medium model(can have large data way beyond 16 bit).
227 if (TM.getCodeModel() == CodeModel::Medium && !atLeastM68020())
228 return MachineJumpTableInfo::EK_Custom32;
230 return MachineJumpTableInfo::EK_LabelDifference32;
233 // In non-pic modes, just use the address of a block.
234 return MachineJumpTableInfo::EK_BlockAddress;
237 unsigned char
238 M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {
239 return classifyGlobalFunctionReference(GV, *GV->getParent());
242 unsigned char
243 M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
244 const Module &M) const {
245 // local always use pc-rel referencing
246 if (TM.shouldAssumeDSOLocal(M, GV))
247 return M68kII::MO_NO_FLAG;
249 // If the function is marked as non-lazy, generate an indirect call
250 // which loads from the GOT directly. This avoids run-time overhead
251 // at the cost of eager binding.
252 auto *F = dyn_cast_or_null<Function>(GV);
253 if (F && F->hasFnAttribute(Attribute::NonLazyBind)) {
254 return M68kII::MO_GOTPCREL;
257 // otherwise linker will figure this out
258 return M68kII::MO_PLT;