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