Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/M68k/M68kSubtarget.cpp
35266 views
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
//===----------------------------------------------------------------------===//
13
14
#include "M68kSubtarget.h"
15
#include "GISel/M68kCallLowering.h"
16
#include "GISel/M68kLegalizerInfo.h"
17
#include "GISel/M68kRegisterBankInfo.h"
18
19
#include "M68k.h"
20
#include "M68kMachineFunction.h"
21
#include "M68kRegisterInfo.h"
22
#include "M68kTargetMachine.h"
23
24
#include "llvm/CodeGen/MachineJumpTableInfo.h"
25
#include "llvm/IR/Attributes.h"
26
#include "llvm/IR/Function.h"
27
#include "llvm/MC/TargetRegistry.h"
28
#include "llvm/Support/CommandLine.h"
29
#include "llvm/Support/ErrorHandling.h"
30
31
using namespace llvm;
32
33
#define DEBUG_TYPE "m68k-subtarget"
34
35
#define GET_SUBTARGETINFO_TARGET_DESC
36
#define GET_SUBTARGETINFO_CTOR
37
#include "M68kGenSubtargetInfo.inc"
38
39
extern bool FixGlobalBaseReg;
40
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";
45
}
46
return CPU;
47
}
48
49
void M68kSubtarget::anchor() {}
50
51
M68kSubtarget::M68kSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
52
const M68kTargetMachine &TM)
53
: M68kGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), TM(TM), TSInfo(),
54
InstrInfo(initializeSubtargetDependencies(CPU, TT, FS, TM)),
55
FrameLowering(*this, this->getStackAlignment()), TLInfo(TM, *this),
56
TargetTriple(TT) {
57
CallLoweringInfo.reset(new M68kCallLowering(*getTargetLowering()));
58
Legalizer.reset(new M68kLegalizerInfo(*this));
59
60
auto *RBI = new M68kRegisterBankInfo(*getRegisterInfo());
61
RegBankInfo.reset(RBI);
62
InstSelector.reset(createM68kInstructionSelector(TM, *this, *RBI));
63
}
64
65
const CallLowering *M68kSubtarget::getCallLowering() const {
66
return CallLoweringInfo.get();
67
}
68
69
InstructionSelector *M68kSubtarget::getInstructionSelector() const {
70
return InstSelector.get();
71
}
72
73
const LegalizerInfo *M68kSubtarget::getLegalizerInfo() const {
74
return Legalizer.get();
75
}
76
77
const RegisterBankInfo *M68kSubtarget::getRegBankInfo() const {
78
return RegBankInfo.get();
79
}
80
81
bool M68kSubtarget::isPositionIndependent() const {
82
return TM.isPositionIndependent();
83
}
84
85
bool M68kSubtarget::isLegalToCallImmediateAddr() const { return true; }
86
87
M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
88
StringRef CPU, Triple TT, StringRef FS, const M68kTargetMachine &TM) {
89
std::string CPUName = selectM68kCPU(TT, CPU).str();
90
91
// Parse features string.
92
ParseSubtargetFeatures(CPUName, CPUName, FS);
93
94
// Initialize scheduling itinerary for the specified CPU.
95
InstrItins = getInstrItineraryForCPU(CPUName);
96
97
stackAlignment = 8;
98
99
return *this;
100
}
101
102
//===----------------------------------------------------------------------===//
103
// Code Model
104
//
105
// Key assumptions:
106
// - Whenever possible we use pc-rel encoding since it is smaller(16 bit) than
107
// absolute(32 bit).
108
// - GOT is reachable within 16 bit offset for both Small and Medium models.
109
// - Code section is reachable within 16 bit offset for both models.
110
//
111
// ---------------------+-------------------------+--------------------------
112
// | Small | Medium
113
// +-------------------------+------------+-------------
114
// | Static | PIC | Static | PIC
115
// ---------------------+------------+------------+------------+-------------
116
// branch | pc-rel | pc-rel | pc-rel | pc-rel
117
// ---------------------+------------+------------+------------+-------------
118
// call global | @PLT | @PLT | @PLT | @PLT
119
// ---------------------+------------+------------+------------+-------------
120
// call internal | pc-rel | pc-rel | pc-rel | pc-rel
121
// ---------------------+------------+------------+------------+-------------
122
// data local | pc-rel | pc-rel | ~pc-rel | ^pc-rel
123
// ---------------------+------------+------------+------------+-------------
124
// data local big* | pc-rel | pc-rel | absolute | @GOTOFF
125
// ---------------------+------------+------------+------------+-------------
126
// data global | pc-rel | @GOTPCREL | ~pc-rel | @GOTPCREL
127
// ---------------------+------------+------------+------------+-------------
128
// data global big* | pc-rel | @GOTPCREL | absolute | @GOTPCREL
129
// ---------------------+------------+------------+------------+-------------
130
//
131
// * Big data potentially cannot be reached within 16 bit offset and requires
132
// special handling for old(x00 and x10) CPUs. Normally these symbols go into
133
// separate .ldata section which mapped after normal .data and .text, but I
134
// don't really know how this must be done for M68k atm... will try to dig
135
// this info out from GCC. For now CPUs prior to M68020 will use static ref
136
// for Static Model and @GOT based references for PIC.
137
//
138
// ~ These are absolute for older CPUs for now.
139
// ^ These are @GOTOFF for older CPUs for now.
140
//===----------------------------------------------------------------------===//
141
142
/// Classify a blockaddress reference for the current subtarget according to how
143
/// we should reference it in a non-pcrel context.
144
unsigned char M68kSubtarget::classifyBlockAddressReference() const {
145
// Unless we start to support Large Code Model branching is always pc-rel
146
return M68kII::MO_PC_RELATIVE_ADDRESS;
147
}
148
149
unsigned char
150
M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const {
151
switch (TM.getCodeModel()) {
152
default:
153
llvm_unreachable("Unsupported code model");
154
case CodeModel::Small:
155
case CodeModel::Kernel: {
156
return M68kII::MO_PC_RELATIVE_ADDRESS;
157
}
158
case CodeModel::Medium: {
159
if (isPositionIndependent()) {
160
// On M68020 and better we can fit big any data offset into dips field.
161
if (atLeastM68020()) {
162
return M68kII::MO_PC_RELATIVE_ADDRESS;
163
}
164
// Otherwise we could check the data size and make sure it will fit into
165
// 16 bit offset. For now we will be conservative and go with @GOTOFF
166
return M68kII::MO_GOTOFF;
167
} else {
168
if (atLeastM68020()) {
169
return M68kII::MO_PC_RELATIVE_ADDRESS;
170
}
171
return M68kII::MO_ABSOLUTE_ADDRESS;
172
}
173
}
174
}
175
}
176
177
unsigned char M68kSubtarget::classifyExternalReference(const Module &M) const {
178
if (TM.shouldAssumeDSOLocal(nullptr))
179
return classifyLocalReference(nullptr);
180
181
if (isPositionIndependent())
182
return M68kII::MO_GOTPCREL;
183
184
return M68kII::MO_GOT;
185
}
186
187
unsigned char
188
M68kSubtarget::classifyGlobalReference(const GlobalValue *GV) const {
189
return classifyGlobalReference(GV, *GV->getParent());
190
}
191
192
unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV,
193
const Module &M) const {
194
if (TM.shouldAssumeDSOLocal(GV))
195
return classifyLocalReference(GV);
196
197
switch (TM.getCodeModel()) {
198
default:
199
llvm_unreachable("Unsupported code model");
200
case CodeModel::Small:
201
case CodeModel::Kernel: {
202
if (isPositionIndependent())
203
return M68kII::MO_GOTPCREL;
204
return M68kII::MO_PC_RELATIVE_ADDRESS;
205
}
206
case CodeModel::Medium: {
207
if (isPositionIndependent())
208
return M68kII::MO_GOTPCREL;
209
210
if (atLeastM68020())
211
return M68kII::MO_PC_RELATIVE_ADDRESS;
212
213
return M68kII::MO_ABSOLUTE_ADDRESS;
214
}
215
}
216
}
217
218
unsigned M68kSubtarget::getJumpTableEncoding() const {
219
if (isPositionIndependent()) {
220
// The only time we want to use GOTOFF(used when with EK_Custom32) is when
221
// the potential delta between the jump target and table base can be larger
222
// than displacement field, which is True for older CPUs(16 bit disp)
223
// in Medium model(can have large data way beyond 16 bit).
224
if (TM.getCodeModel() == CodeModel::Medium && !atLeastM68020())
225
return MachineJumpTableInfo::EK_Custom32;
226
227
return MachineJumpTableInfo::EK_LabelDifference32;
228
}
229
230
// In non-pic modes, just use the address of a block.
231
return MachineJumpTableInfo::EK_BlockAddress;
232
}
233
234
unsigned char
235
M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {
236
return classifyGlobalFunctionReference(GV, *GV->getParent());
237
}
238
239
unsigned char
240
M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
241
const Module &M) const {
242
// local always use pc-rel referencing
243
if (TM.shouldAssumeDSOLocal(GV))
244
return M68kII::MO_NO_FLAG;
245
246
// If the function is marked as non-lazy, generate an indirect call
247
// which loads from the GOT directly. This avoids run-time overhead
248
// at the cost of eager binding.
249
auto *F = dyn_cast_or_null<Function>(GV);
250
if (F && F->hasFnAttribute(Attribute::NonLazyBind)) {
251
return M68kII::MO_GOTPCREL;
252
}
253
254
// Ensure that we don't emit PLT relocations when in non-pic modes.
255
return isPositionIndependent() ? M68kII::MO_PLT : M68kII::MO_ABSOLUTE_ADDRESS;
256
}
257
258