MC/Mach-O: Implement "absolutizing" semantics of .set, by evaluating the assembly...
[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, 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, MCAsmLayout *Layout) const {
181   switch (getKind()) {
182   case Target:
183     return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout);
184       
185   case Constant:
186     Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
187     return true;
188
189   case SymbolRef: {
190     const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol();
191
192     // Evaluate recursively if this is a variable.
193     if (Sym.isVariable()) {
194       if (!Sym.getValue()->EvaluateAsRelocatable(Res, Layout))
195         return false;
196
197       // Absolutize symbol differences when we have a layout object and the
198       // target requests it.
199       if (Layout && Res.getSymB() &&
200           Layout->getAssembler().getBackend().hasAbsolutizedSet()) {
201         MCSymbolData &A = Layout->getAssembler().getSymbolData(*Res.getSymA());
202         MCSymbolData &B = Layout->getAssembler().getSymbolData(*Res.getSymB());
203         Res = MCValue::get(+ A.getFragment()->getAddress() + A.getOffset()
204                            - B.getFragment()->getAddress() - B.getOffset()
205                            + Res.getConstant());
206       }
207
208       return true;
209     }
210
211     Res = MCValue::get(&Sym, 0, 0);
212     return true;
213   }
214
215   case Unary: {
216     const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
217     MCValue Value;
218
219     if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout))
220       return false;
221
222     switch (AUE->getOpcode()) {
223     case MCUnaryExpr::LNot:
224       if (!Value.isAbsolute())
225         return false;
226       Res = MCValue::get(!Value.getConstant());
227       break;
228     case MCUnaryExpr::Minus:
229       /// -(a - b + const) ==> (b - a - const)
230       if (Value.getSymA() && !Value.getSymB())
231         return false;
232       Res = MCValue::get(Value.getSymB(), Value.getSymA(), 
233                          -Value.getConstant()); 
234       break;
235     case MCUnaryExpr::Not:
236       if (!Value.isAbsolute())
237         return false;
238       Res = MCValue::get(~Value.getConstant()); 
239       break;
240     case MCUnaryExpr::Plus:
241       Res = Value;
242       break;
243     }
244
245     return true;
246   }
247
248   case Binary: {
249     const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
250     MCValue LHSValue, RHSValue;
251     
252     if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) ||
253         !ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout))
254       return false;
255
256     // We only support a few operations on non-constant expressions, handle
257     // those first.
258     if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
259       switch (ABE->getOpcode()) {
260       default:
261         return false;
262       case MCBinaryExpr::Sub:
263         // Negate RHS and add.
264         return EvaluateSymbolicAdd(LHSValue,
265                                    RHSValue.getSymB(), RHSValue.getSymA(),
266                                    -RHSValue.getConstant(),
267                                    Res);
268
269       case MCBinaryExpr::Add:
270         return EvaluateSymbolicAdd(LHSValue,
271                                    RHSValue.getSymA(), RHSValue.getSymB(),
272                                    RHSValue.getConstant(),
273                                    Res);
274       }
275     }
276
277     // FIXME: We need target hooks for the evaluation. It may be limited in
278     // width, and gas defines the result of comparisons and right shifts
279     // differently from Apple as.
280     int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
281     int64_t Result = 0;
282     switch (ABE->getOpcode()) {
283     case MCBinaryExpr::Add:  Result = LHS + RHS; break;
284     case MCBinaryExpr::And:  Result = LHS & RHS; break;
285     case MCBinaryExpr::Div:  Result = LHS / RHS; break;
286     case MCBinaryExpr::EQ:   Result = LHS == RHS; break;
287     case MCBinaryExpr::GT:   Result = LHS > RHS; break;
288     case MCBinaryExpr::GTE:  Result = LHS >= RHS; break;
289     case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
290     case MCBinaryExpr::LOr:  Result = LHS || RHS; break;
291     case MCBinaryExpr::LT:   Result = LHS < RHS; break;
292     case MCBinaryExpr::LTE:  Result = LHS <= RHS; break;
293     case MCBinaryExpr::Mod:  Result = LHS % RHS; break;
294     case MCBinaryExpr::Mul:  Result = LHS * RHS; break;
295     case MCBinaryExpr::NE:   Result = LHS != RHS; break;
296     case MCBinaryExpr::Or:   Result = LHS | RHS; break;
297     case MCBinaryExpr::Shl:  Result = LHS << RHS; break;
298     case MCBinaryExpr::Shr:  Result = LHS >> RHS; break;
299     case MCBinaryExpr::Sub:  Result = LHS - RHS; break;
300     case MCBinaryExpr::Xor:  Result = LHS ^ RHS; break;
301     }
302
303     Res = MCValue::get(Result);
304     return true;
305   }
306   }
307
308   assert(0 && "Invalid assembly expression kind!");
309   return false;
310 }