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