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