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