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