10759687b2fd444556d7b2765848f321955c3dc8
[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 using namespace llvm;
15
16 const MCBinaryExpr * MCBinaryExpr::Create(Opcode Opc,
17                                           const MCExpr *LHS,
18                                           const MCExpr *RHS,
19                                           MCContext &Ctx) {
20   return new (Ctx) MCBinaryExpr(Opc, LHS, RHS);
21 }
22
23 const MCUnaryExpr * MCUnaryExpr::Create(Opcode Opc,
24                                         const MCExpr *Expr,
25                                         MCContext &Ctx) {
26   return new (Ctx) MCUnaryExpr(Opc, Expr);
27 }
28
29 const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) {
30   return new (Ctx) MCConstantExpr(Value);
31 }
32
33 const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym,
34                                                MCContext &Ctx) {
35   return new (Ctx) MCSymbolRefExpr(Sym);
36 }
37
38 /* *** */
39
40 bool MCExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
41   MCValue Value;
42   
43   if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isAbsolute())
44     return false;
45
46   Res = Value.getConstant();
47   return true;
48 }
49
50 static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A, 
51                                 const MCSymbol *RHS_B, int64_t RHS_Cst,
52                                 MCValue &Res) {
53   // We can't add or subtract two symbols.
54   if ((LHS.getSymA() && RHS_A) ||
55       (LHS.getSymB() && RHS_B))
56     return false;
57
58   const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
59   const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
60   if (B) {
61     // If we have a negated symbol, then we must have also have a non-negated
62     // symbol in order to encode the expression. We can do this check later to
63     // permit expressions which eventually fold to a representable form -- such
64     // as (a + (0 - b)) -- if necessary.
65     if (!A)
66       return false;
67   }
68   Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
69   return true;
70 }
71
72 bool MCExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
73   switch (getKind()) {
74   case Constant:
75     Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
76     return true;
77
78   case SymbolRef: {
79     const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol();
80     if (const MCValue *Value = Ctx.GetSymbolValue(&Sym))
81       Res = *Value;
82     else
83       Res = MCValue::get(&Sym, 0, 0);
84     return true;
85   }
86
87   case Unary: {
88     const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
89     MCValue Value;
90
91     if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
92       return false;
93
94     switch (AUE->getOpcode()) {
95     case MCUnaryExpr::LNot:
96       if (!Value.isAbsolute())
97         return false;
98       Res = MCValue::get(!Value.getConstant());
99       break;
100     case MCUnaryExpr::Minus:
101       /// -(a - b + const) ==> (b - a - const)
102       if (Value.getSymA() && !Value.getSymB())
103         return false;
104       Res = MCValue::get(Value.getSymB(), Value.getSymA(), 
105                          -Value.getConstant()); 
106       break;
107     case MCUnaryExpr::Not:
108       if (!Value.isAbsolute())
109         return false;
110       Res = MCValue::get(~Value.getConstant()); 
111       break;
112     case MCUnaryExpr::Plus:
113       Res = Value;
114       break;
115     }
116
117     return true;
118   }
119
120   case Binary: {
121     const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
122     MCValue LHSValue, RHSValue;
123     
124     if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) ||
125         !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue))
126       return false;
127
128     // We only support a few operations on non-constant expressions, handle
129     // those first.
130     if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
131       switch (ABE->getOpcode()) {
132       default:
133         return false;
134       case MCBinaryExpr::Sub:
135         // Negate RHS and add.
136         return EvaluateSymbolicAdd(LHSValue,
137                                    RHSValue.getSymB(), RHSValue.getSymA(),
138                                    -RHSValue.getConstant(),
139                                    Res);
140
141       case MCBinaryExpr::Add:
142         return EvaluateSymbolicAdd(LHSValue,
143                                    RHSValue.getSymA(), RHSValue.getSymB(),
144                                    RHSValue.getConstant(),
145                                    Res);
146       }
147     }
148
149     // FIXME: We need target hooks for the evaluation. It may be limited in
150     // width, and gas defines the result of comparisons differently from Apple
151     // as (the result is sign extended).
152     int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
153     int64_t Result = 0;
154     switch (ABE->getOpcode()) {
155     case MCBinaryExpr::Add:  Result = LHS + RHS; break;
156     case MCBinaryExpr::And:  Result = LHS & RHS; break;
157     case MCBinaryExpr::Div:  Result = LHS / RHS; break;
158     case MCBinaryExpr::EQ:   Result = LHS == RHS; break;
159     case MCBinaryExpr::GT:   Result = LHS > RHS; break;
160     case MCBinaryExpr::GTE:  Result = LHS >= RHS; break;
161     case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
162     case MCBinaryExpr::LOr:  Result = LHS || RHS; break;
163     case MCBinaryExpr::LT:   Result = LHS < RHS; break;
164     case MCBinaryExpr::LTE:  Result = LHS <= RHS; break;
165     case MCBinaryExpr::Mod:  Result = LHS % RHS; break;
166     case MCBinaryExpr::Mul:  Result = LHS * RHS; break;
167     case MCBinaryExpr::NE:   Result = LHS != RHS; break;
168     case MCBinaryExpr::Or:   Result = LHS | RHS; break;
169     case MCBinaryExpr::Shl:  Result = LHS << RHS; break;
170     case MCBinaryExpr::Shr:  Result = LHS >> RHS; break;
171     case MCBinaryExpr::Sub:  Result = LHS - RHS; break;
172     case MCBinaryExpr::Xor:  Result = LHS ^ RHS; break;
173     }
174
175     Res = MCValue::get(Result);
176     return true;
177   }
178   }
179
180   assert(0 && "Invalid assembly expression kind!");
181   return false;
182 }