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