MCExpr.cpp revision 34a9d4b3b9b7858b729a1af67afa721c048fe5e7
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#define DEBUG_TYPE "mcexpr"
11#include "llvm/MC/MCExpr.h"
12#include "llvm/ADT/Statistic.h"
13#include "llvm/ADT/StringSwitch.h"
14#include "llvm/MC/MCAsmLayout.h"
15#include "llvm/MC/MCAssembler.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCObjectWriter.h"
18#include "llvm/MC/MCSymbol.h"
19#include "llvm/MC/MCValue.h"
20#include "llvm/Support/Debug.h"
21#include "llvm/Support/ErrorHandling.h"
22#include "llvm/Support/raw_ostream.h"
23using namespace llvm;
24
25namespace {
26namespace stats {
27STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations");
28}
29}
30
31void MCExpr::print(raw_ostream &OS) const {
32  switch (getKind()) {
33  case MCExpr::Target:
34    return cast<MCTargetExpr>(this)->PrintImpl(OS);
35  case MCExpr::Constant:
36    OS << cast<MCConstantExpr>(*this).getValue();
37    return;
38
39  case MCExpr::SymbolRef: {
40    const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this);
41    const MCSymbol &Sym = SRE.getSymbol();
42    // Parenthesize names that start with $ so that they don't look like
43    // absolute names.
44    bool UseParens = Sym.getName()[0] == '$';
45
46    if (SRE.getKind() == MCSymbolRefExpr::VK_PPC_DARWIN_HA16 ||
47        SRE.getKind() == MCSymbolRefExpr::VK_PPC_DARWIN_LO16) {
48      OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
49      UseParens = true;
50    }
51
52    if (UseParens)
53      OS << '(' << Sym << ')';
54    else
55      OS << Sym;
56
57    if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_PLT ||
58        SRE.getKind() == MCSymbolRefExpr::VK_ARM_TLSGD ||
59        SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOT ||
60        SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTOFF ||
61        SRE.getKind() == MCSymbolRefExpr::VK_ARM_TPOFF ||
62        SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF ||
63        SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET1 ||
64        SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET2)
65      OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
66    else if (SRE.getKind() != MCSymbolRefExpr::VK_None &&
67             SRE.getKind() != MCSymbolRefExpr::VK_PPC_DARWIN_HA16 &&
68             SRE.getKind() != MCSymbolRefExpr::VK_PPC_DARWIN_LO16)
69      OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
70
71    return;
72  }
73
74  case MCExpr::Unary: {
75    const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this);
76    switch (UE.getOpcode()) {
77    case MCUnaryExpr::LNot:  OS << '!'; break;
78    case MCUnaryExpr::Minus: OS << '-'; break;
79    case MCUnaryExpr::Not:   OS << '~'; break;
80    case MCUnaryExpr::Plus:  OS << '+'; break;
81    }
82    OS << *UE.getSubExpr();
83    return;
84  }
85
86  case MCExpr::Binary: {
87    const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);
88
89    // Only print parens around the LHS if it is non-trivial.
90    if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
91      OS << *BE.getLHS();
92    } else {
93      OS << '(' << *BE.getLHS() << ')';
94    }
95
96    switch (BE.getOpcode()) {
97    case MCBinaryExpr::Add:
98      // Print "X-42" instead of "X+-42".
99      if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {
100        if (RHSC->getValue() < 0) {
101          OS << RHSC->getValue();
102          return;
103        }
104      }
105
106      OS <<  '+';
107      break;
108    case MCBinaryExpr::And:  OS <<  '&'; break;
109    case MCBinaryExpr::Div:  OS <<  '/'; break;
110    case MCBinaryExpr::EQ:   OS << "=="; break;
111    case MCBinaryExpr::GT:   OS <<  '>'; break;
112    case MCBinaryExpr::GTE:  OS << ">="; break;
113    case MCBinaryExpr::LAnd: OS << "&&"; break;
114    case MCBinaryExpr::LOr:  OS << "||"; break;
115    case MCBinaryExpr::LT:   OS <<  '<'; break;
116    case MCBinaryExpr::LTE:  OS << "<="; break;
117    case MCBinaryExpr::Mod:  OS <<  '%'; break;
118    case MCBinaryExpr::Mul:  OS <<  '*'; break;
119    case MCBinaryExpr::NE:   OS << "!="; break;
120    case MCBinaryExpr::Or:   OS <<  '|'; break;
121    case MCBinaryExpr::Shl:  OS << "<<"; break;
122    case MCBinaryExpr::Shr:  OS << ">>"; break;
123    case MCBinaryExpr::Sub:  OS <<  '-'; break;
124    case MCBinaryExpr::Xor:  OS <<  '^'; break;
125    }
126
127    // Only print parens around the LHS if it is non-trivial.
128    if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
129      OS << *BE.getRHS();
130    } else {
131      OS << '(' << *BE.getRHS() << ')';
132    }
133    return;
134  }
135  }
136
137  llvm_unreachable("Invalid expression kind!");
138}
139
140#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
141void MCExpr::dump() const {
142  print(dbgs());
143  dbgs() << '\n';
144}
145#endif
146
147/* *** */
148
149const MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS,
150                                         const MCExpr *RHS, MCContext &Ctx) {
151  return new (Ctx) MCBinaryExpr(Opc, LHS, RHS);
152}
153
154const MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr,
155                                       MCContext &Ctx) {
156  return new (Ctx) MCUnaryExpr(Opc, Expr);
157}
158
159const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) {
160  return new (Ctx) MCConstantExpr(Value);
161}
162
163/* *** */
164
165const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym,
166                                               VariantKind Kind,
167                                               MCContext &Ctx) {
168  return new (Ctx) MCSymbolRefExpr(Sym, Kind);
169}
170
171const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind,
172                                               MCContext &Ctx) {
173  return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx);
174}
175
176StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
177  switch (Kind) {
178  case VK_Invalid: return "<<invalid>>";
179  case VK_None: return "<<none>>";
180
181  case VK_GOT: return "GOT";
182  case VK_GOTOFF: return "GOTOFF";
183  case VK_GOTPCREL: return "GOTPCREL";
184  case VK_GOTTPOFF: return "GOTTPOFF";
185  case VK_INDNTPOFF: return "INDNTPOFF";
186  case VK_NTPOFF: return "NTPOFF";
187  case VK_GOTNTPOFF: return "GOTNTPOFF";
188  case VK_PLT: return "PLT";
189  case VK_TLSGD: return "TLSGD";
190  case VK_TLSLD: return "TLSLD";
191  case VK_TLSLDM: return "TLSLDM";
192  case VK_TPOFF: return "TPOFF";
193  case VK_DTPOFF: return "DTPOFF";
194  case VK_TLVP: return "TLVP";
195  case VK_SECREL: return "SECREL";
196  case VK_ARM_PLT: return "(PLT)";
197  case VK_ARM_GOT: return "(GOT)";
198  case VK_ARM_GOTOFF: return "(GOTOFF)";
199  case VK_ARM_TPOFF: return "(tpoff)";
200  case VK_ARM_GOTTPOFF: return "(gottpoff)";
201  case VK_ARM_TLSGD: return "(tlsgd)";
202  case VK_ARM_TARGET1: return "(target1)";
203  case VK_ARM_TARGET2: return "(target2)";
204  case VK_PPC_TOC: return "tocbase";
205  case VK_PPC_TOC_ENTRY: return "toc";
206  case VK_PPC_DARWIN_HA16: return "ha16";
207  case VK_PPC_DARWIN_LO16: return "lo16";
208  case VK_PPC_GAS_HA16: return "ha";
209  case VK_PPC_GAS_LO16: return "l";
210  case VK_PPC_TPREL16_HA: return "tprel@ha";
211  case VK_PPC_TPREL16_LO: return "tprel@l";
212  case VK_PPC_TOC16_HA: return "toc@ha";
213  case VK_PPC_TOC16_LO: return "toc@l";
214  case VK_Mips_GPREL: return "GPREL";
215  case VK_Mips_GOT_CALL: return "GOT_CALL";
216  case VK_Mips_GOT16: return "GOT16";
217  case VK_Mips_GOT: return "GOT";
218  case VK_Mips_ABS_HI: return "ABS_HI";
219  case VK_Mips_ABS_LO: return "ABS_LO";
220  case VK_Mips_TLSGD: return "TLSGD";
221  case VK_Mips_TLSLDM: return "TLSLDM";
222  case VK_Mips_DTPREL_HI: return "DTPREL_HI";
223  case VK_Mips_DTPREL_LO: return "DTPREL_LO";
224  case VK_Mips_GOTTPREL: return "GOTTPREL";
225  case VK_Mips_TPREL_HI: return "TPREL_HI";
226  case VK_Mips_TPREL_LO: return "TPREL_LO";
227  case VK_Mips_GPOFF_HI: return "GPOFF_HI";
228  case VK_Mips_GPOFF_LO: return "GPOFF_LO";
229  case VK_Mips_GOT_DISP: return "GOT_DISP";
230  case VK_Mips_GOT_PAGE: return "GOT_PAGE";
231  case VK_Mips_GOT_OFST: return "GOT_OFST";
232  case VK_Mips_HIGHER:   return "HIGHER";
233  case VK_Mips_HIGHEST:  return "HIGHEST";
234  case VK_Mips_GOT_HI16: return "GOT_HI16";
235  case VK_Mips_GOT_LO16: return "GOT_LO16";
236  case VK_Mips_CALL_HI16: return "CALL_HI16";
237  case VK_Mips_CALL_LO16: return "CALL_LO16";
238  }
239  llvm_unreachable("Invalid variant kind");
240}
241
242MCSymbolRefExpr::VariantKind
243MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
244  return StringSwitch<VariantKind>(Name)
245    .Case("GOT", VK_GOT)
246    .Case("got", VK_GOT)
247    .Case("GOTOFF", VK_GOTOFF)
248    .Case("gotoff", VK_GOTOFF)
249    .Case("GOTPCREL", VK_GOTPCREL)
250    .Case("gotpcrel", VK_GOTPCREL)
251    .Case("GOTTPOFF", VK_GOTTPOFF)
252    .Case("gottpoff", VK_GOTTPOFF)
253    .Case("INDNTPOFF", VK_INDNTPOFF)
254    .Case("indntpoff", VK_INDNTPOFF)
255    .Case("NTPOFF", VK_NTPOFF)
256    .Case("ntpoff", VK_NTPOFF)
257    .Case("GOTNTPOFF", VK_GOTNTPOFF)
258    .Case("gotntpoff", VK_GOTNTPOFF)
259    .Case("PLT", VK_PLT)
260    .Case("plt", VK_PLT)
261    .Case("TLSGD", VK_TLSGD)
262    .Case("tlsgd", VK_TLSGD)
263    .Case("TLSLD", VK_TLSLD)
264    .Case("tlsld", VK_TLSLD)
265    .Case("TLSLDM", VK_TLSLDM)
266    .Case("tlsldm", VK_TLSLDM)
267    .Case("TPOFF", VK_TPOFF)
268    .Case("tpoff", VK_TPOFF)
269    .Case("DTPOFF", VK_DTPOFF)
270    .Case("dtpoff", VK_DTPOFF)
271    .Case("TLVP", VK_TLVP)
272    .Case("tlvp", VK_TLVP)
273    .Default(VK_Invalid);
274}
275
276/* *** */
277
278void MCTargetExpr::anchor() {}
279
280/* *** */
281
282bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const {
283  return EvaluateAsAbsolute(Res, 0, 0, 0);
284}
285
286bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
287                                const MCAsmLayout &Layout) const {
288  return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0);
289}
290
291bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
292                                const MCAsmLayout &Layout,
293                                const SectionAddrMap &Addrs) const {
294  return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs);
295}
296
297bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
298  return EvaluateAsAbsolute(Res, &Asm, 0, 0);
299}
300
301bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
302                                const MCAsmLayout *Layout,
303                                const SectionAddrMap *Addrs) const {
304  MCValue Value;
305
306  // Fast path constants.
307  if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) {
308    Res = CE->getValue();
309    return true;
310  }
311
312  // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us
313  // absolutize differences across sections and that is what the MachO writer
314  // uses Addrs for.
315  bool IsRelocatable =
316    EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs);
317
318  // Record the current value.
319  Res = Value.getConstant();
320
321  return IsRelocatable && Value.isAbsolute();
322}
323
324/// \brief Helper method for \see EvaluateSymbolAdd().
325static void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
326                                                const MCAsmLayout *Layout,
327                                                const SectionAddrMap *Addrs,
328                                                bool InSet,
329                                                const MCSymbolRefExpr *&A,
330                                                const MCSymbolRefExpr *&B,
331                                                int64_t &Addend) {
332  if (!A || !B)
333    return;
334
335  const MCSymbol &SA = A->getSymbol();
336  const MCSymbol &SB = B->getSymbol();
337
338  if (SA.isUndefined() || SB.isUndefined())
339    return;
340
341  if (!Asm->getWriter().IsSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
342    return;
343
344  MCSymbolData &AD = Asm->getSymbolData(SA);
345  MCSymbolData &BD = Asm->getSymbolData(SB);
346
347  if (AD.getFragment() == BD.getFragment()) {
348    Addend += (AD.getOffset() - BD.getOffset());
349
350    // Pointers to Thumb symbols need to have their low-bit set to allow
351    // for interworking.
352    if (Asm->isThumbFunc(&SA))
353      Addend |= 1;
354
355    // Clear the symbol expr pointers to indicate we have folded these
356    // operands.
357    A = B = 0;
358    return;
359  }
360
361  if (!Layout)
362    return;
363
364  const MCSectionData &SecA = *AD.getFragment()->getParent();
365  const MCSectionData &SecB = *BD.getFragment()->getParent();
366
367  if ((&SecA != &SecB) && !Addrs)
368    return;
369
370  // Eagerly evaluate.
371  Addend += (Layout->getSymbolOffset(&Asm->getSymbolData(A->getSymbol())) -
372             Layout->getSymbolOffset(&Asm->getSymbolData(B->getSymbol())));
373  if (Addrs && (&SecA != &SecB))
374    Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB));
375
376  // Pointers to Thumb symbols need to have their low-bit set to allow
377  // for interworking.
378  if (Asm->isThumbFunc(&SA))
379    Addend |= 1;
380
381  // Clear the symbol expr pointers to indicate we have folded these
382  // operands.
383  A = B = 0;
384}
385
386/// \brief Evaluate the result of an add between (conceptually) two MCValues.
387///
388/// This routine conceptually attempts to construct an MCValue:
389///   Result = (Result_A - Result_B + Result_Cst)
390/// from two MCValue's LHS and RHS where
391///   Result = LHS + RHS
392/// and
393///   Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
394///
395/// This routine attempts to aggresively fold the operands such that the result
396/// is representable in an MCValue, but may not always succeed.
397///
398/// \returns True on success, false if the result is not representable in an
399/// MCValue.
400
401/// NOTE: It is really important to have both the Asm and Layout arguments.
402/// They might look redundant, but this function can be used before layout
403/// is done (see the object streamer for example) and having the Asm argument
404/// lets us avoid relaxations early.
405static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
406                                const MCAsmLayout *Layout,
407                                const SectionAddrMap *Addrs,
408                                bool InSet,
409                                const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
410                                const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
411                                MCValue &Res) {
412  // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy
413  // about dealing with modifiers. This will ultimately bite us, one day.
414  const MCSymbolRefExpr *LHS_A = LHS.getSymA();
415  const MCSymbolRefExpr *LHS_B = LHS.getSymB();
416  int64_t LHS_Cst = LHS.getConstant();
417
418  // Fold the result constant immediately.
419  int64_t Result_Cst = LHS_Cst + RHS_Cst;
420
421  assert((!Layout || Asm) &&
422         "Must have an assembler object if layout is given!");
423
424  // If we have a layout, we can fold resolved differences.
425  if (Asm) {
426    // First, fold out any differences which are fully resolved. By
427    // reassociating terms in
428    //   Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
429    // we have the four possible differences:
430    //   (LHS_A - LHS_B),
431    //   (LHS_A - RHS_B),
432    //   (RHS_A - LHS_B),
433    //   (RHS_A - RHS_B).
434    // Since we are attempting to be as aggressive as possible about folding, we
435    // attempt to evaluate each possible alternative.
436    AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B,
437                                        Result_Cst);
438    AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B,
439                                        Result_Cst);
440    AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B,
441                                        Result_Cst);
442    AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B,
443                                        Result_Cst);
444  }
445
446  // We can't represent the addition or subtraction of two symbols.
447  if ((LHS_A && RHS_A) || (LHS_B && RHS_B))
448    return false;
449
450  // At this point, we have at most one additive symbol and one subtractive
451  // symbol -- find them.
452  const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A;
453  const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B;
454
455  // If we have a negated symbol, then we must have also have a non-negated
456  // symbol in order to encode the expression.
457  if (B && !A)
458    return false;
459
460  Res = MCValue::get(A, B, Result_Cst);
461  return true;
462}
463
464bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
465                                   const MCAsmLayout &Layout) const {
466  return EvaluateAsRelocatableImpl(Res, &Layout.getAssembler(), &Layout,
467                                   0, false);
468}
469
470bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
471                                       const MCAssembler *Asm,
472                                       const MCAsmLayout *Layout,
473                                       const SectionAddrMap *Addrs,
474                                       bool InSet) const {
475  ++stats::MCExprEvaluate;
476
477  switch (getKind()) {
478  case Target:
479    return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout);
480
481  case Constant:
482    Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
483    return true;
484
485  case SymbolRef: {
486    const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
487    const MCSymbol &Sym = SRE->getSymbol();
488
489    // Evaluate recursively if this is a variable.
490    if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
491      bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm,
492                                                                   Layout,
493                                                                   Addrs,
494                                                                   true);
495      // If we failed to simplify this to a constant, let the target
496      // handle it.
497      if (Ret && !Res.getSymA() && !Res.getSymB())
498        return true;
499    }
500
501    Res = MCValue::get(SRE, 0, 0);
502    return true;
503  }
504
505  case Unary: {
506    const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
507    MCValue Value;
508
509    if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
510                                                      Addrs, InSet))
511      return false;
512
513    switch (AUE->getOpcode()) {
514    case MCUnaryExpr::LNot:
515      if (!Value.isAbsolute())
516        return false;
517      Res = MCValue::get(!Value.getConstant());
518      break;
519    case MCUnaryExpr::Minus:
520      /// -(a - b + const) ==> (b - a - const)
521      if (Value.getSymA() && !Value.getSymB())
522        return false;
523      Res = MCValue::get(Value.getSymB(), Value.getSymA(),
524                         -Value.getConstant());
525      break;
526    case MCUnaryExpr::Not:
527      if (!Value.isAbsolute())
528        return false;
529      Res = MCValue::get(~Value.getConstant());
530      break;
531    case MCUnaryExpr::Plus:
532      Res = Value;
533      break;
534    }
535
536    return true;
537  }
538
539  case Binary: {
540    const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
541    MCValue LHSValue, RHSValue;
542
543    if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
544                                                  Addrs, InSet) ||
545        !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
546                                                  Addrs, InSet))
547      return false;
548
549    // We only support a few operations on non-constant expressions, handle
550    // those first.
551    if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
552      switch (ABE->getOpcode()) {
553      default:
554        return false;
555      case MCBinaryExpr::Sub:
556        // Negate RHS and add.
557        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
558                                   RHSValue.getSymB(), RHSValue.getSymA(),
559                                   -RHSValue.getConstant(),
560                                   Res);
561
562      case MCBinaryExpr::Add:
563        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
564                                   RHSValue.getSymA(), RHSValue.getSymB(),
565                                   RHSValue.getConstant(),
566                                   Res);
567      }
568    }
569
570    // FIXME: We need target hooks for the evaluation. It may be limited in
571    // width, and gas defines the result of comparisons and right shifts
572    // differently from Apple as.
573    int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
574    int64_t Result = 0;
575    switch (ABE->getOpcode()) {
576    case MCBinaryExpr::Add:  Result = LHS + RHS; break;
577    case MCBinaryExpr::And:  Result = LHS & RHS; break;
578    case MCBinaryExpr::Div:  Result = LHS / RHS; break;
579    case MCBinaryExpr::EQ:   Result = LHS == RHS; break;
580    case MCBinaryExpr::GT:   Result = LHS > RHS; break;
581    case MCBinaryExpr::GTE:  Result = LHS >= RHS; break;
582    case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
583    case MCBinaryExpr::LOr:  Result = LHS || RHS; break;
584    case MCBinaryExpr::LT:   Result = LHS < RHS; break;
585    case MCBinaryExpr::LTE:  Result = LHS <= RHS; break;
586    case MCBinaryExpr::Mod:  Result = LHS % RHS; break;
587    case MCBinaryExpr::Mul:  Result = LHS * RHS; break;
588    case MCBinaryExpr::NE:   Result = LHS != RHS; break;
589    case MCBinaryExpr::Or:   Result = LHS | RHS; break;
590    case MCBinaryExpr::Shl:  Result = LHS << RHS; break;
591    case MCBinaryExpr::Shr:  Result = LHS >> RHS; break;
592    case MCBinaryExpr::Sub:  Result = LHS - RHS; break;
593    case MCBinaryExpr::Xor:  Result = LHS ^ RHS; break;
594    }
595
596    Res = MCValue::get(Result);
597    return true;
598  }
599  }
600
601  llvm_unreachable("Invalid assembly expression kind!");
602}
603
604const MCSection *MCExpr::FindAssociatedSection() const {
605  switch (getKind()) {
606  case Target:
607    // We never look through target specific expressions.
608    return cast<MCTargetExpr>(this)->FindAssociatedSection();
609
610  case Constant:
611    return MCSymbol::AbsolutePseudoSection;
612
613  case SymbolRef: {
614    const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
615    const MCSymbol &Sym = SRE->getSymbol();
616
617    if (Sym.isDefined())
618      return &Sym.getSection();
619
620    return 0;
621  }
622
623  case Unary:
624    return cast<MCUnaryExpr>(this)->getSubExpr()->FindAssociatedSection();
625
626  case Binary: {
627    const MCBinaryExpr *BE = cast<MCBinaryExpr>(this);
628    const MCSection *LHS_S = BE->getLHS()->FindAssociatedSection();
629    const MCSection *RHS_S = BE->getRHS()->FindAssociatedSection();
630
631    // If either section is absolute, return the other.
632    if (LHS_S == MCSymbol::AbsolutePseudoSection)
633      return RHS_S;
634    if (RHS_S == MCSymbol::AbsolutePseudoSection)
635      return LHS_S;
636
637    // Otherwise, return the first non-null section.
638    return LHS_S ? LHS_S : RHS_S;
639  }
640  }
641
642  llvm_unreachable("Invalid assembly expression kind!");
643}
644