Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
35294 views
1
//===-- MipsMCExpr.cpp - Mips specific MC expression classes --------------===//
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
#include "MipsMCExpr.h"
10
#include "llvm/BinaryFormat/ELF.h"
11
#include "llvm/MC/MCAsmInfo.h"
12
#include "llvm/MC/MCAssembler.h"
13
#include "llvm/MC/MCContext.h"
14
#include "llvm/MC/MCStreamer.h"
15
#include "llvm/MC/MCSymbolELF.h"
16
#include "llvm/MC/MCValue.h"
17
#include "llvm/Support/Casting.h"
18
#include "llvm/Support/ErrorHandling.h"
19
#include "llvm/Support/MathExtras.h"
20
#include "llvm/Support/raw_ostream.h"
21
#include <cstdint>
22
23
using namespace llvm;
24
25
#define DEBUG_TYPE "mipsmcexpr"
26
27
const MipsMCExpr *MipsMCExpr::create(MipsMCExpr::MipsExprKind Kind,
28
const MCExpr *Expr, MCContext &Ctx) {
29
return new (Ctx) MipsMCExpr(Kind, Expr);
30
}
31
32
const MipsMCExpr *MipsMCExpr::createGpOff(MipsMCExpr::MipsExprKind Kind,
33
const MCExpr *Expr, MCContext &Ctx) {
34
return create(Kind, create(MEK_NEG, create(MEK_GPREL, Expr, Ctx), Ctx), Ctx);
35
}
36
37
void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
38
int64_t AbsVal;
39
40
switch (Kind) {
41
case MEK_None:
42
case MEK_Special:
43
llvm_unreachable("MEK_None and MEK_Special are invalid");
44
break;
45
case MEK_DTPREL:
46
// MEK_DTPREL is used for marking TLS DIEExpr only
47
// and contains a regular sub-expression.
48
getSubExpr()->print(OS, MAI, true);
49
return;
50
case MEK_CALL_HI16:
51
OS << "%call_hi";
52
break;
53
case MEK_CALL_LO16:
54
OS << "%call_lo";
55
break;
56
case MEK_DTPREL_HI:
57
OS << "%dtprel_hi";
58
break;
59
case MEK_DTPREL_LO:
60
OS << "%dtprel_lo";
61
break;
62
case MEK_GOT:
63
OS << "%got";
64
break;
65
case MEK_GOTTPREL:
66
OS << "%gottprel";
67
break;
68
case MEK_GOT_CALL:
69
OS << "%call16";
70
break;
71
case MEK_GOT_DISP:
72
OS << "%got_disp";
73
break;
74
case MEK_GOT_HI16:
75
OS << "%got_hi";
76
break;
77
case MEK_GOT_LO16:
78
OS << "%got_lo";
79
break;
80
case MEK_GOT_PAGE:
81
OS << "%got_page";
82
break;
83
case MEK_GOT_OFST:
84
OS << "%got_ofst";
85
break;
86
case MEK_GPREL:
87
OS << "%gp_rel";
88
break;
89
case MEK_HI:
90
OS << "%hi";
91
break;
92
case MEK_HIGHER:
93
OS << "%higher";
94
break;
95
case MEK_HIGHEST:
96
OS << "%highest";
97
break;
98
case MEK_LO:
99
OS << "%lo";
100
break;
101
case MEK_NEG:
102
OS << "%neg";
103
break;
104
case MEK_PCREL_HI16:
105
OS << "%pcrel_hi";
106
break;
107
case MEK_PCREL_LO16:
108
OS << "%pcrel_lo";
109
break;
110
case MEK_TLSGD:
111
OS << "%tlsgd";
112
break;
113
case MEK_TLSLDM:
114
OS << "%tlsldm";
115
break;
116
case MEK_TPREL_HI:
117
OS << "%tprel_hi";
118
break;
119
case MEK_TPREL_LO:
120
OS << "%tprel_lo";
121
break;
122
}
123
124
OS << '(';
125
if (Expr->evaluateAsAbsolute(AbsVal))
126
OS << AbsVal;
127
else
128
Expr->print(OS, MAI, true);
129
OS << ')';
130
}
131
132
bool MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
133
const MCFixup *Fixup) const {
134
// Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X))) special cases.
135
if (isGpOff()) {
136
const MCExpr *SubExpr =
137
cast<MipsMCExpr>(cast<MipsMCExpr>(getSubExpr())->getSubExpr())
138
->getSubExpr();
139
if (!SubExpr->evaluateAsRelocatable(Res, Asm, Fixup))
140
return false;
141
142
Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(),
143
MEK_Special);
144
return true;
145
}
146
147
if (!getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup))
148
return false;
149
150
if (Res.getRefKind() != MCSymbolRefExpr::VK_None)
151
return false;
152
153
// evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the
154
// %hi/%lo/etc. here. Fixup is a null pointer when either of these is the
155
// caller.
156
if (Res.isAbsolute() && Fixup == nullptr) {
157
int64_t AbsVal = Res.getConstant();
158
switch (Kind) {
159
case MEK_None:
160
case MEK_Special:
161
llvm_unreachable("MEK_None and MEK_Special are invalid");
162
case MEK_DTPREL:
163
// MEK_DTPREL is used for marking TLS DIEExpr only
164
// and contains a regular sub-expression.
165
return getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup);
166
case MEK_DTPREL_HI:
167
case MEK_DTPREL_LO:
168
case MEK_GOT:
169
case MEK_GOTTPREL:
170
case MEK_GOT_CALL:
171
case MEK_GOT_DISP:
172
case MEK_GOT_HI16:
173
case MEK_GOT_LO16:
174
case MEK_GOT_OFST:
175
case MEK_GOT_PAGE:
176
case MEK_GPREL:
177
case MEK_PCREL_HI16:
178
case MEK_PCREL_LO16:
179
case MEK_TLSGD:
180
case MEK_TLSLDM:
181
case MEK_TPREL_HI:
182
case MEK_TPREL_LO:
183
return false;
184
case MEK_LO:
185
case MEK_CALL_LO16:
186
AbsVal = SignExtend64<16>(AbsVal);
187
break;
188
case MEK_CALL_HI16:
189
case MEK_HI:
190
AbsVal = SignExtend64<16>((AbsVal + 0x8000) >> 16);
191
break;
192
case MEK_HIGHER:
193
AbsVal = SignExtend64<16>((AbsVal + 0x80008000LL) >> 32);
194
break;
195
case MEK_HIGHEST:
196
AbsVal = SignExtend64<16>((AbsVal + 0x800080008000LL) >> 48);
197
break;
198
case MEK_NEG:
199
AbsVal = -AbsVal;
200
break;
201
}
202
Res = MCValue::get(AbsVal);
203
return true;
204
}
205
206
// We want to defer it for relocatable expressions since the constant is
207
// applied to the whole symbol value.
208
//
209
// The value of getKind() that is given to MCValue is only intended to aid
210
// debugging when inspecting MCValue objects. It shouldn't be relied upon
211
// for decision making.
212
Res =
213
MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
214
215
return true;
216
}
217
218
void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
219
Streamer.visitUsedExpr(*getSubExpr());
220
}
221
222
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
223
switch (Expr->getKind()) {
224
case MCExpr::Target:
225
fixELFSymbolsInTLSFixupsImpl(cast<MipsMCExpr>(Expr)->getSubExpr(), Asm);
226
break;
227
case MCExpr::Constant:
228
break;
229
case MCExpr::Binary: {
230
const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
231
fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
232
fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
233
break;
234
}
235
case MCExpr::SymbolRef: {
236
// We're known to be under a TLS fixup, so any symbol should be
237
// modified. There should be only one.
238
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
239
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
240
break;
241
}
242
case MCExpr::Unary:
243
fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
244
break;
245
}
246
}
247
248
void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
249
switch (getKind()) {
250
case MEK_None:
251
case MEK_Special:
252
llvm_unreachable("MEK_None and MEK_Special are invalid");
253
break;
254
case MEK_CALL_HI16:
255
case MEK_CALL_LO16:
256
case MEK_GOT:
257
case MEK_GOT_CALL:
258
case MEK_GOT_DISP:
259
case MEK_GOT_HI16:
260
case MEK_GOT_LO16:
261
case MEK_GOT_OFST:
262
case MEK_GOT_PAGE:
263
case MEK_GPREL:
264
case MEK_HI:
265
case MEK_HIGHER:
266
case MEK_HIGHEST:
267
case MEK_LO:
268
case MEK_NEG:
269
case MEK_PCREL_HI16:
270
case MEK_PCREL_LO16:
271
// If we do have nested target-specific expressions, they will be in
272
// a consecutive chain.
273
if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr()))
274
E->fixELFSymbolsInTLSFixups(Asm);
275
break;
276
case MEK_DTPREL:
277
case MEK_DTPREL_HI:
278
case MEK_DTPREL_LO:
279
case MEK_TLSLDM:
280
case MEK_TLSGD:
281
case MEK_GOTTPREL:
282
case MEK_TPREL_HI:
283
case MEK_TPREL_LO:
284
fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
285
break;
286
}
287
}
288
289
bool MipsMCExpr::isGpOff(MipsExprKind &Kind) const {
290
if (getKind() == MEK_HI || getKind() == MEK_LO) {
291
if (const MipsMCExpr *S1 = dyn_cast<const MipsMCExpr>(getSubExpr())) {
292
if (const MipsMCExpr *S2 = dyn_cast<const MipsMCExpr>(S1->getSubExpr())) {
293
if (S1->getKind() == MEK_NEG && S2->getKind() == MEK_GPREL) {
294
Kind = getKind();
295
return true;
296
}
297
}
298
}
299
}
300
return false;
301
}
302
303