blob: e419043a771749acc36796fa71f937f01a41139d [file] [log] [blame]
Shih-wei Liaoe264f622010-02-10 11:10:31 -08001//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
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 "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/Debug.h"
15#include "llvm/Support/raw_ostream.h"
16using namespace llvm;
17
18void MCExpr::print(raw_ostream &OS) const {
19 switch (getKind()) {
20 case MCExpr::Target:
21 return cast<MCTargetExpr>(this)->PrintImpl(OS);
22 case MCExpr::Constant:
23 OS << cast<MCConstantExpr>(*this).getValue();
24 return;
25
26 case MCExpr::SymbolRef: {
27 const MCSymbol &Sym = cast<MCSymbolRefExpr>(*this).getSymbol();
28
29 // Parenthesize names that start with $ so that they don't look like
30 // absolute names.
31 if (Sym.getName()[0] == '$')
32 OS << '(' << Sym << ')';
33 else
34 OS << Sym;
35 return;
36 }
37
38 case MCExpr::Unary: {
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;
46 }
47 OS << *UE.getSubExpr();
48 return;
49 }
50
51 case MCExpr::Binary: {
52 const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);
53
54 // Only print parens around the LHS if it is non-trivial.
55 if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
56 OS << *BE.getLHS();
57 } else {
58 OS << '(' << *BE.getLHS() << ')';
59 }
60
61 switch (BE.getOpcode()) {
62 default: assert(0 && "Invalid opcode!");
63 case MCBinaryExpr::Add:
64 // Print "X-42" instead of "X+-42".
65 if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {
66 if (RHSC->getValue() < 0) {
67 OS << RHSC->getValue();
68 return;
69 }
70 }
71
72 OS << '+';
73 break;
74 case MCBinaryExpr::And: OS << '&'; break;
75 case MCBinaryExpr::Div: OS << '/'; break;
76 case MCBinaryExpr::EQ: OS << "=="; break;
77 case MCBinaryExpr::GT: OS << '>'; break;
78 case MCBinaryExpr::GTE: OS << ">="; break;
79 case MCBinaryExpr::LAnd: OS << "&&"; break;
80 case MCBinaryExpr::LOr: OS << "||"; break;
81 case MCBinaryExpr::LT: OS << '<'; break;
82 case MCBinaryExpr::LTE: OS << "<="; break;
83 case MCBinaryExpr::Mod: OS << '%'; break;
84 case MCBinaryExpr::Mul: OS << '*'; break;
85 case MCBinaryExpr::NE: OS << "!="; break;
86 case MCBinaryExpr::Or: OS << '|'; break;
87 case MCBinaryExpr::Shl: OS << "<<"; break;
88 case MCBinaryExpr::Shr: OS << ">>"; break;
89 case MCBinaryExpr::Sub: OS << '-'; break;
90 case MCBinaryExpr::Xor: OS << '^'; break;
91 }
92
93 // Only print parens around the LHS if it is non-trivial.
94 if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
95 OS << *BE.getRHS();
96 } else {
97 OS << '(' << *BE.getRHS() << ')';
98 }
99 return;
100 }
101 }
102
103 assert(0 && "Invalid expression kind!");
104}
105
106void MCExpr::dump() const {
107 print(dbgs());
108 dbgs() << '\n';
109}
110
111/* *** */
112
113const MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS,
114 const MCExpr *RHS, MCContext &Ctx) {
115 return new (Ctx) MCBinaryExpr(Opc, LHS, RHS);
116}
117
118const MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr,
119 MCContext &Ctx) {
120 return new (Ctx) MCUnaryExpr(Opc, Expr);
121}
122
123const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) {
124 return new (Ctx) MCConstantExpr(Value);
125}
126
127const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym,
128 MCContext &Ctx) {
129 return new (Ctx) MCSymbolRefExpr(Sym);
130}
131
132const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, MCContext &Ctx) {
133 return Create(Ctx.GetOrCreateSymbol(Name), Ctx);
134}
135
136void MCTargetExpr::Anchor() {}
137
138/* *** */
139
140bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const {
141 MCValue Value;
142
143 if (!EvaluateAsRelocatable(Value) || !Value.isAbsolute())
144 return false;
145
146 Res = Value.getConstant();
147 return true;
148}
149
150static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A,
151 const MCSymbol *RHS_B, int64_t RHS_Cst,
152 MCValue &Res) {
153 // We can't add or subtract two symbols.
154 if ((LHS.getSymA() && RHS_A) ||
155 (LHS.getSymB() && RHS_B))
156 return false;
157
158 const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
159 const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
160 if (B) {
161 // If we have a negated symbol, then we must have also have a non-negated
162 // symbol in order to encode the expression. We can do this check later to
163 // permit expressions which eventually fold to a representable form -- such
164 // as (a + (0 - b)) -- if necessary.
165 if (!A)
166 return false;
167 }
168 Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
169 return true;
170}
171
172bool MCExpr::EvaluateAsRelocatable(MCValue &Res) const {
173 switch (getKind()) {
174 case Target:
175 return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res);
176
177 case Constant:
178 Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
179 return true;
180
181 case SymbolRef: {
182 const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol();
183
184 // Evaluate recursively if this is a variable.
185 if (Sym.isVariable())
186 return Sym.getValue()->EvaluateAsRelocatable(Res);
187
188 Res = MCValue::get(&Sym, 0, 0);
189 return true;
190 }
191
192 case Unary: {
193 const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
194 MCValue Value;
195
196 if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value))
197 return false;
198
199 switch (AUE->getOpcode()) {
200 case MCUnaryExpr::LNot:
201 if (!Value.isAbsolute())
202 return false;
203 Res = MCValue::get(!Value.getConstant());
204 break;
205 case MCUnaryExpr::Minus:
206 /// -(a - b + const) ==> (b - a - const)
207 if (Value.getSymA() && !Value.getSymB())
208 return false;
209 Res = MCValue::get(Value.getSymB(), Value.getSymA(),
210 -Value.getConstant());
211 break;
212 case MCUnaryExpr::Not:
213 if (!Value.isAbsolute())
214 return false;
215 Res = MCValue::get(~Value.getConstant());
216 break;
217 case MCUnaryExpr::Plus:
218 Res = Value;
219 break;
220 }
221
222 return true;
223 }
224
225 case Binary: {
226 const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
227 MCValue LHSValue, RHSValue;
228
229 if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue) ||
230 !ABE->getRHS()->EvaluateAsRelocatable(RHSValue))
231 return false;
232
233 // We only support a few operations on non-constant expressions, handle
234 // those first.
235 if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
236 switch (ABE->getOpcode()) {
237 default:
238 return false;
239 case MCBinaryExpr::Sub:
240 // Negate RHS and add.
241 return EvaluateSymbolicAdd(LHSValue,
242 RHSValue.getSymB(), RHSValue.getSymA(),
243 -RHSValue.getConstant(),
244 Res);
245
246 case MCBinaryExpr::Add:
247 return EvaluateSymbolicAdd(LHSValue,
248 RHSValue.getSymA(), RHSValue.getSymB(),
249 RHSValue.getConstant(),
250 Res);
251 }
252 }
253
254 // FIXME: We need target hooks for the evaluation. It may be limited in
255 // width, and gas defines the result of comparisons and right shifts
256 // differently from Apple as.
257 int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
258 int64_t Result = 0;
259 switch (ABE->getOpcode()) {
260 case MCBinaryExpr::Add: Result = LHS + RHS; break;
261 case MCBinaryExpr::And: Result = LHS & RHS; break;
262 case MCBinaryExpr::Div: Result = LHS / RHS; break;
263 case MCBinaryExpr::EQ: Result = LHS == RHS; break;
264 case MCBinaryExpr::GT: Result = LHS > RHS; break;
265 case MCBinaryExpr::GTE: Result = LHS >= RHS; break;
266 case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
267 case MCBinaryExpr::LOr: Result = LHS || RHS; break;
268 case MCBinaryExpr::LT: Result = LHS < RHS; break;
269 case MCBinaryExpr::LTE: Result = LHS <= RHS; break;
270 case MCBinaryExpr::Mod: Result = LHS % RHS; break;
271 case MCBinaryExpr::Mul: Result = LHS * RHS; break;
272 case MCBinaryExpr::NE: Result = LHS != RHS; break;
273 case MCBinaryExpr::Or: Result = LHS | RHS; break;
274 case MCBinaryExpr::Shl: Result = LHS << RHS; break;
275 case MCBinaryExpr::Shr: Result = LHS >> RHS; break;
276 case MCBinaryExpr::Sub: Result = LHS - RHS; break;
277 case MCBinaryExpr::Xor: Result = LHS ^ RHS; break;
278 }
279
280 Res = MCValue::get(Result);
281 return true;
282 }
283 }
284
285 assert(0 && "Invalid assembly expression kind!");
286 return false;
287}