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