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