/src/keystone/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
Line | Count | Source |
1 | | //===-- RISCVMCExpr.cpp - RISCV 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 RISCV architecture (e.g. ":lo12:", ":gottprel_g1:", ...). |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "RISCVMCExpr.h" |
15 | | #include "MCTargetDesc/RISCVAsmBackend.h" |
16 | | #include "RISCV.h" |
17 | | #include "RISCVFixupKinds.h" |
18 | | #include "llvm/Support/ELF.h" |
19 | | #include "llvm/MC/MCAsmLayout.h" |
20 | | #include "llvm/MC/MCAssembler.h" |
21 | | #include "llvm/MC/MCContext.h" |
22 | | #include "llvm/MC/MCStreamer.h" |
23 | | #include "llvm/MC/MCSymbolELF.h" |
24 | | #include "llvm/MC/MCValue.h" |
25 | | #include "llvm/Support/ErrorHandling.h" |
26 | | |
27 | | using namespace llvm_ks; |
28 | | |
29 | | #define DEBUG_TYPE "riscvmcexpr" |
30 | | |
31 | | const RISCVMCExpr *RISCVMCExpr::create(const MCExpr *Expr, VariantKind Kind, |
32 | 90 | MCContext &Ctx) { |
33 | 90 | return new (Ctx) RISCVMCExpr(Expr, Kind); |
34 | 90 | } |
35 | | |
36 | 0 | void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { |
37 | 0 | VariantKind Kind = getKind(); |
38 | 0 | bool HasVariant = ((Kind != VK_RISCV_None) && (Kind != VK_RISCV_CALL) && |
39 | 0 | (Kind != VK_RISCV_CALL_PLT)); |
40 | |
|
41 | 0 | if (HasVariant) |
42 | 0 | OS << '%' << getVariantKindName(getKind()) << '('; |
43 | 0 | Expr->print(OS, MAI); |
44 | 0 | if (Kind == VK_RISCV_CALL_PLT) |
45 | 0 | OS << "@plt"; |
46 | 0 | if (HasVariant) |
47 | 0 | OS << ')'; |
48 | 0 | } |
49 | | |
50 | 0 | const MCFixup *RISCVMCExpr::getPCRelHiFixup() const { |
51 | 0 | MCValue AUIPCLoc; |
52 | 0 | if (!getSubExpr()->evaluateAsRelocatable(AUIPCLoc, nullptr, nullptr)) |
53 | 0 | return nullptr; |
54 | | |
55 | 0 | const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA(); |
56 | 0 | if (!AUIPCSRE) |
57 | 0 | return nullptr; |
58 | | |
59 | 0 | const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol(); |
60 | 0 | const auto *DF = dyn_cast_or_null<MCDataFragment>(AUIPCSymbol->getFragment()); |
61 | |
|
62 | 0 | if (!DF) |
63 | 0 | return nullptr; |
64 | | |
65 | 0 | uint64_t Offset = AUIPCSymbol->getOffset(); |
66 | 0 | if (DF->getContents().size() == Offset) { |
67 | 0 | DF = dyn_cast_or_null<MCDataFragment>(DF->getNextNode()); |
68 | 0 | if (!DF) |
69 | 0 | return nullptr; |
70 | 0 | Offset = 0; |
71 | 0 | } |
72 | | |
73 | 0 | for (const MCFixup &F : DF->getFixups()) { |
74 | 0 | if (F.getOffset() != Offset) |
75 | 0 | continue; |
76 | | |
77 | 0 | switch ((unsigned)F.getKind()) { |
78 | 0 | default: |
79 | 0 | continue; |
80 | 0 | case RISCV::fixup_riscv_got_hi20: |
81 | 0 | case RISCV::fixup_riscv_tls_got_hi20: |
82 | 0 | case RISCV::fixup_riscv_tls_gd_hi20: |
83 | 0 | case RISCV::fixup_riscv_pcrel_hi20: |
84 | 0 | return &F; |
85 | 0 | } |
86 | 0 | } |
87 | | |
88 | 0 | return nullptr; |
89 | 0 | } |
90 | | |
91 | | bool RISCVMCExpr::evaluatePCRelLo(MCValue &Res, const MCAsmLayout *Layout, |
92 | 0 | const MCFixup *Fixup) const { |
93 | | // VK_RISCV_PCREL_LO has to be handled specially. The MCExpr inside is |
94 | | // actually the location of a auipc instruction with a VK_RISCV_PCREL_HI fixup |
95 | | // pointing to the real target. We need to generate an MCValue in the form of |
96 | | // (<real target> + <offset from this fixup to the auipc fixup>). The Fixup |
97 | | // is pcrel relative to the VK_RISCV_PCREL_LO fixup, so we need to add the |
98 | | // offset to the VK_RISCV_PCREL_HI Fixup from VK_RISCV_PCREL_LO to correct. |
99 | | |
100 | | // Don't try to evaluate if the fixup will be forced as a relocation (e.g. |
101 | | // as linker relaxation is enabled). If we evaluated pcrel_lo in this case, |
102 | | // the modified fixup will be converted into a relocation that no longer |
103 | | // points to the pcrel_hi as the linker requires. |
104 | 0 | auto &RAB = |
105 | 0 | static_cast<RISCVAsmBackend &>(Layout->getAssembler().getBackend()); |
106 | 0 | if (RAB.willForceRelocations()) |
107 | 0 | return false; |
108 | | |
109 | 0 | MCValue AUIPCLoc; |
110 | 0 | if (!getSubExpr()->evaluateAsValue(AUIPCLoc, *Layout)) |
111 | 0 | return false; |
112 | | |
113 | 0 | const MCSymbolRefExpr *AUIPCSRE = AUIPCLoc.getSymA(); |
114 | | // Don't try to evaluate %pcrel_hi/%pcrel_lo pairs that cross fragment |
115 | | // boundries. |
116 | 0 | if (!AUIPCSRE || |
117 | 0 | findAssociatedFragment() != AUIPCSRE->findAssociatedFragment()) |
118 | 0 | return false; |
119 | | |
120 | 0 | const MCSymbol *AUIPCSymbol = &AUIPCSRE->getSymbol(); |
121 | 0 | if (!AUIPCSymbol) |
122 | 0 | return false; |
123 | | |
124 | 0 | const MCFixup *TargetFixup = getPCRelHiFixup(); |
125 | 0 | if (!TargetFixup) |
126 | 0 | return false; |
127 | | |
128 | 0 | if ((unsigned)TargetFixup->getKind() != RISCV::fixup_riscv_pcrel_hi20) |
129 | 0 | return false; |
130 | | |
131 | 0 | MCValue Target; |
132 | 0 | if (!TargetFixup->getValue()->evaluateAsValue(Target, *Layout)) |
133 | 0 | return false; |
134 | | |
135 | 0 | if (!Target.getSymA() || !Target.getSymA()->getSymbol().isInSection()) |
136 | 0 | return false; |
137 | | |
138 | 0 | if (&Target.getSymA()->getSymbol().getSection() != |
139 | 0 | findAssociatedFragment()->getParent()) |
140 | 0 | return false; |
141 | | |
142 | 0 | uint64_t AUIPCOffset = AUIPCSymbol->getOffset(); |
143 | |
|
144 | 0 | Res = MCValue::get(Target.getSymA(), nullptr, |
145 | 0 | Target.getConstant() + (Fixup->getOffset() - AUIPCOffset)); |
146 | 0 | return true; |
147 | 0 | } |
148 | | |
149 | | bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res, |
150 | | const MCAsmLayout *Layout, |
151 | 7 | const MCFixup *Fixup) const { |
152 | 7 | if (Kind == VK_RISCV_PCREL_LO && evaluatePCRelLo(Res, Layout, Fixup)) |
153 | 0 | return true; |
154 | | |
155 | 7 | if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) |
156 | 0 | return false; |
157 | | |
158 | | // Some custom fixup types are not valid with symbol difference expressions |
159 | 7 | if (Res.getSymA() && Res.getSymB()) { |
160 | 0 | switch (getKind()) { |
161 | 0 | default: |
162 | 0 | return true; |
163 | 0 | case VK_RISCV_LO: |
164 | 0 | case VK_RISCV_HI: |
165 | 0 | case VK_RISCV_PCREL_LO: |
166 | 0 | case VK_RISCV_PCREL_HI: |
167 | 0 | case VK_RISCV_GOT_HI: |
168 | 0 | case VK_RISCV_TPREL_LO: |
169 | 0 | case VK_RISCV_TPREL_HI: |
170 | 0 | case VK_RISCV_TPREL_ADD: |
171 | 0 | case VK_RISCV_TLS_GOT_HI: |
172 | 0 | case VK_RISCV_TLS_GD_HI: |
173 | 0 | return false; |
174 | 0 | } |
175 | 0 | } |
176 | | |
177 | 7 | return true; |
178 | 7 | } |
179 | | |
180 | 87 | void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const { |
181 | 87 | Streamer.visitUsedExpr(*getSubExpr()); |
182 | 87 | } |
183 | | |
184 | 195 | RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) { |
185 | 195 | return StringSwitch<RISCVMCExpr::VariantKind>(name) |
186 | 195 | .Case("lo", VK_RISCV_LO) |
187 | 195 | .Case("hi", VK_RISCV_HI) |
188 | 195 | .Case("pcrel_lo", VK_RISCV_PCREL_LO) |
189 | 195 | .Case("pcrel_hi", VK_RISCV_PCREL_HI) |
190 | 195 | .Case("got_pcrel_hi", VK_RISCV_GOT_HI) |
191 | 195 | .Case("tprel_lo", VK_RISCV_TPREL_LO) |
192 | 195 | .Case("tprel_hi", VK_RISCV_TPREL_HI) |
193 | 195 | .Case("tprel_add", VK_RISCV_TPREL_ADD) |
194 | 195 | .Case("tls_ie_pcrel_hi", VK_RISCV_TLS_GOT_HI) |
195 | 195 | .Case("tls_gd_pcrel_hi", VK_RISCV_TLS_GD_HI) |
196 | 195 | .Default(VK_RISCV_Invalid); |
197 | 195 | } |
198 | | |
199 | 0 | StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) { |
200 | 0 | switch (Kind) { |
201 | 0 | default: |
202 | 0 | llvm_unreachable("Invalid ELF symbol kind"); |
203 | 0 | case VK_RISCV_LO: |
204 | 0 | return "lo"; |
205 | 0 | case VK_RISCV_HI: |
206 | 0 | return "hi"; |
207 | 0 | case VK_RISCV_PCREL_LO: |
208 | 0 | return "pcrel_lo"; |
209 | 0 | case VK_RISCV_PCREL_HI: |
210 | 0 | return "pcrel_hi"; |
211 | 0 | case VK_RISCV_GOT_HI: |
212 | 0 | return "got_pcrel_hi"; |
213 | 0 | case VK_RISCV_TPREL_LO: |
214 | 0 | return "tprel_lo"; |
215 | 0 | case VK_RISCV_TPREL_HI: |
216 | 0 | return "tprel_hi"; |
217 | 0 | case VK_RISCV_TPREL_ADD: |
218 | 0 | return "tprel_add"; |
219 | 0 | case VK_RISCV_TLS_GOT_HI: |
220 | 0 | return "tls_ie_pcrel_hi"; |
221 | 0 | case VK_RISCV_TLS_GD_HI: |
222 | 0 | return "tls_gd_pcrel_hi"; |
223 | 0 | } |
224 | 0 | } |
225 | | |
226 | 0 | static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { |
227 | 0 | switch (Expr->getKind()) { |
228 | 0 | case MCExpr::Target: |
229 | 0 | llvm_unreachable("Can't handle nested target expression"); |
230 | 0 | break; |
231 | 0 | case MCExpr::Constant: |
232 | 0 | break; |
233 | | |
234 | 0 | case MCExpr::Binary: { |
235 | 0 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); |
236 | 0 | fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); |
237 | 0 | fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); |
238 | 0 | break; |
239 | 0 | } |
240 | | |
241 | 0 | case MCExpr::SymbolRef: { |
242 | | // We're known to be under a TLS fixup, so any symbol should be |
243 | | // modified. There should be only one. |
244 | 0 | const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); |
245 | 0 | cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); |
246 | 0 | break; |
247 | 0 | } |
248 | | |
249 | 0 | case MCExpr::Unary: |
250 | 0 | fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); |
251 | 0 | break; |
252 | 0 | } |
253 | 0 | } |
254 | | |
255 | 87 | void RISCVMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { |
256 | 87 | switch (getKind()) { |
257 | 87 | default: |
258 | 87 | return; |
259 | 87 | case VK_RISCV_TPREL_HI: |
260 | 0 | case VK_RISCV_TLS_GOT_HI: |
261 | 0 | case VK_RISCV_TLS_GD_HI: |
262 | 0 | break; |
263 | 87 | } |
264 | | |
265 | 0 | fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); |
266 | 0 | } |
267 | | |
268 | 94 | bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const { |
269 | 94 | MCValue Value; |
270 | | |
271 | 94 | if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO || |
272 | 94 | Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_TPREL_HI || |
273 | 94 | Kind == VK_RISCV_TPREL_LO || Kind == VK_RISCV_TPREL_ADD || |
274 | 94 | Kind == VK_RISCV_TLS_GOT_HI || Kind == VK_RISCV_TLS_GD_HI || |
275 | 94 | Kind == VK_RISCV_CALL || Kind == VK_RISCV_CALL_PLT) |
276 | 94 | return false; |
277 | | |
278 | 0 | if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr)) |
279 | 0 | return false; |
280 | | |
281 | 0 | if (!Value.isAbsolute()) |
282 | 0 | return false; |
283 | | |
284 | 0 | Res = evaluateAsInt64(Value.getConstant()); |
285 | 0 | return true; |
286 | 0 | } |
287 | | |
288 | 0 | int64_t RISCVMCExpr::evaluateAsInt64(int64_t Value) const { |
289 | 0 | switch (Kind) { |
290 | 0 | default: |
291 | 0 | llvm_unreachable("Invalid kind"); |
292 | 0 | case VK_RISCV_LO: |
293 | 0 | return SignExtend64<12>(Value); |
294 | 0 | case VK_RISCV_HI: |
295 | | // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative. |
296 | 0 | return ((Value + 0x800) >> 12) & 0xfffff; |
297 | 0 | } |
298 | 0 | } |