1 //===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #define DEBUG_TYPE "mcexpr"
11 #include "llvm/MC/MCExpr.h"
12 #include "llvm/ADT/Statistic.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/MC/MCAsmLayout.h"
15 #include "llvm/MC/MCAssembler.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCSymbol.h"
18 #include "llvm/MC/MCValue.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/Target/TargetAsmBackend.h"
26 STATISTIC(MCExprEvaluate
, "Number of MCExpr evaluations");
30 void MCExpr::print(raw_ostream
&OS
) const {
33 return cast
<MCTargetExpr
>(this)->PrintImpl(OS
);
34 case MCExpr::Constant
:
35 OS
<< cast
<MCConstantExpr
>(*this).getValue();
38 case MCExpr::SymbolRef
: {
39 const MCSymbolRefExpr
&SRE
= cast
<MCSymbolRefExpr
>(*this);
40 const MCSymbol
&Sym
= SRE
.getSymbol();
41 // Parenthesize names that start with $ so that they don't look like
43 bool UseParens
= Sym
.getName()[0] == '$';
45 if (SRE
.getKind() == MCSymbolRefExpr::VK_PPC_HA16
||
46 SRE
.getKind() == MCSymbolRefExpr::VK_PPC_LO16
) {
47 OS
<< MCSymbolRefExpr::getVariantKindName(SRE
.getKind());
52 OS
<< '(' << Sym
<< ')';
56 if (SRE
.getKind() == MCSymbolRefExpr::VK_ARM_PLT
||
57 SRE
.getKind() == MCSymbolRefExpr::VK_ARM_TLSGD
||
58 SRE
.getKind() == MCSymbolRefExpr::VK_ARM_GOT
||
59 SRE
.getKind() == MCSymbolRefExpr::VK_ARM_GOTOFF
||
60 SRE
.getKind() == MCSymbolRefExpr::VK_ARM_TPOFF
||
61 SRE
.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF
)
62 OS
<< MCSymbolRefExpr::getVariantKindName(SRE
.getKind());
63 else if (SRE
.getKind() != MCSymbolRefExpr::VK_None
&&
64 SRE
.getKind() != MCSymbolRefExpr::VK_PPC_HA16
&&
65 SRE
.getKind() != MCSymbolRefExpr::VK_PPC_LO16
)
66 OS
<< '@' << MCSymbolRefExpr::getVariantKindName(SRE
.getKind());
72 const MCUnaryExpr
&UE
= cast
<MCUnaryExpr
>(*this);
73 switch (UE
.getOpcode()) {
74 default: assert(0 && "Invalid opcode!");
75 case MCUnaryExpr::LNot
: OS
<< '!'; break;
76 case MCUnaryExpr::Minus
: OS
<< '-'; break;
77 case MCUnaryExpr::Not
: OS
<< '~'; break;
78 case MCUnaryExpr::Plus
: OS
<< '+'; break;
80 OS
<< *UE
.getSubExpr();
84 case MCExpr::Binary
: {
85 const MCBinaryExpr
&BE
= cast
<MCBinaryExpr
>(*this);
87 // Only print parens around the LHS if it is non-trivial.
88 if (isa
<MCConstantExpr
>(BE
.getLHS()) || isa
<MCSymbolRefExpr
>(BE
.getLHS())) {
91 OS
<< '(' << *BE
.getLHS() << ')';
94 switch (BE
.getOpcode()) {
95 default: assert(0 && "Invalid opcode!");
96 case MCBinaryExpr::Add
:
97 // Print "X-42" instead of "X+-42".
98 if (const MCConstantExpr
*RHSC
= dyn_cast
<MCConstantExpr
>(BE
.getRHS())) {
99 if (RHSC
->getValue() < 0) {
100 OS
<< RHSC
->getValue();
107 case MCBinaryExpr::And
: OS
<< '&'; break;
108 case MCBinaryExpr::Div
: OS
<< '/'; break;
109 case MCBinaryExpr::EQ
: OS
<< "=="; break;
110 case MCBinaryExpr::GT
: OS
<< '>'; break;
111 case MCBinaryExpr::GTE
: OS
<< ">="; break;
112 case MCBinaryExpr::LAnd
: OS
<< "&&"; break;
113 case MCBinaryExpr::LOr
: OS
<< "||"; break;
114 case MCBinaryExpr::LT
: OS
<< '<'; break;
115 case MCBinaryExpr::LTE
: OS
<< "<="; break;
116 case MCBinaryExpr::Mod
: OS
<< '%'; break;
117 case MCBinaryExpr::Mul
: OS
<< '*'; break;
118 case MCBinaryExpr::NE
: OS
<< "!="; break;
119 case MCBinaryExpr::Or
: OS
<< '|'; break;
120 case MCBinaryExpr::Shl
: OS
<< "<<"; break;
121 case MCBinaryExpr::Shr
: OS
<< ">>"; break;
122 case MCBinaryExpr::Sub
: OS
<< '-'; break;
123 case MCBinaryExpr::Xor
: OS
<< '^'; break;
126 // Only print parens around the LHS if it is non-trivial.
127 if (isa
<MCConstantExpr
>(BE
.getRHS()) || isa
<MCSymbolRefExpr
>(BE
.getRHS())) {
130 OS
<< '(' << *BE
.getRHS() << ')';
136 assert(0 && "Invalid expression kind!");
139 void MCExpr::dump() const {
146 const MCBinaryExpr
*MCBinaryExpr::Create(Opcode Opc
, const MCExpr
*LHS
,
147 const MCExpr
*RHS
, MCContext
&Ctx
) {
148 return new (Ctx
) MCBinaryExpr(Opc
, LHS
, RHS
);
151 const MCUnaryExpr
*MCUnaryExpr::Create(Opcode Opc
, const MCExpr
*Expr
,
153 return new (Ctx
) MCUnaryExpr(Opc
, Expr
);
156 const MCConstantExpr
*MCConstantExpr::Create(int64_t Value
, MCContext
&Ctx
) {
157 return new (Ctx
) MCConstantExpr(Value
);
162 const MCSymbolRefExpr
*MCSymbolRefExpr::Create(const MCSymbol
*Sym
,
165 return new (Ctx
) MCSymbolRefExpr(Sym
, Kind
);
168 const MCSymbolRefExpr
*MCSymbolRefExpr::Create(StringRef Name
, VariantKind Kind
,
170 return Create(Ctx
.GetOrCreateSymbol(Name
), Kind
, Ctx
);
173 StringRef
MCSymbolRefExpr::getVariantKindName(VariantKind Kind
) {
176 case VK_Invalid
: return "<<invalid>>";
177 case VK_None
: return "<<none>>";
179 case VK_GOT
: return "GOT";
180 case VK_GOTOFF
: return "GOTOFF";
181 case VK_GOTPCREL
: return "GOTPCREL";
182 case VK_GOTTPOFF
: return "GOTTPOFF";
183 case VK_INDNTPOFF
: return "INDNTPOFF";
184 case VK_NTPOFF
: return "NTPOFF";
185 case VK_GOTNTPOFF
: return "GOTNTPOFF";
186 case VK_PLT
: return "PLT";
187 case VK_TLSGD
: return "TLSGD";
188 case VK_TLSLD
: return "TLSLD";
189 case VK_TLSLDM
: return "TLSLDM";
190 case VK_TPOFF
: return "TPOFF";
191 case VK_DTPOFF
: return "DTPOFF";
192 case VK_TLVP
: return "TLVP";
193 case VK_ARM_PLT
: return "(PLT)";
194 case VK_ARM_GOT
: return "(GOT)";
195 case VK_ARM_GOTOFF
: return "(GOTOFF)";
196 case VK_ARM_TPOFF
: return "(tpoff)";
197 case VK_ARM_GOTTPOFF
: return "(gottpoff)";
198 case VK_ARM_TLSGD
: return "(tlsgd)";
199 case VK_PPC_TOC
: return "toc";
200 case VK_PPC_HA16
: return "ha16";
201 case VK_PPC_LO16
: return "lo16";
205 MCSymbolRefExpr::VariantKind
206 MCSymbolRefExpr::getVariantKindForName(StringRef Name
) {
207 return StringSwitch
<VariantKind
>(Name
)
210 .Case("GOTOFF", VK_GOTOFF
)
211 .Case("gotoff", VK_GOTOFF
)
212 .Case("GOTPCREL", VK_GOTPCREL
)
213 .Case("gotpcrel", VK_GOTPCREL
)
214 .Case("GOTTPOFF", VK_GOTTPOFF
)
215 .Case("gottpoff", VK_GOTTPOFF
)
216 .Case("INDNTPOFF", VK_INDNTPOFF
)
217 .Case("indntpoff", VK_INDNTPOFF
)
218 .Case("NTPOFF", VK_NTPOFF
)
219 .Case("ntpoff", VK_NTPOFF
)
220 .Case("GOTNTPOFF", VK_GOTNTPOFF
)
221 .Case("gotntpoff", VK_GOTNTPOFF
)
224 .Case("TLSGD", VK_TLSGD
)
225 .Case("tlsgd", VK_TLSGD
)
226 .Case("TLSLD", VK_TLSLD
)
227 .Case("tlsld", VK_TLSLD
)
228 .Case("TLSLDM", VK_TLSLDM
)
229 .Case("tlsldm", VK_TLSLDM
)
230 .Case("TPOFF", VK_TPOFF
)
231 .Case("tpoff", VK_TPOFF
)
232 .Case("DTPOFF", VK_DTPOFF
)
233 .Case("dtpoff", VK_DTPOFF
)
234 .Case("TLVP", VK_TLVP
)
235 .Case("tlvp", VK_TLVP
)
236 .Default(VK_Invalid
);
241 void MCTargetExpr::Anchor() {}
245 bool MCExpr::EvaluateAsAbsolute(int64_t &Res
) const {
246 return EvaluateAsAbsolute(Res
, 0, 0, 0);
249 bool MCExpr::EvaluateAsAbsolute(int64_t &Res
,
250 const MCAsmLayout
&Layout
) const {
251 return EvaluateAsAbsolute(Res
, &Layout
.getAssembler(), &Layout
, 0);
254 bool MCExpr::EvaluateAsAbsolute(int64_t &Res
,
255 const MCAsmLayout
&Layout
,
256 const SectionAddrMap
&Addrs
) const {
257 return EvaluateAsAbsolute(Res
, &Layout
.getAssembler(), &Layout
, &Addrs
);
260 bool MCExpr::EvaluateAsAbsolute(int64_t &Res
, const MCAssembler
&Asm
) const {
261 return EvaluateAsAbsolute(Res
, &Asm
, 0, 0);
264 bool MCExpr::EvaluateAsAbsolute(int64_t &Res
, const MCAssembler
*Asm
,
265 const MCAsmLayout
*Layout
,
266 const SectionAddrMap
*Addrs
) const {
269 // Fast path constants.
270 if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(this)) {
271 Res
= CE
->getValue();
275 // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us
276 // absolutize differences across sections and that is what the MachO writer
279 EvaluateAsRelocatableImpl(Value
, Asm
, Layout
, Addrs
, /*InSet*/ Addrs
);
281 // Record the current value.
282 Res
= Value
.getConstant();
284 return IsRelocatable
&& Value
.isAbsolute();
287 /// \brief Helper method for \see EvaluateSymbolAdd().
288 static void AttemptToFoldSymbolOffsetDifference(const MCAssembler
*Asm
,
289 const MCAsmLayout
*Layout
,
290 const SectionAddrMap
*Addrs
,
292 const MCSymbolRefExpr
*&A
,
293 const MCSymbolRefExpr
*&B
,
298 const MCSymbol
&SA
= A
->getSymbol();
299 const MCSymbol
&SB
= B
->getSymbol();
301 if (SA
.isUndefined() || SB
.isUndefined())
304 if (!Asm
->getWriter().IsSymbolRefDifferenceFullyResolved(*Asm
, A
, B
, InSet
))
307 MCSymbolData
&AD
= Asm
->getSymbolData(SA
);
308 MCSymbolData
&BD
= Asm
->getSymbolData(SB
);
310 if (AD
.getFragment() == BD
.getFragment()) {
311 Addend
+= (AD
.getOffset() - BD
.getOffset());
313 // Pointers to Thumb symbols need to have their low-bit set to allow
315 if (Asm
->isThumbFunc(&SA
))
318 // Clear the symbol expr pointers to indicate we have folded these
327 const MCSectionData
&SecA
= *AD
.getFragment()->getParent();
328 const MCSectionData
&SecB
= *BD
.getFragment()->getParent();
330 if ((&SecA
!= &SecB
) && !Addrs
)
334 Addend
+= (Layout
->getSymbolOffset(&Asm
->getSymbolData(A
->getSymbol())) -
335 Layout
->getSymbolOffset(&Asm
->getSymbolData(B
->getSymbol())));
336 if (Addrs
&& (&SecA
!= &SecB
))
337 Addend
+= (Addrs
->lookup(&SecA
) - Addrs
->lookup(&SecB
));
339 // Clear the symbol expr pointers to indicate we have folded these
344 /// \brief Evaluate the result of an add between (conceptually) two MCValues.
346 /// This routine conceptually attempts to construct an MCValue:
347 /// Result = (Result_A - Result_B + Result_Cst)
348 /// from two MCValue's LHS and RHS where
349 /// Result = LHS + RHS
351 /// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
353 /// This routine attempts to aggresively fold the operands such that the result
354 /// is representable in an MCValue, but may not always succeed.
356 /// \returns True on success, false if the result is not representable in an
359 /// NOTE: It is really important to have both the Asm and Layout arguments.
360 /// They might look redundant, but this function can be used before layout
361 /// is done (see the object streamer for example) and having the Asm argument
362 /// lets us avoid relaxations early.
363 static bool EvaluateSymbolicAdd(const MCAssembler
*Asm
,
364 const MCAsmLayout
*Layout
,
365 const SectionAddrMap
*Addrs
,
367 const MCValue
&LHS
,const MCSymbolRefExpr
*RHS_A
,
368 const MCSymbolRefExpr
*RHS_B
, int64_t RHS_Cst
,
370 // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy
371 // about dealing with modifiers. This will ultimately bite us, one day.
372 const MCSymbolRefExpr
*LHS_A
= LHS
.getSymA();
373 const MCSymbolRefExpr
*LHS_B
= LHS
.getSymB();
374 int64_t LHS_Cst
= LHS
.getConstant();
376 // Fold the result constant immediately.
377 int64_t Result_Cst
= LHS_Cst
+ RHS_Cst
;
379 assert((!Layout
|| Asm
) &&
380 "Must have an assembler object if layout is given!");
382 // If we have a layout, we can fold resolved differences.
384 // First, fold out any differences which are fully resolved. By
385 // reassociating terms in
386 // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
387 // we have the four possible differences:
392 // Since we are attempting to be as aggresive as possible about folding, we
393 // attempt to evaluate each possible alternative.
394 AttemptToFoldSymbolOffsetDifference(Asm
, Layout
, Addrs
, InSet
, LHS_A
, LHS_B
,
396 AttemptToFoldSymbolOffsetDifference(Asm
, Layout
, Addrs
, InSet
, LHS_A
, RHS_B
,
398 AttemptToFoldSymbolOffsetDifference(Asm
, Layout
, Addrs
, InSet
, RHS_A
, LHS_B
,
400 AttemptToFoldSymbolOffsetDifference(Asm
, Layout
, Addrs
, InSet
, RHS_A
, RHS_B
,
404 // We can't represent the addition or subtraction of two symbols.
405 if ((LHS_A
&& RHS_A
) || (LHS_B
&& RHS_B
))
408 // At this point, we have at most one additive symbol and one subtractive
409 // symbol -- find them.
410 const MCSymbolRefExpr
*A
= LHS_A
? LHS_A
: RHS_A
;
411 const MCSymbolRefExpr
*B
= LHS_B
? LHS_B
: RHS_B
;
413 // If we have a negated symbol, then we must have also have a non-negated
414 // symbol in order to encode the expression.
418 Res
= MCValue::get(A
, B
, Result_Cst
);
422 bool MCExpr::EvaluateAsRelocatable(MCValue
&Res
,
423 const MCAsmLayout
&Layout
) const {
424 return EvaluateAsRelocatableImpl(Res
, &Layout
.getAssembler(), &Layout
,
428 bool MCExpr::EvaluateAsRelocatableImpl(MCValue
&Res
,
429 const MCAssembler
*Asm
,
430 const MCAsmLayout
*Layout
,
431 const SectionAddrMap
*Addrs
,
433 ++stats::MCExprEvaluate
;
437 return cast
<MCTargetExpr
>(this)->EvaluateAsRelocatableImpl(Res
, Layout
);
440 Res
= MCValue::get(cast
<MCConstantExpr
>(this)->getValue());
444 const MCSymbolRefExpr
*SRE
= cast
<MCSymbolRefExpr
>(this);
445 const MCSymbol
&Sym
= SRE
->getSymbol();
447 // Evaluate recursively if this is a variable.
448 if (Sym
.isVariable() && SRE
->getKind() == MCSymbolRefExpr::VK_None
) {
449 bool Ret
= Sym
.getVariableValue()->EvaluateAsRelocatableImpl(Res
, Asm
,
453 // If we failed to simplify this to a constant, let the target
455 if (Ret
&& !Res
.getSymA() && !Res
.getSymB())
459 Res
= MCValue::get(SRE
, 0, 0);
464 const MCUnaryExpr
*AUE
= cast
<MCUnaryExpr
>(this);
467 if (!AUE
->getSubExpr()->EvaluateAsRelocatableImpl(Value
, Asm
, Layout
,
471 switch (AUE
->getOpcode()) {
472 case MCUnaryExpr::LNot
:
473 if (!Value
.isAbsolute())
475 Res
= MCValue::get(!Value
.getConstant());
477 case MCUnaryExpr::Minus
:
478 /// -(a - b + const) ==> (b - a - const)
479 if (Value
.getSymA() && !Value
.getSymB())
481 Res
= MCValue::get(Value
.getSymB(), Value
.getSymA(),
482 -Value
.getConstant());
484 case MCUnaryExpr::Not
:
485 if (!Value
.isAbsolute())
487 Res
= MCValue::get(~Value
.getConstant());
489 case MCUnaryExpr::Plus
:
498 const MCBinaryExpr
*ABE
= cast
<MCBinaryExpr
>(this);
499 MCValue LHSValue
, RHSValue
;
501 if (!ABE
->getLHS()->EvaluateAsRelocatableImpl(LHSValue
, Asm
, Layout
,
503 !ABE
->getRHS()->EvaluateAsRelocatableImpl(RHSValue
, Asm
, Layout
,
507 // We only support a few operations on non-constant expressions, handle
509 if (!LHSValue
.isAbsolute() || !RHSValue
.isAbsolute()) {
510 switch (ABE
->getOpcode()) {
513 case MCBinaryExpr::Sub
:
514 // Negate RHS and add.
515 return EvaluateSymbolicAdd(Asm
, Layout
, Addrs
, InSet
, LHSValue
,
516 RHSValue
.getSymB(), RHSValue
.getSymA(),
517 -RHSValue
.getConstant(),
520 case MCBinaryExpr::Add
:
521 return EvaluateSymbolicAdd(Asm
, Layout
, Addrs
, InSet
, LHSValue
,
522 RHSValue
.getSymA(), RHSValue
.getSymB(),
523 RHSValue
.getConstant(),
528 // FIXME: We need target hooks for the evaluation. It may be limited in
529 // width, and gas defines the result of comparisons and right shifts
530 // differently from Apple as.
531 int64_t LHS
= LHSValue
.getConstant(), RHS
= RHSValue
.getConstant();
533 switch (ABE
->getOpcode()) {
534 case MCBinaryExpr::Add
: Result
= LHS
+ RHS
; break;
535 case MCBinaryExpr::And
: Result
= LHS
& RHS
; break;
536 case MCBinaryExpr::Div
: Result
= LHS
/ RHS
; break;
537 case MCBinaryExpr::EQ
: Result
= LHS
== RHS
; break;
538 case MCBinaryExpr::GT
: Result
= LHS
> RHS
; break;
539 case MCBinaryExpr::GTE
: Result
= LHS
>= RHS
; break;
540 case MCBinaryExpr::LAnd
: Result
= LHS
&& RHS
; break;
541 case MCBinaryExpr::LOr
: Result
= LHS
|| RHS
; break;
542 case MCBinaryExpr::LT
: Result
= LHS
< RHS
; break;
543 case MCBinaryExpr::LTE
: Result
= LHS
<= RHS
; break;
544 case MCBinaryExpr::Mod
: Result
= LHS
% RHS
; break;
545 case MCBinaryExpr::Mul
: Result
= LHS
* RHS
; break;
546 case MCBinaryExpr::NE
: Result
= LHS
!= RHS
; break;
547 case MCBinaryExpr::Or
: Result
= LHS
| RHS
; break;
548 case MCBinaryExpr::Shl
: Result
= LHS
<< RHS
; break;
549 case MCBinaryExpr::Shr
: Result
= LHS
>> RHS
; break;
550 case MCBinaryExpr::Sub
: Result
= LHS
- RHS
; break;
551 case MCBinaryExpr::Xor
: Result
= LHS
^ RHS
; break;
554 Res
= MCValue::get(Result
);
559 assert(0 && "Invalid assembly expression kind!");