MCExpr.cpp revision 198396
1209513Simp//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
2209513Simp//
3209552Simp//                     The LLVM Compiler Infrastructure
4209513Simp//
5209513Simp// This file is distributed under the University of Illinois Open Source
6209513Simp// License. See LICENSE.TXT for details.
7209513Simp//
8209513Simp//===----------------------------------------------------------------------===//
9209513Simp
10209513Simp#include "llvm/MC/MCExpr.h"
11209513Simp#include "llvm/MC/MCContext.h"
12209513Simp#include "llvm/MC/MCSymbol.h"
13209513Simp#include "llvm/MC/MCValue.h"
14209513Simp#include "llvm/Support/raw_ostream.h"
15209513Simpusing namespace llvm;
16209513Simp
17209513Simpvoid MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
18209513Simp  switch (getKind()) {
19209513Simp  case MCExpr::Constant:
20209513Simp    OS << cast<MCConstantExpr>(*this).getValue();
21209513Simp    return;
22209513Simp
23209513Simp  case MCExpr::SymbolRef: {
24209513Simp    const MCSymbol &Sym = cast<MCSymbolRefExpr>(*this).getSymbol();
25209513Simp
26209513Simp    // Parenthesize names that start with $ so that they don't look like
27209513Simp    // absolute names.
28209513Simp    if (Sym.getName()[0] == '$') {
29209513Simp      OS << '(';
30209513Simp      Sym.print(OS, MAI);
31209513Simp      OS << ')';
32209513Simp    } else {
33209513Simp      Sym.print(OS, MAI);
34209513Simp    }
35209513Simp    return;
36220059Sjpaetzel  }
37220059Sjpaetzel
38209513Simp  case MCExpr::Unary: {
39209513Simp    const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this);
40209513Simp    switch (UE.getOpcode()) {
41209513Simp    default: assert(0 && "Invalid opcode!");
42209513Simp    case MCUnaryExpr::LNot:  OS << '!'; break;
43220059Sjpaetzel    case MCUnaryExpr::Minus: OS << '-'; break;
44209513Simp    case MCUnaryExpr::Not:   OS << '~'; break;
45209513Simp    case MCUnaryExpr::Plus:  OS << '+'; break;
46209513Simp    }
47209513Simp    UE.getSubExpr()->print(OS, MAI);
48209513Simp    return;
49209513Simp  }
50209513Simp
51209513Simp  case MCExpr::Binary: {
52209513Simp    const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);
53232899Sjpaetzel
54220059Sjpaetzel    // Only print parens around the LHS if it is non-trivial.
55209513Simp    if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
56209513Simp      BE.getLHS()->print(OS, MAI);
57220059Sjpaetzel    } else {
58220059Sjpaetzel      OS << '(';
59209513Simp      BE.getLHS()->print(OS, MAI);
60232899Sjpaetzel      OS << ')';
61209513Simp    }
62232510Seadler
63220059Sjpaetzel    switch (BE.getOpcode()) {
64211488Simp    default: assert(0 && "Invalid opcode!");
65211488Simp    case MCBinaryExpr::Add:
66211488Simp      // Print "X-42" instead of "X+-42".
67209513Simp      if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {
68209513Simp        if (RHSC->getValue() < 0) {
69209513Simp          OS << RHSC->getValue();
70209513Simp          return;
71209513Simp        }
72209513Simp      }
73209513Simp
74209513Simp      OS <<  '+';
75209513Simp      break;
76209513Simp    case MCBinaryExpr::And:  OS <<  '&'; break;
77209513Simp    case MCBinaryExpr::Div:  OS <<  '/'; break;
78225657Sjpaetzel    case MCBinaryExpr::EQ:   OS << "=="; break;
79225657Sjpaetzel    case MCBinaryExpr::GT:   OS <<  '>'; break;
80225657Sjpaetzel    case MCBinaryExpr::GTE:  OS << ">="; break;
81225657Sjpaetzel    case MCBinaryExpr::LAnd: OS << "&&"; break;
82225657Sjpaetzel    case MCBinaryExpr::LOr:  OS << "||"; break;
83225657Sjpaetzel    case MCBinaryExpr::LT:   OS <<  '<'; break;
84225657Sjpaetzel    case MCBinaryExpr::LTE:  OS << "<="; break;
85225657Sjpaetzel    case MCBinaryExpr::Mod:  OS <<  '%'; break;
86225657Sjpaetzel    case MCBinaryExpr::Mul:  OS <<  '*'; break;
87209513Simp    case MCBinaryExpr::NE:   OS << "!="; break;
88209513Simp    case MCBinaryExpr::Or:   OS <<  '|'; break;
89209513Simp    case MCBinaryExpr::Shl:  OS << "<<"; break;
90220059Sjpaetzel    case MCBinaryExpr::Shr:  OS << ">>"; break;
91209513Simp    case MCBinaryExpr::Sub:  OS <<  '-'; break;
92209513Simp    case MCBinaryExpr::Xor:  OS <<  '^'; break;
93209513Simp    }
94209513Simp
95211730Simp    // Only print parens around the LHS if it is non-trivial.
96211730Simp    if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
97211730Simp      BE.getRHS()->print(OS, MAI);
98209513Simp    } else {
99211730Simp      OS << '(';
100211730Simp      BE.getRHS()->print(OS, MAI);
101211730Simp      OS << ')';
102211730Simp    }
103211730Simp    return;
104220059Sjpaetzel  }
105220059Sjpaetzel  }
106211730Simp
107211730Simp  assert(0 && "Invalid expression kind!");
108211730Simp}
109220059Sjpaetzel
110211730Simpvoid MCExpr::dump() const {
111211730Simp  print(errs(), 0);
112211730Simp  errs() << '\n';
113211730Simp}
114211730Simp
115211730Simp/* *** */
116211730Simp
117211730Simpconst MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS,
118211730Simp                                         const MCExpr *RHS, MCContext &Ctx) {
119209513Simp  return new (Ctx) MCBinaryExpr(Opc, LHS, RHS);
120209513Simp}
121209513Simp
122209513Simpconst MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr,
123209513Simp                                       MCContext &Ctx) {
124209513Simp  return new (Ctx) MCUnaryExpr(Opc, Expr);
125209513Simp}
126209513Simp
127209513Simpconst MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) {
128209513Simp  return new (Ctx) MCConstantExpr(Value);
129232899Sjpaetzel}
130232899Sjpaetzel
131232899Sjpaetzelconst MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym,
132209513Simp                                               MCContext &Ctx) {
133209513Simp  return new (Ctx) MCSymbolRefExpr(Sym);
134209513Simp}
135209513Simp
136209513Simpconst MCSymbolRefExpr *MCSymbolRefExpr::Create(const StringRef &Name,
137209513Simp                                               MCContext &Ctx) {
138209513Simp  return Create(Ctx.GetOrCreateSymbol(Name), Ctx);
139209513Simp}
140209513Simp
141209513Simp
142209513Simp/* *** */
143209513Simp
144209513Simpbool MCExpr::EvaluateAsAbsolute(int64_t &Res) const {
145209513Simp  MCValue Value;
146209513Simp
147220059Sjpaetzel  if (!EvaluateAsRelocatable(Value) || !Value.isAbsolute())
148220059Sjpaetzel    return false;
149209513Simp
150209513Simp  Res = Value.getConstant();
151209513Simp  return true;
152220059Sjpaetzel}
153209513Simp
154209513Simpstatic bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A,
155209513Simp                                const MCSymbol *RHS_B, int64_t RHS_Cst,
156209513Simp                                MCValue &Res) {
157209513Simp  // We can't add or subtract two symbols.
158209513Simp  if ((LHS.getSymA() && RHS_A) ||
159209513Simp      (LHS.getSymB() && RHS_B))
160209513Simp    return false;
161209513Simp
162209513Simp  const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
163220059Sjpaetzel  const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
164209513Simp  if (B) {
165209513Simp    // If we have a negated symbol, then we must have also have a non-negated
166217229Sjpaetzel    // symbol in order to encode the expression. We can do this check later to
167217229Sjpaetzel    // permit expressions which eventually fold to a representable form -- such
168209513Simp    // as (a + (0 - b)) -- if necessary.
169217229Sjpaetzel    if (!A)
170217229Sjpaetzel      return false;
171217229Sjpaetzel  }
172217229Sjpaetzel  Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
173217229Sjpaetzel  return true;
174209513Simp}
175209513Simp
176217229Sjpaetzelbool MCExpr::EvaluateAsRelocatable(MCValue &Res) const {
177217229Sjpaetzel  switch (getKind()) {
178217229Sjpaetzel  case Constant:
179217229Sjpaetzel    Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
180217229Sjpaetzel    return true;
181217229Sjpaetzel
182227368Sjpaetzel  case SymbolRef: {
183227368Sjpaetzel    const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol();
184227368Sjpaetzel
185217229Sjpaetzel    // Evaluate recursively if this is a variable.
186209513Simp    if (Sym.isVariable())
187209513Simp      return Sym.getValue()->EvaluateAsRelocatable(Res);
188209513Simp
189209513Simp    Res = MCValue::get(&Sym, 0, 0);
190220059Sjpaetzel    return true;
191220059Sjpaetzel  }
192209513Simp
193209513Simp  case Unary: {
194209513Simp    const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
195209513Simp    MCValue Value;
196209513Simp
197209513Simp    if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value))
198209513Simp      return false;
199209513Simp
200209513Simp    switch (AUE->getOpcode()) {
201209513Simp    case MCUnaryExpr::LNot:
202209513Simp      if (!Value.isAbsolute())
203209513Simp        return false;
204220059Sjpaetzel      Res = MCValue::get(!Value.getConstant());
205220059Sjpaetzel      break;
206209513Simp    case MCUnaryExpr::Minus:
207209513Simp      /// -(a - b + const) ==> (b - a - const)
208209513Simp      if (Value.getSymA() && !Value.getSymB())
209209513Simp        return false;
210209513Simp      Res = MCValue::get(Value.getSymB(), Value.getSymA(),
211209513Simp                         -Value.getConstant());
212209513Simp      break;
213209513Simp    case MCUnaryExpr::Not:
214209513Simp      if (!Value.isAbsolute())
215209513Simp        return false;
216209513Simp      Res = MCValue::get(~Value.getConstant());
217209513Simp      break;
218209513Simp    case MCUnaryExpr::Plus:
219209513Simp      Res = Value;
220220059Sjpaetzel      break;
221209513Simp    }
222220059Sjpaetzel
223209513Simp    return true;
224209513Simp  }
225209513Simp
226209513Simp  case Binary: {
227213647Simp    const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
228209513Simp    MCValue LHSValue, RHSValue;
229209513Simp
230209513Simp    if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue) ||
231209513Simp        !ABE->getRHS()->EvaluateAsRelocatable(RHSValue))
232209513Simp      return false;
233220059Sjpaetzel
234209513Simp    // We only support a few operations on non-constant expressions, handle
235209513Simp    // those first.
236209513Simp    if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
237209513Simp      switch (ABE->getOpcode()) {
238220059Sjpaetzel      default:
239220059Sjpaetzel        return false;
240209513Simp      case MCBinaryExpr::Sub:
241209513Simp        // Negate RHS and add.
242209513Simp        return EvaluateSymbolicAdd(LHSValue,
243209513Simp                                   RHSValue.getSymB(), RHSValue.getSymA(),
244209513Simp                                   -RHSValue.getConstant(),
245209513Simp                                   Res);
246209513Simp
247209513Simp      case MCBinaryExpr::Add:
248209513Simp        return EvaluateSymbolicAdd(LHSValue,
249209513Simp                                   RHSValue.getSymA(), RHSValue.getSymB(),
250209513Simp                                   RHSValue.getConstant(),
251209513Simp                                   Res);
252220059Sjpaetzel      }
253220059Sjpaetzel    }
254217229Sjpaetzel
255220059Sjpaetzel    // FIXME: We need target hooks for the evaluation. It may be limited in
256209513Simp    // width, and gas defines the result of comparisons differently from Apple
257217229Sjpaetzel    // as (the result is sign extended).
258220059Sjpaetzel    int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
259217229Sjpaetzel    int64_t Result = 0;
260227368Sjpaetzel    switch (ABE->getOpcode()) {
261227368Sjpaetzel    case MCBinaryExpr::Add:  Result = LHS + RHS; break;
262227368Sjpaetzel    case MCBinaryExpr::And:  Result = LHS & RHS; break;
263209513Simp    case MCBinaryExpr::Div:  Result = LHS / RHS; break;
264209513Simp    case MCBinaryExpr::EQ:   Result = LHS == RHS; break;
265209513Simp    case MCBinaryExpr::GT:   Result = LHS > RHS; break;
266220059Sjpaetzel    case MCBinaryExpr::GTE:  Result = LHS >= RHS; break;
267220059Sjpaetzel    case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
268217229Sjpaetzel    case MCBinaryExpr::LOr:  Result = LHS || RHS; break;
269209513Simp    case MCBinaryExpr::LT:   Result = LHS < RHS; break;
270209513Simp    case MCBinaryExpr::LTE:  Result = LHS <= RHS; break;
271217229Sjpaetzel    case MCBinaryExpr::Mod:  Result = LHS % RHS; break;
272217229Sjpaetzel    case MCBinaryExpr::Mul:  Result = LHS * RHS; break;
273217229Sjpaetzel    case MCBinaryExpr::NE:   Result = LHS != RHS; break;
274227368Sjpaetzel    case MCBinaryExpr::Or:   Result = LHS | RHS; break;
275227368Sjpaetzel    case MCBinaryExpr::Shl:  Result = LHS << RHS; break;
276227368Sjpaetzel    case MCBinaryExpr::Shr:  Result = LHS >> RHS; break;
277217229Sjpaetzel    case MCBinaryExpr::Sub:  Result = LHS - RHS; break;
278217229Sjpaetzel    case MCBinaryExpr::Xor:  Result = LHS ^ RHS; break;
279217229Sjpaetzel    }
280217229Sjpaetzel
281209513Simp    Res = MCValue::get(Result);
282209513Simp    return true;
283209513Simp  }
284209513Simp  }
285209513Simp
286209513Simp  assert(0 && "Invalid assembly expression kind!");
287209513Simp  return false;
288217229Sjpaetzel}
289217229Sjpaetzel