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