Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
35294 views
1
//===-- RISCVMCExpr.cpp - RISC-V 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
// This file contains the implementation of the assembly expression modifiers
10
// accepted by the RISC-V architecture (e.g. ":lo12:", ":gottprel_g1:", ...).
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "RISCVMCExpr.h"
15
#include "MCTargetDesc/RISCVAsmBackend.h"
16
#include "RISCVFixupKinds.h"
17
#include "llvm/BinaryFormat/ELF.h"
18
#include "llvm/MC/MCAssembler.h"
19
#include "llvm/MC/MCContext.h"
20
#include "llvm/MC/MCStreamer.h"
21
#include "llvm/MC/MCSymbolELF.h"
22
#include "llvm/MC/MCValue.h"
23
#include "llvm/Support/Casting.h"
24
#include "llvm/Support/ErrorHandling.h"
25
26
using namespace llvm;
27
28
#define DEBUG_TYPE "riscvmcexpr"
29
30
const RISCVMCExpr *RISCVMCExpr::create(const MCExpr *Expr, VariantKind Kind,
31
MCContext &Ctx) {
32
return new (Ctx) RISCVMCExpr(Expr, Kind);
33
}
34
35
void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
36
VariantKind Kind = getKind();
37
bool HasVariant = ((Kind != VK_RISCV_None) && (Kind != VK_RISCV_CALL) &&
38
(Kind != VK_RISCV_CALL_PLT));
39
40
if (HasVariant)
41
OS << '%' << getVariantKindName(getKind()) << '(';
42
Expr->print(OS, MAI);
43
if (HasVariant)
44
OS << ')';
45
}
46
47
const MCFixup *RISCVMCExpr::getPCRelHiFixup(const MCFragment **DFOut) const {
48
MCValue AUIPCLoc;
49
if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr))
50
return nullptr;
51
52
const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA();
53
if (!AUIPCSRE)
54
return nullptr;
55
56
const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol();
57
const auto *DF = dyn_cast_or_null<MCDataFragment>(AUIPCSymbol->getFragment());
58
59
if (!DF)
60
return nullptr;
61
62
uint64_t Offset = AUIPCSymbol->getOffset();
63
if (DF->getContents().size() == Offset) {
64
DF = dyn_cast_or_null<MCDataFragment>(DF->getNext());
65
if (!DF)
66
return nullptr;
67
Offset = 0;
68
}
69
70
for (const MCFixup &F : DF->getFixups()) {
71
if (F.getOffset() != Offset)
72
continue;
73
74
switch ((unsigned)F.getKind()) {
75
default:
76
continue;
77
case RISCV::fixup_riscv_got_hi20:
78
case RISCV::fixup_riscv_tls_got_hi20:
79
case RISCV::fixup_riscv_tls_gd_hi20:
80
case RISCV::fixup_riscv_pcrel_hi20:
81
case RISCV::fixup_riscv_tlsdesc_hi20:
82
if (DFOut)
83
*DFOut = DF;
84
return &F;
85
}
86
}
87
88
return nullptr;
89
}
90
91
bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
92
const MCAssembler *Asm,
93
const MCFixup *Fixup) const {
94
// Explicitly drop the layout and assembler to prevent any symbolic folding in
95
// the expression handling. This is required to preserve symbolic difference
96
// expressions to emit the paired relocations.
97
if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr))
98
return false;
99
100
Res =
101
MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
102
// Custom fixup types are not valid with symbol difference expressions.
103
return Res.getSymB() ? getKind() == VK_RISCV_None : true;
104
}
105
106
void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
107
Streamer.visitUsedExpr(*getSubExpr());
108
}
109
110
RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {
111
return StringSwitch<RISCVMCExpr::VariantKind>(name)
112
.Case("lo", VK_RISCV_LO)
113
.Case("hi", VK_RISCV_HI)
114
.Case("pcrel_lo", VK_RISCV_PCREL_LO)
115
.Case("pcrel_hi", VK_RISCV_PCREL_HI)
116
.Case("got_pcrel_hi", VK_RISCV_GOT_HI)
117
.Case("tprel_lo", VK_RISCV_TPREL_LO)
118
.Case("tprel_hi", VK_RISCV_TPREL_HI)
119
.Case("tprel_add", VK_RISCV_TPREL_ADD)
120
.Case("tls_ie_pcrel_hi", VK_RISCV_TLS_GOT_HI)
121
.Case("tls_gd_pcrel_hi", VK_RISCV_TLS_GD_HI)
122
.Case("tlsdesc_hi", VK_RISCV_TLSDESC_HI)
123
.Case("tlsdesc_load_lo", VK_RISCV_TLSDESC_LOAD_LO)
124
.Case("tlsdesc_add_lo", VK_RISCV_TLSDESC_ADD_LO)
125
.Case("tlsdesc_call", VK_RISCV_TLSDESC_CALL)
126
.Default(VK_RISCV_Invalid);
127
}
128
129
StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {
130
switch (Kind) {
131
case VK_RISCV_Invalid:
132
case VK_RISCV_None:
133
llvm_unreachable("Invalid ELF symbol kind");
134
case VK_RISCV_LO:
135
return "lo";
136
case VK_RISCV_HI:
137
return "hi";
138
case VK_RISCV_PCREL_LO:
139
return "pcrel_lo";
140
case VK_RISCV_PCREL_HI:
141
return "pcrel_hi";
142
case VK_RISCV_GOT_HI:
143
return "got_pcrel_hi";
144
case VK_RISCV_TPREL_LO:
145
return "tprel_lo";
146
case VK_RISCV_TPREL_HI:
147
return "tprel_hi";
148
case VK_RISCV_TPREL_ADD:
149
return "tprel_add";
150
case VK_RISCV_TLS_GOT_HI:
151
return "tls_ie_pcrel_hi";
152
case VK_RISCV_TLSDESC_HI:
153
return "tlsdesc_hi";
154
case VK_RISCV_TLSDESC_LOAD_LO:
155
return "tlsdesc_load_lo";
156
case VK_RISCV_TLSDESC_ADD_LO:
157
return "tlsdesc_add_lo";
158
case VK_RISCV_TLSDESC_CALL:
159
return "tlsdesc_call";
160
case VK_RISCV_TLS_GD_HI:
161
return "tls_gd_pcrel_hi";
162
case VK_RISCV_CALL:
163
return "call";
164
case VK_RISCV_CALL_PLT:
165
return "call_plt";
166
case VK_RISCV_32_PCREL:
167
return "32_pcrel";
168
}
169
llvm_unreachable("Invalid ELF symbol kind");
170
}
171
172
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
173
switch (Expr->getKind()) {
174
case MCExpr::Target:
175
llvm_unreachable("Can't handle nested target expression");
176
break;
177
case MCExpr::Constant:
178
break;
179
180
case MCExpr::Binary: {
181
const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
182
fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
183
fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
184
break;
185
}
186
187
case MCExpr::SymbolRef: {
188
// We're known to be under a TLS fixup, so any symbol should be
189
// modified. There should be only one.
190
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
191
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
192
break;
193
}
194
195
case MCExpr::Unary:
196
fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
197
break;
198
}
199
}
200
201
void RISCVMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
202
switch (getKind()) {
203
default:
204
return;
205
case VK_RISCV_TPREL_HI:
206
case VK_RISCV_TLS_GOT_HI:
207
case VK_RISCV_TLS_GD_HI:
208
case VK_RISCV_TLSDESC_HI:
209
break;
210
}
211
212
fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
213
}
214
215
bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
216
MCValue Value;
217
218
if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
219
Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI ||
220
Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD ||
221
Kind == VK_RISCV_TLS_GOT_HI || Kind == VK_RISCV_TLS_GD_HI ||
222
Kind == VK_RISCV_TLSDESC_HI || Kind == VK_RISCV_TLSDESC_LOAD_LO ||
223
Kind == VK_RISCV_TLSDESC_ADD_LO || Kind == VK_RISCV_TLSDESC_CALL ||
224
Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT)
225
return false;
226
227
if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
228
return false;
229
230
if (!Value.isAbsolute())
231
return false;
232
233
Res = evaluateAsInt64(Value.getConstant());
234
return true;
235
}
236
237
int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const {
238
switch (Kind) {
239
default:
240
llvm_unreachable("Invalid kind");
241
case VK_RISCV_LO:
242
return SignExtend64<12>(Value);
243
case VK_RISCV_HI:
244
// Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
245
return ((Value + 0x800) >> 12) & 0xfffff;
246
}
247
}
248
249