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