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 #include "llvm/MC/MCExpr.h"
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCSymbol.h"
13 #include "llvm/MC/MCValue.h"
14 #include "llvm/Support/raw_ostream.h"
17 void MCExpr::print(raw_ostream
&OS
, const MCAsmInfo
*MAI
) const {
19 case MCExpr::Constant
:
20 OS
<< cast
<MCConstantExpr
>(*this).getValue();
23 case MCExpr::SymbolRef
: {
24 const MCSymbol
&Sym
= cast
<MCSymbolRefExpr
>(*this).getSymbol();
26 // Parenthesize names that start with $ so that they don't look like
28 if (Sym
.getName()[0] == '$') {
39 const MCUnaryExpr
&UE
= cast
<MCUnaryExpr
>(*this);
40 switch (UE
.getOpcode()) {
41 default: assert(0 && "Invalid opcode!");
42 case MCUnaryExpr::LNot
: OS
<< '!'; break;
43 case MCUnaryExpr::Minus
: OS
<< '-'; break;
44 case MCUnaryExpr::Not
: OS
<< '~'; break;
45 case MCUnaryExpr::Plus
: OS
<< '+'; break;
47 UE
.getSubExpr()->print(OS
, MAI
);
51 case MCExpr::Binary
: {
52 const MCBinaryExpr
&BE
= cast
<MCBinaryExpr
>(*this);
54 // Only print parens around the LHS if it is non-trivial.
55 if (isa
<MCConstantExpr
>(BE
.getLHS()) || isa
<MCSymbolRefExpr
>(BE
.getLHS())) {
56 BE
.getLHS()->print(OS
, MAI
);
59 BE
.getLHS()->print(OS
, MAI
);
63 switch (BE
.getOpcode()) {
64 default: assert(0 && "Invalid opcode!");
65 case MCBinaryExpr::Add
:
66 // Print "X-42" instead of "X+-42".
67 if (const MCConstantExpr
*RHSC
= dyn_cast
<MCConstantExpr
>(BE
.getRHS())) {
68 if (RHSC
->getValue() < 0) {
69 OS
<< RHSC
->getValue();
76 case MCBinaryExpr::And
: OS
<< '&'; break;
77 case MCBinaryExpr::Div
: OS
<< '/'; break;
78 case MCBinaryExpr::EQ
: OS
<< "=="; break;
79 case MCBinaryExpr::GT
: OS
<< '>'; break;
80 case MCBinaryExpr::GTE
: OS
<< ">="; break;
81 case MCBinaryExpr::LAnd
: OS
<< "&&"; break;
82 case MCBinaryExpr::LOr
: OS
<< "||"; break;
83 case MCBinaryExpr::LT
: OS
<< '<'; break;
84 case MCBinaryExpr::LTE
: OS
<< "<="; break;
85 case MCBinaryExpr::Mod
: OS
<< '%'; break;
86 case MCBinaryExpr::Mul
: OS
<< '*'; break;
87 case MCBinaryExpr::NE
: OS
<< "!="; break;
88 case MCBinaryExpr::Or
: OS
<< '|'; break;
89 case MCBinaryExpr::Shl
: OS
<< "<<"; break;
90 case MCBinaryExpr::Shr
: OS
<< ">>"; break;
91 case MCBinaryExpr::Sub
: OS
<< '-'; break;
92 case MCBinaryExpr::Xor
: OS
<< '^'; break;
95 // Only print parens around the LHS if it is non-trivial.
96 if (isa
<MCConstantExpr
>(BE
.getRHS()) || isa
<MCSymbolRefExpr
>(BE
.getRHS())) {
97 BE
.getRHS()->print(OS
, MAI
);
100 BE
.getRHS()->print(OS
, MAI
);
107 assert(0 && "Invalid expression kind!");
110 void MCExpr::dump() const {
117 const MCBinaryExpr
*MCBinaryExpr::Create(Opcode Opc
, const MCExpr
*LHS
,
118 const MCExpr
*RHS
, MCContext
&Ctx
) {
119 return new (Ctx
) MCBinaryExpr(Opc
, LHS
, RHS
);
122 const MCUnaryExpr
*MCUnaryExpr::Create(Opcode Opc
, const MCExpr
*Expr
,
124 return new (Ctx
) MCUnaryExpr(Opc
, Expr
);
127 const MCConstantExpr
*MCConstantExpr::Create(int64_t Value
, MCContext
&Ctx
) {
128 return new (Ctx
) MCConstantExpr(Value
);
131 const MCSymbolRefExpr
*MCSymbolRefExpr::Create(const MCSymbol
*Sym
,
133 return new (Ctx
) MCSymbolRefExpr(Sym
);
138 bool MCExpr::EvaluateAsAbsolute(MCContext
&Ctx
, int64_t &Res
) const {
141 if (!EvaluateAsRelocatable(Ctx
, Value
) || !Value
.isAbsolute())
144 Res
= Value
.getConstant();
148 static bool EvaluateSymbolicAdd(const MCValue
&LHS
, const MCSymbol
*RHS_A
,
149 const MCSymbol
*RHS_B
, int64_t RHS_Cst
,
151 // We can't add or subtract two symbols.
152 if ((LHS
.getSymA() && RHS_A
) ||
153 (LHS
.getSymB() && RHS_B
))
156 const MCSymbol
*A
= LHS
.getSymA() ? LHS
.getSymA() : RHS_A
;
157 const MCSymbol
*B
= LHS
.getSymB() ? LHS
.getSymB() : RHS_B
;
159 // If we have a negated symbol, then we must have also have a non-negated
160 // symbol in order to encode the expression. We can do this check later to
161 // permit expressions which eventually fold to a representable form -- such
162 // as (a + (0 - b)) -- if necessary.
166 Res
= MCValue::get(A
, B
, LHS
.getConstant() + RHS_Cst
);
170 bool MCExpr::EvaluateAsRelocatable(MCContext
&Ctx
, MCValue
&Res
) const {
173 Res
= MCValue::get(cast
<MCConstantExpr
>(this)->getValue());
177 const MCSymbol
&Sym
= cast
<MCSymbolRefExpr
>(this)->getSymbol();
178 if (const MCValue
*Value
= Ctx
.GetSymbolValue(&Sym
))
181 Res
= MCValue::get(&Sym
, 0, 0);
186 const MCUnaryExpr
*AUE
= cast
<MCUnaryExpr
>(this);
189 if (!AUE
->getSubExpr()->EvaluateAsRelocatable(Ctx
, Value
))
192 switch (AUE
->getOpcode()) {
193 case MCUnaryExpr::LNot
:
194 if (!Value
.isAbsolute())
196 Res
= MCValue::get(!Value
.getConstant());
198 case MCUnaryExpr::Minus
:
199 /// -(a - b + const) ==> (b - a - const)
200 if (Value
.getSymA() && !Value
.getSymB())
202 Res
= MCValue::get(Value
.getSymB(), Value
.getSymA(),
203 -Value
.getConstant());
205 case MCUnaryExpr::Not
:
206 if (!Value
.isAbsolute())
208 Res
= MCValue::get(~Value
.getConstant());
210 case MCUnaryExpr::Plus
:
219 const MCBinaryExpr
*ABE
= cast
<MCBinaryExpr
>(this);
220 MCValue LHSValue
, RHSValue
;
222 if (!ABE
->getLHS()->EvaluateAsRelocatable(Ctx
, LHSValue
) ||
223 !ABE
->getRHS()->EvaluateAsRelocatable(Ctx
, RHSValue
))
226 // We only support a few operations on non-constant expressions, handle
228 if (!LHSValue
.isAbsolute() || !RHSValue
.isAbsolute()) {
229 switch (ABE
->getOpcode()) {
232 case MCBinaryExpr::Sub
:
233 // Negate RHS and add.
234 return EvaluateSymbolicAdd(LHSValue
,
235 RHSValue
.getSymB(), RHSValue
.getSymA(),
236 -RHSValue
.getConstant(),
239 case MCBinaryExpr::Add
:
240 return EvaluateSymbolicAdd(LHSValue
,
241 RHSValue
.getSymA(), RHSValue
.getSymB(),
242 RHSValue
.getConstant(),
247 // FIXME: We need target hooks for the evaluation. It may be limited in
248 // width, and gas defines the result of comparisons differently from Apple
249 // as (the result is sign extended).
250 int64_t LHS
= LHSValue
.getConstant(), RHS
= RHSValue
.getConstant();
252 switch (ABE
->getOpcode()) {
253 case MCBinaryExpr::Add
: Result
= LHS
+ RHS
; break;
254 case MCBinaryExpr::And
: Result
= LHS
& RHS
; break;
255 case MCBinaryExpr::Div
: Result
= LHS
/ RHS
; break;
256 case MCBinaryExpr::EQ
: Result
= LHS
== RHS
; break;
257 case MCBinaryExpr::GT
: Result
= LHS
> RHS
; break;
258 case MCBinaryExpr::GTE
: Result
= LHS
>= RHS
; break;
259 case MCBinaryExpr::LAnd
: Result
= LHS
&& RHS
; break;
260 case MCBinaryExpr::LOr
: Result
= LHS
|| RHS
; break;
261 case MCBinaryExpr::LT
: Result
= LHS
< RHS
; break;
262 case MCBinaryExpr::LTE
: Result
= LHS
<= RHS
; break;
263 case MCBinaryExpr::Mod
: Result
= LHS
% RHS
; break;
264 case MCBinaryExpr::Mul
: Result
= LHS
* RHS
; break;
265 case MCBinaryExpr::NE
: Result
= LHS
!= RHS
; break;
266 case MCBinaryExpr::Or
: Result
= LHS
| RHS
; break;
267 case MCBinaryExpr::Shl
: Result
= LHS
<< RHS
; break;
268 case MCBinaryExpr::Shr
: Result
= LHS
>> RHS
; break;
269 case MCBinaryExpr::Sub
: Result
= LHS
- RHS
; break;
270 case MCBinaryExpr::Xor
: Result
= LHS
^ RHS
; break;
273 Res
= MCValue::get(Result
);
278 assert(0 && "Invalid assembly expression kind!");