1 //===-- MipsMCExpr.cpp - Mips specific MC expression classes --------------===//
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
7 //===----------------------------------------------------------------------===//
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"
25 #define DEBUG_TYPE "mipsmcexpr"
27 const MipsMCExpr
*MipsMCExpr::create(MipsMCExpr::MipsExprKind Kind
,
28 const MCExpr
*Expr
, MCContext
&Ctx
) {
29 return new (Ctx
) MipsMCExpr(Kind
, Expr
);
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
);
37 void MipsMCExpr::printImpl(raw_ostream
&OS
, const MCAsmInfo
*MAI
) const {
43 llvm_unreachable("MEK_None and MEK_Special are invalid");
46 // MEK_DTPREL is used for marking TLS DIEExpr only
47 // and contains a regular sub-expression.
48 getSubExpr()->print(OS
, MAI
, true);
125 if (Expr
->evaluateAsAbsolute(AbsVal
))
128 Expr
->print(OS
, MAI
, true);
133 MipsMCExpr::evaluateAsRelocatableImpl(MCValue
&Res
,
134 const MCAsmLayout
*Layout
,
135 const MCFixup
*Fixup
) const {
136 // Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X))) special cases.
138 const MCExpr
*SubExpr
=
139 cast
<MipsMCExpr
>(cast
<MipsMCExpr
>(getSubExpr())->getSubExpr())
141 if (!SubExpr
->evaluateAsRelocatable(Res
, Layout
, Fixup
))
144 Res
= MCValue::get(Res
.getSymA(), Res
.getSymB(), Res
.getConstant(),
149 if (!getSubExpr()->evaluateAsRelocatable(Res
, Layout
, Fixup
))
152 if (Res
.getRefKind() != MCSymbolRefExpr::VK_None
)
155 // evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the
156 // %hi/%lo/etc. here. Fixup is a null pointer when either of these is the
158 if (Res
.isAbsolute() && Fixup
== nullptr) {
159 int64_t AbsVal
= Res
.getConstant();
163 llvm_unreachable("MEK_None and MEK_Special are invalid");
165 // MEK_DTPREL is used for marking TLS DIEExpr only
166 // and contains a regular sub-expression.
167 return getSubExpr()->evaluateAsRelocatable(Res
, Layout
, Fixup
);
188 AbsVal
= SignExtend64
<16>(AbsVal
);
192 AbsVal
= SignExtend64
<16>((AbsVal
+ 0x8000) >> 16);
195 AbsVal
= SignExtend64
<16>((AbsVal
+ 0x80008000LL
) >> 32);
198 AbsVal
= SignExtend64
<16>((AbsVal
+ 0x800080008000LL
) >> 48);
204 Res
= MCValue::get(AbsVal
);
208 // We want to defer it for relocatable expressions since the constant is
209 // applied to the whole symbol value.
211 // The value of getKind() that is given to MCValue is only intended to aid
212 // debugging when inspecting MCValue objects. It shouldn't be relied upon
213 // for decision making.
214 Res
= MCValue::get(Res
.getSymA(), Res
.getSymB(), Res
.getConstant(), getKind());
219 void MipsMCExpr::visitUsedExpr(MCStreamer
&Streamer
) const {
220 Streamer
.visitUsedExpr(*getSubExpr());
223 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr
*Expr
, MCAssembler
&Asm
) {
224 switch (Expr
->getKind()) {
226 fixELFSymbolsInTLSFixupsImpl(cast
<MipsMCExpr
>(Expr
)->getSubExpr(), Asm
);
228 case MCExpr::Constant
:
230 case MCExpr::Binary
: {
231 const MCBinaryExpr
*BE
= cast
<MCBinaryExpr
>(Expr
);
232 fixELFSymbolsInTLSFixupsImpl(BE
->getLHS(), Asm
);
233 fixELFSymbolsInTLSFixupsImpl(BE
->getRHS(), Asm
);
236 case MCExpr::SymbolRef
: {
237 // We're known to be under a TLS fixup, so any symbol should be
238 // modified. There should be only one.
239 const MCSymbolRefExpr
&SymRef
= *cast
<MCSymbolRefExpr
>(Expr
);
240 cast
<MCSymbolELF
>(SymRef
.getSymbol()).setType(ELF::STT_TLS
);
244 fixELFSymbolsInTLSFixupsImpl(cast
<MCUnaryExpr
>(Expr
)->getSubExpr(), Asm
);
249 void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler
&Asm
) const {
253 llvm_unreachable("MEK_None and MEK_Special are invalid");
272 // If we do have nested target-specific expressions, they will be in
273 // a consecutive chain.
274 if (const MipsMCExpr
*E
= dyn_cast
<const MipsMCExpr
>(getSubExpr()))
275 E
->fixELFSymbolsInTLSFixups(Asm
);
285 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm
);
290 bool MipsMCExpr::isGpOff(MipsExprKind
&Kind
) const {
291 if (getKind() == MEK_HI
|| getKind() == MEK_LO
) {
292 if (const MipsMCExpr
*S1
= dyn_cast
<const MipsMCExpr
>(getSubExpr())) {
293 if (const MipsMCExpr
*S2
= dyn_cast
<const MipsMCExpr
>(S1
->getSubExpr())) {
294 if (S1
->getKind() == MEK_NEG
&& S2
->getKind() == MEK_GPREL
) {