MCExpr.cpp revision 4e815f8a8cae6c846cdca52420046cab902865de
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/ADT/StringSwitch.h"
12#include "llvm/MC/MCAsmLayout.h"
13#include "llvm/MC/MCAssembler.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCSymbol.h"
16#include "llvm/MC/MCValue.h"
17#include "llvm/Support/Debug.h"
18#include "llvm/Support/raw_ostream.h"
19#include "llvm/Target/TargetAsmBackend.h"
20using namespace llvm;
21
22void MCExpr::print(raw_ostream &OS) const {
23  switch (getKind()) {
24  case MCExpr::Target:
25    return cast<MCTargetExpr>(this)->PrintImpl(OS);
26  case MCExpr::Constant:
27    OS << cast<MCConstantExpr>(*this).getValue();
28    return;
29
30  case MCExpr::SymbolRef: {
31    const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this);
32    const MCSymbol &Sym = SRE.getSymbol();
33
34    // Parenthesize names that start with $ so that they don't look like
35    // absolute names.
36    if (Sym.getName()[0] == '$')
37      OS << '(' << Sym << ')';
38    else
39      OS << Sym;
40
41    if (SRE.getKind() != MCSymbolRefExpr::VK_None)
42      OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
43
44    return;
45  }
46
47  case MCExpr::Unary: {
48    const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this);
49    switch (UE.getOpcode()) {
50    default: assert(0 && "Invalid opcode!");
51    case MCUnaryExpr::LNot:  OS << '!'; break;
52    case MCUnaryExpr::Minus: OS << '-'; break;
53    case MCUnaryExpr::Not:   OS << '~'; break;
54    case MCUnaryExpr::Plus:  OS << '+'; break;
55    }
56    OS << *UE.getSubExpr();
57    return;
58  }
59
60  case MCExpr::Binary: {
61    const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);
62
63    // Only print parens around the LHS if it is non-trivial.
64    if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
65      OS << *BE.getLHS();
66    } else {
67      OS << '(' << *BE.getLHS() << ')';
68    }
69
70    switch (BE.getOpcode()) {
71    default: assert(0 && "Invalid opcode!");
72    case MCBinaryExpr::Add:
73      // Print "X-42" instead of "X+-42".
74      if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {
75        if (RHSC->getValue() < 0) {
76          OS << RHSC->getValue();
77          return;
78        }
79      }
80
81      OS <<  '+';
82      break;
83    case MCBinaryExpr::And:  OS <<  '&'; break;
84    case MCBinaryExpr::Div:  OS <<  '/'; break;
85    case MCBinaryExpr::EQ:   OS << "=="; break;
86    case MCBinaryExpr::GT:   OS <<  '>'; break;
87    case MCBinaryExpr::GTE:  OS << ">="; break;
88    case MCBinaryExpr::LAnd: OS << "&&"; break;
89    case MCBinaryExpr::LOr:  OS << "||"; break;
90    case MCBinaryExpr::LT:   OS <<  '<'; break;
91    case MCBinaryExpr::LTE:  OS << "<="; break;
92    case MCBinaryExpr::Mod:  OS <<  '%'; break;
93    case MCBinaryExpr::Mul:  OS <<  '*'; break;
94    case MCBinaryExpr::NE:   OS << "!="; break;
95    case MCBinaryExpr::Or:   OS <<  '|'; break;
96    case MCBinaryExpr::Shl:  OS << "<<"; break;
97    case MCBinaryExpr::Shr:  OS << ">>"; break;
98    case MCBinaryExpr::Sub:  OS <<  '-'; break;
99    case MCBinaryExpr::Xor:  OS <<  '^'; break;
100    }
101
102    // Only print parens around the LHS if it is non-trivial.
103    if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
104      OS << *BE.getRHS();
105    } else {
106      OS << '(' << *BE.getRHS() << ')';
107    }
108    return;
109  }
110  }
111
112  assert(0 && "Invalid expression kind!");
113}
114
115void MCExpr::dump() const {
116  print(dbgs());
117  dbgs() << '\n';
118}
119
120/* *** */
121
122const MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS,
123                                         const MCExpr *RHS, MCContext &Ctx) {
124  return new (Ctx) MCBinaryExpr(Opc, LHS, RHS);
125}
126
127const MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr,
128                                       MCContext &Ctx) {
129  return new (Ctx) MCUnaryExpr(Opc, Expr);
130}
131
132const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) {
133  return new (Ctx) MCConstantExpr(Value);
134}
135
136/* *** */
137
138const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym,
139                                               VariantKind Kind,
140                                               MCContext &Ctx) {
141  return new (Ctx) MCSymbolRefExpr(Sym, Kind);
142}
143
144const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind,
145                                               MCContext &Ctx) {
146  return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx);
147}
148
149const MCSymbolRefExpr *MCSymbolRefExpr::CreateTemp(StringRef Name,
150                                                   VariantKind Kind,
151                                                   MCContext &Ctx) {
152  return Create(Ctx.GetOrCreateTemporarySymbol(Name), Kind, Ctx);
153}
154
155StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
156  switch (Kind) {
157  default:
158  case VK_Invalid: return "<<invalid>>";
159  case VK_None: return "<<none>>";
160
161  case VK_GOT: return "GOT";
162  case VK_GOTOFF: return "GOTOFF";
163  case VK_GOTPCREL: return "GOTPCREL";
164  case VK_GOTTPOFF: return "GOTTPOFF";
165  case VK_INDNTPOFF: return "INDNTPOFF";
166  case VK_NTPOFF: return "NTPOFF";
167  case VK_PLT: return "PLT";
168  case VK_TLSGD: return "TLSGD";
169  case VK_TPOFF: return "TPOFF";
170  }
171}
172
173MCSymbolRefExpr::VariantKind
174MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
175  return StringSwitch<VariantKind>(Name)
176    .Case("GOT", VK_GOT)
177    .Case("GOTOFF", VK_GOTOFF)
178    .Case("GOTPCREL", VK_GOTPCREL)
179    .Case("GOTTPOFF", VK_GOTTPOFF)
180    .Case("INDNTPOFF", VK_INDNTPOFF)
181    .Case("NTPOFF", VK_NTPOFF)
182    .Case("PLT", VK_PLT)
183    .Case("TLSGD", VK_TLSGD)
184    .Case("TPOFF", VK_TPOFF)
185    .Default(VK_Invalid);
186}
187
188/* *** */
189
190void MCTargetExpr::Anchor() {}
191
192/* *** */
193
194bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const {
195  MCValue Value;
196
197  if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute())
198    return false;
199
200  Res = Value.getConstant();
201  return true;
202}
203
204static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A,
205                                const MCSymbol *RHS_B, int64_t RHS_Cst,
206                                MCValue &Res) {
207  // We can't add or subtract two symbols.
208  if ((LHS.getSymA() && RHS_A) ||
209      (LHS.getSymB() && RHS_B))
210    return false;
211
212  const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
213  const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
214  if (B) {
215    // If we have a negated symbol, then we must have also have a non-negated
216    // symbol in order to encode the expression. We can do this check later to
217    // permit expressions which eventually fold to a representable form -- such
218    // as (a + (0 - b)) -- if necessary.
219    if (!A)
220      return false;
221  }
222  Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
223  return true;
224}
225
226bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
227                                   const MCAsmLayout *Layout) const {
228  switch (getKind()) {
229  case Target:
230    return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout);
231
232  case Constant:
233    Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
234    return true;
235
236  case SymbolRef: {
237    const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol();
238
239    // Evaluate recursively if this is a variable.
240    if (Sym.isVariable()) {
241      if (!Sym.getValue()->EvaluateAsRelocatable(Res, Layout))
242        return false;
243
244      // Absolutize symbol differences between defined symbols when we have a
245      // layout object and the target requests it.
246      if (Layout && Res.getSymB() &&
247          Layout->getAssembler().getBackend().hasAbsolutizedSet() &&
248          Res.getSymA()->isDefined() && Res.getSymB()->isDefined()) {
249        MCSymbolData &A = Layout->getAssembler().getSymbolData(*Res.getSymA());
250        MCSymbolData &B = Layout->getAssembler().getSymbolData(*Res.getSymB());
251        Res = MCValue::get(+ A.getFragment()->getAddress() + A.getOffset()
252                           - B.getFragment()->getAddress() - B.getOffset()
253                           + Res.getConstant());
254      }
255
256      return true;
257    }
258
259    Res = MCValue::get(&Sym, 0, 0);
260    return true;
261  }
262
263  case Unary: {
264    const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
265    MCValue Value;
266
267    if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout))
268      return false;
269
270    switch (AUE->getOpcode()) {
271    case MCUnaryExpr::LNot:
272      if (!Value.isAbsolute())
273        return false;
274      Res = MCValue::get(!Value.getConstant());
275      break;
276    case MCUnaryExpr::Minus:
277      /// -(a - b + const) ==> (b - a - const)
278      if (Value.getSymA() && !Value.getSymB())
279        return false;
280      Res = MCValue::get(Value.getSymB(), Value.getSymA(),
281                         -Value.getConstant());
282      break;
283    case MCUnaryExpr::Not:
284      if (!Value.isAbsolute())
285        return false;
286      Res = MCValue::get(~Value.getConstant());
287      break;
288    case MCUnaryExpr::Plus:
289      Res = Value;
290      break;
291    }
292
293    return true;
294  }
295
296  case Binary: {
297    const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
298    MCValue LHSValue, RHSValue;
299
300    if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) ||
301        !ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout))
302      return false;
303
304    // We only support a few operations on non-constant expressions, handle
305    // those first.
306    if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
307      switch (ABE->getOpcode()) {
308      default:
309        return false;
310      case MCBinaryExpr::Sub:
311        // Negate RHS and add.
312        return EvaluateSymbolicAdd(LHSValue,
313                                   RHSValue.getSymB(), RHSValue.getSymA(),
314                                   -RHSValue.getConstant(),
315                                   Res);
316
317      case MCBinaryExpr::Add:
318        return EvaluateSymbolicAdd(LHSValue,
319                                   RHSValue.getSymA(), RHSValue.getSymB(),
320                                   RHSValue.getConstant(),
321                                   Res);
322      }
323    }
324
325    // FIXME: We need target hooks for the evaluation. It may be limited in
326    // width, and gas defines the result of comparisons and right shifts
327    // differently from Apple as.
328    int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
329    int64_t Result = 0;
330    switch (ABE->getOpcode()) {
331    case MCBinaryExpr::Add:  Result = LHS + RHS; break;
332    case MCBinaryExpr::And:  Result = LHS & RHS; break;
333    case MCBinaryExpr::Div:  Result = LHS / RHS; break;
334    case MCBinaryExpr::EQ:   Result = LHS == RHS; break;
335    case MCBinaryExpr::GT:   Result = LHS > RHS; break;
336    case MCBinaryExpr::GTE:  Result = LHS >= RHS; break;
337    case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
338    case MCBinaryExpr::LOr:  Result = LHS || RHS; break;
339    case MCBinaryExpr::LT:   Result = LHS < RHS; break;
340    case MCBinaryExpr::LTE:  Result = LHS <= RHS; break;
341    case MCBinaryExpr::Mod:  Result = LHS % RHS; break;
342    case MCBinaryExpr::Mul:  Result = LHS * RHS; break;
343    case MCBinaryExpr::NE:   Result = LHS != RHS; break;
344    case MCBinaryExpr::Or:   Result = LHS | RHS; break;
345    case MCBinaryExpr::Shl:  Result = LHS << RHS; break;
346    case MCBinaryExpr::Shr:  Result = LHS >> RHS; break;
347    case MCBinaryExpr::Sub:  Result = LHS - RHS; break;
348    case MCBinaryExpr::Xor:  Result = LHS ^ RHS; break;
349    }
350
351    Res = MCValue::get(Result);
352    return true;
353  }
354  }
355
356  assert(0 && "Invalid assembly expression kind!");
357  return false;
358}
359