1198090Srdivacky//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
2198090Srdivacky//
3198090Srdivacky//                     The LLVM Compiler Infrastructure
4198090Srdivacky//
5198090Srdivacky// This file is distributed under the University of Illinois Open Source
6198090Srdivacky// License. See LICENSE.TXT for details.
7198090Srdivacky//
8198090Srdivacky//===----------------------------------------------------------------------===//
9198090Srdivacky
10206083Srdivacky#define DEBUG_TYPE "mcexpr"
11198090Srdivacky#include "llvm/MC/MCExpr.h"
12206083Srdivacky#include "llvm/ADT/Statistic.h"
13205218Srdivacky#include "llvm/ADT/StringSwitch.h"
14205218Srdivacky#include "llvm/MC/MCAsmLayout.h"
15205218Srdivacky#include "llvm/MC/MCAssembler.h"
16198090Srdivacky#include "llvm/MC/MCContext.h"
17234353Sdim#include "llvm/MC/MCObjectWriter.h"
18198090Srdivacky#include "llvm/MC/MCSymbol.h"
19198090Srdivacky#include "llvm/MC/MCValue.h"
20202375Srdivacky#include "llvm/Support/Debug.h"
21234353Sdim#include "llvm/Support/ErrorHandling.h"
22198090Srdivacky#include "llvm/Support/raw_ostream.h"
23198090Srdivackyusing namespace llvm;
24198090Srdivacky
25206083Srdivackynamespace {
26206083Srdivackynamespace stats {
27206083SrdivackySTATISTIC(MCExprEvaluate, "Number of MCExpr evaluations");
28206083Srdivacky}
29206083Srdivacky}
30206083Srdivacky
31202878Srdivackyvoid MCExpr::print(raw_ostream &OS) const {
32198090Srdivacky  switch (getKind()) {
33203954Srdivacky  case MCExpr::Target:
34203954Srdivacky    return cast<MCTargetExpr>(this)->PrintImpl(OS);
35198090Srdivacky  case MCExpr::Constant:
36198090Srdivacky    OS << cast<MCConstantExpr>(*this).getValue();
37198090Srdivacky    return;
38198090Srdivacky
39198090Srdivacky  case MCExpr::SymbolRef: {
40205218Srdivacky    const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this);
41205218Srdivacky    const MCSymbol &Sym = SRE.getSymbol();
42218893Sdim    // Parenthesize names that start with $ so that they don't look like
43218893Sdim    // absolute names.
44218893Sdim    bool UseParens = Sym.getName()[0] == '$';
45218893Sdim    if (UseParens)
46202878Srdivacky      OS << '(' << Sym << ')';
47202878Srdivacky    else
48202878Srdivacky      OS << Sym;
49205218Srdivacky
50249423Sdim    if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_NONE ||
51249423Sdim        SRE.getKind() == MCSymbolRefExpr::VK_ARM_PLT ||
52218893Sdim        SRE.getKind() == MCSymbolRefExpr::VK_ARM_TLSGD ||
53218893Sdim        SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOT ||
54218893Sdim        SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTOFF ||
55218893Sdim        SRE.getKind() == MCSymbolRefExpr::VK_ARM_TPOFF ||
56234353Sdim        SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF ||
57243830Sdim        SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET1 ||
58249423Sdim        SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET2 ||
59249423Sdim        SRE.getKind() == MCSymbolRefExpr::VK_ARM_PREL31)
60218893Sdim      OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
61263508Sdim    else if (SRE.getKind() != MCSymbolRefExpr::VK_None)
62205218Srdivacky      OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind());
63205218Srdivacky
64198090Srdivacky    return;
65198090Srdivacky  }
66198090Srdivacky
67198090Srdivacky  case MCExpr::Unary: {
68198090Srdivacky    const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this);
69198090Srdivacky    switch (UE.getOpcode()) {
70198090Srdivacky    case MCUnaryExpr::LNot:  OS << '!'; break;
71198090Srdivacky    case MCUnaryExpr::Minus: OS << '-'; break;
72198090Srdivacky    case MCUnaryExpr::Not:   OS << '~'; break;
73198090Srdivacky    case MCUnaryExpr::Plus:  OS << '+'; break;
74198090Srdivacky    }
75202878Srdivacky    OS << *UE.getSubExpr();
76198090Srdivacky    return;
77198090Srdivacky  }
78198090Srdivacky
79198090Srdivacky  case MCExpr::Binary: {
80198090Srdivacky    const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);
81205407Srdivacky
82198090Srdivacky    // Only print parens around the LHS if it is non-trivial.
83198090Srdivacky    if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
84202878Srdivacky      OS << *BE.getLHS();
85198090Srdivacky    } else {
86202878Srdivacky      OS << '(' << *BE.getLHS() << ')';
87198090Srdivacky    }
88205407Srdivacky
89198090Srdivacky    switch (BE.getOpcode()) {
90198090Srdivacky    case MCBinaryExpr::Add:
91198090Srdivacky      // Print "X-42" instead of "X+-42".
92198090Srdivacky      if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {
93198090Srdivacky        if (RHSC->getValue() < 0) {
94198090Srdivacky          OS << RHSC->getValue();
95198090Srdivacky          return;
96198090Srdivacky        }
97198090Srdivacky      }
98205407Srdivacky
99198090Srdivacky      OS <<  '+';
100198090Srdivacky      break;
101198090Srdivacky    case MCBinaryExpr::And:  OS <<  '&'; break;
102198090Srdivacky    case MCBinaryExpr::Div:  OS <<  '/'; break;
103198090Srdivacky    case MCBinaryExpr::EQ:   OS << "=="; break;
104198090Srdivacky    case MCBinaryExpr::GT:   OS <<  '>'; break;
105198090Srdivacky    case MCBinaryExpr::GTE:  OS << ">="; break;
106198090Srdivacky    case MCBinaryExpr::LAnd: OS << "&&"; break;
107198090Srdivacky    case MCBinaryExpr::LOr:  OS << "||"; break;
108198090Srdivacky    case MCBinaryExpr::LT:   OS <<  '<'; break;
109198090Srdivacky    case MCBinaryExpr::LTE:  OS << "<="; break;
110198090Srdivacky    case MCBinaryExpr::Mod:  OS <<  '%'; break;
111198090Srdivacky    case MCBinaryExpr::Mul:  OS <<  '*'; break;
112198090Srdivacky    case MCBinaryExpr::NE:   OS << "!="; break;
113198090Srdivacky    case MCBinaryExpr::Or:   OS <<  '|'; break;
114198090Srdivacky    case MCBinaryExpr::Shl:  OS << "<<"; break;
115198090Srdivacky    case MCBinaryExpr::Shr:  OS << ">>"; break;
116198090Srdivacky    case MCBinaryExpr::Sub:  OS <<  '-'; break;
117198090Srdivacky    case MCBinaryExpr::Xor:  OS <<  '^'; break;
118198090Srdivacky    }
119205407Srdivacky
120198090Srdivacky    // Only print parens around the LHS if it is non-trivial.
121198090Srdivacky    if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
122202878Srdivacky      OS << *BE.getRHS();
123198090Srdivacky    } else {
124202878Srdivacky      OS << '(' << *BE.getRHS() << ')';
125198090Srdivacky    }
126198090Srdivacky    return;
127198090Srdivacky  }
128198090Srdivacky  }
129198090Srdivacky
130234353Sdim  llvm_unreachable("Invalid expression kind!");
131198090Srdivacky}
132198090Srdivacky
133243830Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
134198090Srdivackyvoid MCExpr::dump() const {
135202878Srdivacky  print(dbgs());
136202375Srdivacky  dbgs() << '\n';
137198090Srdivacky}
138243830Sdim#endif
139198090Srdivacky
140198090Srdivacky/* *** */
141198090Srdivacky
142198090Srdivackyconst MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS,
143198090Srdivacky                                         const MCExpr *RHS, MCContext &Ctx) {
144198090Srdivacky  return new (Ctx) MCBinaryExpr(Opc, LHS, RHS);
145198090Srdivacky}
146198090Srdivacky
147198090Srdivackyconst MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr,
148198090Srdivacky                                       MCContext &Ctx) {
149198090Srdivacky  return new (Ctx) MCUnaryExpr(Opc, Expr);
150198090Srdivacky}
151198090Srdivacky
152198090Srdivackyconst MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) {
153198090Srdivacky  return new (Ctx) MCConstantExpr(Value);
154198090Srdivacky}
155198090Srdivacky
156205218Srdivacky/* *** */
157205218Srdivacky
158198090Srdivackyconst MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym,
159205218Srdivacky                                               VariantKind Kind,
160198090Srdivacky                                               MCContext &Ctx) {
161205218Srdivacky  return new (Ctx) MCSymbolRefExpr(Sym, Kind);
162198090Srdivacky}
163198090Srdivacky
164205218Srdivackyconst MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind,
165205218Srdivacky                                               MCContext &Ctx) {
166205218Srdivacky  return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx);
167198090Srdivacky}
168198090Srdivacky
169205218SrdivackyStringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
170205218Srdivacky  switch (Kind) {
171205218Srdivacky  case VK_Invalid: return "<<invalid>>";
172205218Srdivacky  case VK_None: return "<<none>>";
173205218Srdivacky
174205218Srdivacky  case VK_GOT: return "GOT";
175205218Srdivacky  case VK_GOTOFF: return "GOTOFF";
176205218Srdivacky  case VK_GOTPCREL: return "GOTPCREL";
177205218Srdivacky  case VK_GOTTPOFF: return "GOTTPOFF";
178205218Srdivacky  case VK_INDNTPOFF: return "INDNTPOFF";
179205218Srdivacky  case VK_NTPOFF: return "NTPOFF";
180218893Sdim  case VK_GOTNTPOFF: return "GOTNTPOFF";
181205218Srdivacky  case VK_PLT: return "PLT";
182205218Srdivacky  case VK_TLSGD: return "TLSGD";
183218893Sdim  case VK_TLSLD: return "TLSLD";
184218893Sdim  case VK_TLSLDM: return "TLSLDM";
185205218Srdivacky  case VK_TPOFF: return "TPOFF";
186218893Sdim  case VK_DTPOFF: return "DTPOFF";
187208599Srdivacky  case VK_TLVP: return "TLVP";
188249423Sdim  case VK_SECREL: return "SECREL32";
189249423Sdim  case VK_ARM_NONE: return "(NONE)";
190218893Sdim  case VK_ARM_PLT: return "(PLT)";
191218893Sdim  case VK_ARM_GOT: return "(GOT)";
192218893Sdim  case VK_ARM_GOTOFF: return "(GOTOFF)";
193218893Sdim  case VK_ARM_TPOFF: return "(tpoff)";
194218893Sdim  case VK_ARM_GOTTPOFF: return "(gottpoff)";
195218893Sdim  case VK_ARM_TLSGD: return "(tlsgd)";
196234353Sdim  case VK_ARM_TARGET1: return "(target1)";
197243830Sdim  case VK_ARM_TARGET2: return "(target2)";
198249423Sdim  case VK_ARM_PREL31: return "(prel31)";
199263508Sdim  case VK_PPC_LO: return "l";
200263508Sdim  case VK_PPC_HI: return "h";
201263508Sdim  case VK_PPC_HA: return "ha";
202263508Sdim  case VK_PPC_HIGHER: return "higher";
203263508Sdim  case VK_PPC_HIGHERA: return "highera";
204263508Sdim  case VK_PPC_HIGHEST: return "highest";
205263508Sdim  case VK_PPC_HIGHESTA: return "highesta";
206263508Sdim  case VK_PPC_GOT_LO: return "got@l";
207263508Sdim  case VK_PPC_GOT_HI: return "got@h";
208263508Sdim  case VK_PPC_GOT_HA: return "got@ha";
209263508Sdim  case VK_PPC_TOCBASE: return "tocbase";
210263508Sdim  case VK_PPC_TOC: return "toc";
211263508Sdim  case VK_PPC_TOC_LO: return "toc@l";
212263508Sdim  case VK_PPC_TOC_HI: return "toc@h";
213263508Sdim  case VK_PPC_TOC_HA: return "toc@ha";
214263508Sdim  case VK_PPC_DTPMOD: return "dtpmod";
215263508Sdim  case VK_PPC_TPREL: return "tprel";
216263508Sdim  case VK_PPC_TPREL_LO: return "tprel@l";
217263508Sdim  case VK_PPC_TPREL_HI: return "tprel@h";
218263508Sdim  case VK_PPC_TPREL_HA: return "tprel@ha";
219263508Sdim  case VK_PPC_TPREL_HIGHER: return "tprel@higher";
220263508Sdim  case VK_PPC_TPREL_HIGHERA: return "tprel@highera";
221263508Sdim  case VK_PPC_TPREL_HIGHEST: return "tprel@highest";
222263508Sdim  case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta";
223263508Sdim  case VK_PPC_DTPREL: return "dtprel";
224263508Sdim  case VK_PPC_DTPREL_LO: return "dtprel@l";
225263508Sdim  case VK_PPC_DTPREL_HI: return "dtprel@h";
226263508Sdim  case VK_PPC_DTPREL_HA: return "dtprel@ha";
227263508Sdim  case VK_PPC_DTPREL_HIGHER: return "dtprel@higher";
228263508Sdim  case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera";
229263508Sdim  case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest";
230263508Sdim  case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta";
231263508Sdim  case VK_PPC_GOT_TPREL: return "got@tprel";
232263508Sdim  case VK_PPC_GOT_TPREL_LO: return "got@tprel@l";
233263508Sdim  case VK_PPC_GOT_TPREL_HI: return "got@tprel@h";
234263508Sdim  case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha";
235263508Sdim  case VK_PPC_GOT_DTPREL: return "got@dtprel";
236263508Sdim  case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l";
237263508Sdim  case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h";
238263508Sdim  case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha";
239249423Sdim  case VK_PPC_TLS: return "tls";
240263508Sdim  case VK_PPC_GOT_TLSGD: return "got@tlsgd";
241263508Sdim  case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l";
242263508Sdim  case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h";
243263508Sdim  case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha";
244249423Sdim  case VK_PPC_TLSGD: return "tlsgd";
245263508Sdim  case VK_PPC_GOT_TLSLD: return "got@tlsld";
246263508Sdim  case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";
247263508Sdim  case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";
248263508Sdim  case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";
249249423Sdim  case VK_PPC_TLSLD: return "tlsld";
250234353Sdim  case VK_Mips_GPREL: return "GPREL";
251234353Sdim  case VK_Mips_GOT_CALL: return "GOT_CALL";
252234353Sdim  case VK_Mips_GOT16: return "GOT16";
253234353Sdim  case VK_Mips_GOT: return "GOT";
254234353Sdim  case VK_Mips_ABS_HI: return "ABS_HI";
255234353Sdim  case VK_Mips_ABS_LO: return "ABS_LO";
256234353Sdim  case VK_Mips_TLSGD: return "TLSGD";
257234353Sdim  case VK_Mips_TLSLDM: return "TLSLDM";
258234353Sdim  case VK_Mips_DTPREL_HI: return "DTPREL_HI";
259234353Sdim  case VK_Mips_DTPREL_LO: return "DTPREL_LO";
260234353Sdim  case VK_Mips_GOTTPREL: return "GOTTPREL";
261234353Sdim  case VK_Mips_TPREL_HI: return "TPREL_HI";
262234353Sdim  case VK_Mips_TPREL_LO: return "TPREL_LO";
263234353Sdim  case VK_Mips_GPOFF_HI: return "GPOFF_HI";
264234353Sdim  case VK_Mips_GPOFF_LO: return "GPOFF_LO";
265234353Sdim  case VK_Mips_GOT_DISP: return "GOT_DISP";
266234353Sdim  case VK_Mips_GOT_PAGE: return "GOT_PAGE";
267234353Sdim  case VK_Mips_GOT_OFST: return "GOT_OFST";
268239462Sdim  case VK_Mips_HIGHER:   return "HIGHER";
269239462Sdim  case VK_Mips_HIGHEST:  return "HIGHEST";
270244628Sdim  case VK_Mips_GOT_HI16: return "GOT_HI16";
271244628Sdim  case VK_Mips_GOT_LO16: return "GOT_LO16";
272244628Sdim  case VK_Mips_CALL_HI16: return "CALL_HI16";
273244628Sdim  case VK_Mips_CALL_LO16: return "CALL_LO16";
274251662Sdim  case VK_COFF_IMGREL32: return "IMGREL32";
275205218Srdivacky  }
276234353Sdim  llvm_unreachable("Invalid variant kind");
277205218Srdivacky}
278205218Srdivacky
279205218SrdivackyMCSymbolRefExpr::VariantKind
280205218SrdivackyMCSymbolRefExpr::getVariantKindForName(StringRef Name) {
281205218Srdivacky  return StringSwitch<VariantKind>(Name)
282205218Srdivacky    .Case("GOT", VK_GOT)
283218893Sdim    .Case("got", VK_GOT)
284205218Srdivacky    .Case("GOTOFF", VK_GOTOFF)
285218893Sdim    .Case("gotoff", VK_GOTOFF)
286205218Srdivacky    .Case("GOTPCREL", VK_GOTPCREL)
287218893Sdim    .Case("gotpcrel", VK_GOTPCREL)
288205218Srdivacky    .Case("GOTTPOFF", VK_GOTTPOFF)
289218893Sdim    .Case("gottpoff", VK_GOTTPOFF)
290205218Srdivacky    .Case("INDNTPOFF", VK_INDNTPOFF)
291218893Sdim    .Case("indntpoff", VK_INDNTPOFF)
292205218Srdivacky    .Case("NTPOFF", VK_NTPOFF)
293218893Sdim    .Case("ntpoff", VK_NTPOFF)
294218893Sdim    .Case("GOTNTPOFF", VK_GOTNTPOFF)
295218893Sdim    .Case("gotntpoff", VK_GOTNTPOFF)
296205218Srdivacky    .Case("PLT", VK_PLT)
297218893Sdim    .Case("plt", VK_PLT)
298205218Srdivacky    .Case("TLSGD", VK_TLSGD)
299218893Sdim    .Case("tlsgd", VK_TLSGD)
300218893Sdim    .Case("TLSLD", VK_TLSLD)
301218893Sdim    .Case("tlsld", VK_TLSLD)
302218893Sdim    .Case("TLSLDM", VK_TLSLDM)
303218893Sdim    .Case("tlsldm", VK_TLSLDM)
304205218Srdivacky    .Case("TPOFF", VK_TPOFF)
305218893Sdim    .Case("tpoff", VK_TPOFF)
306218893Sdim    .Case("DTPOFF", VK_DTPOFF)
307218893Sdim    .Case("dtpoff", VK_DTPOFF)
308208599Srdivacky    .Case("TLVP", VK_TLVP)
309218893Sdim    .Case("tlvp", VK_TLVP)
310251662Sdim    .Case("IMGREL", VK_COFF_IMGREL32)
311251662Sdim    .Case("imgrel", VK_COFF_IMGREL32)
312251662Sdim    .Case("SECREL32", VK_SECREL)
313251662Sdim    .Case("secrel32", VK_SECREL)
314263508Sdim    .Case("L", VK_PPC_LO)
315263508Sdim    .Case("l", VK_PPC_LO)
316263508Sdim    .Case("H", VK_PPC_HI)
317263508Sdim    .Case("h", VK_PPC_HI)
318263508Sdim    .Case("HA", VK_PPC_HA)
319263508Sdim    .Case("ha", VK_PPC_HA)
320263508Sdim    .Case("HIGHER", VK_PPC_HIGHER)
321263508Sdim    .Case("higher", VK_PPC_HIGHER)
322263508Sdim    .Case("HIGHERA", VK_PPC_HIGHERA)
323263508Sdim    .Case("highera", VK_PPC_HIGHERA)
324263508Sdim    .Case("HIGHEST", VK_PPC_HIGHEST)
325263508Sdim    .Case("highest", VK_PPC_HIGHEST)
326263508Sdim    .Case("HIGHESTA", VK_PPC_HIGHESTA)
327263508Sdim    .Case("highesta", VK_PPC_HIGHESTA)
328263508Sdim    .Case("GOT@L", VK_PPC_GOT_LO)
329263508Sdim    .Case("got@l", VK_PPC_GOT_LO)
330263508Sdim    .Case("GOT@H", VK_PPC_GOT_HI)
331263508Sdim    .Case("got@h", VK_PPC_GOT_HI)
332263508Sdim    .Case("GOT@HA", VK_PPC_GOT_HA)
333263508Sdim    .Case("got@ha", VK_PPC_GOT_HA)
334263508Sdim    .Case("TOCBASE", VK_PPC_TOCBASE)
335263508Sdim    .Case("tocbase", VK_PPC_TOCBASE)
336263508Sdim    .Case("TOC", VK_PPC_TOC)
337263508Sdim    .Case("toc", VK_PPC_TOC)
338263508Sdim    .Case("TOC@L", VK_PPC_TOC_LO)
339263508Sdim    .Case("toc@l", VK_PPC_TOC_LO)
340263508Sdim    .Case("TOC@H", VK_PPC_TOC_HI)
341263508Sdim    .Case("toc@h", VK_PPC_TOC_HI)
342263508Sdim    .Case("TOC@HA", VK_PPC_TOC_HA)
343263508Sdim    .Case("toc@ha", VK_PPC_TOC_HA)
344251662Sdim    .Case("TLS", VK_PPC_TLS)
345251662Sdim    .Case("tls", VK_PPC_TLS)
346263508Sdim    .Case("DTPMOD", VK_PPC_DTPMOD)
347263508Sdim    .Case("dtpmod", VK_PPC_DTPMOD)
348263508Sdim    .Case("TPREL", VK_PPC_TPREL)
349263508Sdim    .Case("tprel", VK_PPC_TPREL)
350263508Sdim    .Case("TPREL@L", VK_PPC_TPREL_LO)
351263508Sdim    .Case("tprel@l", VK_PPC_TPREL_LO)
352263508Sdim    .Case("TPREL@H", VK_PPC_TPREL_HI)
353263508Sdim    .Case("tprel@h", VK_PPC_TPREL_HI)
354263508Sdim    .Case("TPREL@HA", VK_PPC_TPREL_HA)
355263508Sdim    .Case("tprel@ha", VK_PPC_TPREL_HA)
356263508Sdim    .Case("TPREL@HIGHER", VK_PPC_TPREL_HIGHER)
357263508Sdim    .Case("tprel@higher", VK_PPC_TPREL_HIGHER)
358263508Sdim    .Case("TPREL@HIGHERA", VK_PPC_TPREL_HIGHERA)
359263508Sdim    .Case("tprel@highera", VK_PPC_TPREL_HIGHERA)
360263508Sdim    .Case("TPREL@HIGHEST", VK_PPC_TPREL_HIGHEST)
361263508Sdim    .Case("tprel@highest", VK_PPC_TPREL_HIGHEST)
362263508Sdim    .Case("TPREL@HIGHESTA", VK_PPC_TPREL_HIGHESTA)
363263508Sdim    .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA)
364263508Sdim    .Case("DTPREL", VK_PPC_DTPREL)
365263508Sdim    .Case("dtprel", VK_PPC_DTPREL)
366263508Sdim    .Case("DTPREL@L", VK_PPC_DTPREL_LO)
367263508Sdim    .Case("dtprel@l", VK_PPC_DTPREL_LO)
368263508Sdim    .Case("DTPREL@H", VK_PPC_DTPREL_HI)
369263508Sdim    .Case("dtprel@h", VK_PPC_DTPREL_HI)
370263508Sdim    .Case("DTPREL@HA", VK_PPC_DTPREL_HA)
371263508Sdim    .Case("dtprel@ha", VK_PPC_DTPREL_HA)
372263508Sdim    .Case("DTPREL@HIGHER", VK_PPC_DTPREL_HIGHER)
373263508Sdim    .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER)
374263508Sdim    .Case("DTPREL@HIGHERA", VK_PPC_DTPREL_HIGHERA)
375263508Sdim    .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA)
376263508Sdim    .Case("DTPREL@HIGHEST", VK_PPC_DTPREL_HIGHEST)
377263508Sdim    .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST)
378263508Sdim    .Case("DTPREL@HIGHESTA", VK_PPC_DTPREL_HIGHESTA)
379263508Sdim    .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA)
380263508Sdim    .Case("GOT@TPREL", VK_PPC_GOT_TPREL)
381263508Sdim    .Case("got@tprel", VK_PPC_GOT_TPREL)
382263508Sdim    .Case("GOT@TPREL@L", VK_PPC_GOT_TPREL_LO)
383263508Sdim    .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO)
384263508Sdim    .Case("GOT@TPREL@H", VK_PPC_GOT_TPREL_HI)
385263508Sdim    .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI)
386263508Sdim    .Case("GOT@TPREL@HA", VK_PPC_GOT_TPREL_HA)
387263508Sdim    .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA)
388263508Sdim    .Case("GOT@DTPREL", VK_PPC_GOT_DTPREL)
389263508Sdim    .Case("got@dtprel", VK_PPC_GOT_DTPREL)
390263508Sdim    .Case("GOT@DTPREL@L", VK_PPC_GOT_DTPREL_LO)
391263508Sdim    .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO)
392263508Sdim    .Case("GOT@DTPREL@H", VK_PPC_GOT_DTPREL_HI)
393263508Sdim    .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI)
394263508Sdim    .Case("GOT@DTPREL@HA", VK_PPC_GOT_DTPREL_HA)
395263508Sdim    .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA)
396263508Sdim    .Case("GOT@TLSGD", VK_PPC_GOT_TLSGD)
397263508Sdim    .Case("got@tlsgd", VK_PPC_GOT_TLSGD)
398263508Sdim    .Case("GOT@TLSGD@L", VK_PPC_GOT_TLSGD_LO)
399263508Sdim    .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO)
400263508Sdim    .Case("GOT@TLSGD@H", VK_PPC_GOT_TLSGD_HI)
401263508Sdim    .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI)
402263508Sdim    .Case("GOT@TLSGD@HA", VK_PPC_GOT_TLSGD_HA)
403263508Sdim    .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA)
404263508Sdim    .Case("GOT@TLSLD", VK_PPC_GOT_TLSLD)
405263508Sdim    .Case("got@tlsld", VK_PPC_GOT_TLSLD)
406263508Sdim    .Case("GOT@TLSLD@L", VK_PPC_GOT_TLSLD_LO)
407263508Sdim    .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO)
408263508Sdim    .Case("GOT@TLSLD@H", VK_PPC_GOT_TLSLD_HI)
409263508Sdim    .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI)
410263508Sdim    .Case("GOT@TLSLD@HA", VK_PPC_GOT_TLSLD_HA)
411263508Sdim    .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA)
412205218Srdivacky    .Default(VK_Invalid);
413205218Srdivacky}
414205218Srdivacky
415205218Srdivacky/* *** */
416205218Srdivacky
417243830Sdimvoid MCTargetExpr::anchor() {}
418198090Srdivacky
419198090Srdivacky/* *** */
420198090Srdivacky
421218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res) const {
422218893Sdim  return EvaluateAsAbsolute(Res, 0, 0, 0);
423218893Sdim}
424218893Sdim
425218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res,
426218893Sdim                                const MCAsmLayout &Layout) const {
427218893Sdim  return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0);
428218893Sdim}
429218893Sdim
430218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res,
431218893Sdim                                const MCAsmLayout &Layout,
432218893Sdim                                const SectionAddrMap &Addrs) const {
433218893Sdim  return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs);
434218893Sdim}
435218893Sdim
436218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
437218893Sdim  return EvaluateAsAbsolute(Res, &Asm, 0, 0);
438218893Sdim}
439218893Sdim
440218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
441218893Sdim                                const MCAsmLayout *Layout,
442218893Sdim                                const SectionAddrMap *Addrs) const {
443198090Srdivacky  MCValue Value;
444205407Srdivacky
445206083Srdivacky  // Fast path constants.
446206083Srdivacky  if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) {
447206083Srdivacky    Res = CE->getValue();
448206083Srdivacky    return true;
449206083Srdivacky  }
450206083Srdivacky
451218893Sdim  // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us
452218893Sdim  // absolutize differences across sections and that is what the MachO writer
453218893Sdim  // uses Addrs for.
454218893Sdim  bool IsRelocatable =
455218893Sdim    EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs);
456198090Srdivacky
457218893Sdim  // Record the current value.
458198090Srdivacky  Res = Value.getConstant();
459218893Sdim
460218893Sdim  return IsRelocatable && Value.isAbsolute();
461198090Srdivacky}
462198090Srdivacky
463218893Sdim/// \brief Helper method for \see EvaluateSymbolAdd().
464218893Sdimstatic void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
465218893Sdim                                                const MCAsmLayout *Layout,
466218893Sdim                                                const SectionAddrMap *Addrs,
467218893Sdim                                                bool InSet,
468218893Sdim                                                const MCSymbolRefExpr *&A,
469218893Sdim                                                const MCSymbolRefExpr *&B,
470218893Sdim                                                int64_t &Addend) {
471218893Sdim  if (!A || !B)
472218893Sdim    return;
473218893Sdim
474218893Sdim  const MCSymbol &SA = A->getSymbol();
475218893Sdim  const MCSymbol &SB = B->getSymbol();
476218893Sdim
477218893Sdim  if (SA.isUndefined() || SB.isUndefined())
478218893Sdim    return;
479218893Sdim
480218893Sdim  if (!Asm->getWriter().IsSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
481218893Sdim    return;
482218893Sdim
483218893Sdim  MCSymbolData &AD = Asm->getSymbolData(SA);
484218893Sdim  MCSymbolData &BD = Asm->getSymbolData(SB);
485218893Sdim
486218893Sdim  if (AD.getFragment() == BD.getFragment()) {
487218893Sdim    Addend += (AD.getOffset() - BD.getOffset());
488218893Sdim
489221345Sdim    // Pointers to Thumb symbols need to have their low-bit set to allow
490221345Sdim    // for interworking.
491221345Sdim    if (Asm->isThumbFunc(&SA))
492221345Sdim      Addend |= 1;
493221345Sdim
494218893Sdim    // Clear the symbol expr pointers to indicate we have folded these
495218893Sdim    // operands.
496218893Sdim    A = B = 0;
497218893Sdim    return;
498218893Sdim  }
499218893Sdim
500218893Sdim  if (!Layout)
501218893Sdim    return;
502218893Sdim
503218893Sdim  const MCSectionData &SecA = *AD.getFragment()->getParent();
504218893Sdim  const MCSectionData &SecB = *BD.getFragment()->getParent();
505218893Sdim
506218893Sdim  if ((&SecA != &SecB) && !Addrs)
507218893Sdim    return;
508218893Sdim
509218893Sdim  // Eagerly evaluate.
510218893Sdim  Addend += (Layout->getSymbolOffset(&Asm->getSymbolData(A->getSymbol())) -
511218893Sdim             Layout->getSymbolOffset(&Asm->getSymbolData(B->getSymbol())));
512218893Sdim  if (Addrs && (&SecA != &SecB))
513218893Sdim    Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB));
514218893Sdim
515234353Sdim  // Pointers to Thumb symbols need to have their low-bit set to allow
516234353Sdim  // for interworking.
517234353Sdim  if (Asm->isThumbFunc(&SA))
518234353Sdim    Addend |= 1;
519234353Sdim
520218893Sdim  // Clear the symbol expr pointers to indicate we have folded these
521218893Sdim  // operands.
522218893Sdim  A = B = 0;
523218893Sdim}
524218893Sdim
525218893Sdim/// \brief Evaluate the result of an add between (conceptually) two MCValues.
526218893Sdim///
527218893Sdim/// This routine conceptually attempts to construct an MCValue:
528218893Sdim///   Result = (Result_A - Result_B + Result_Cst)
529218893Sdim/// from two MCValue's LHS and RHS where
530218893Sdim///   Result = LHS + RHS
531218893Sdim/// and
532218893Sdim///   Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
533218893Sdim///
534218893Sdim/// This routine attempts to aggresively fold the operands such that the result
535218893Sdim/// is representable in an MCValue, but may not always succeed.
536218893Sdim///
537218893Sdim/// \returns True on success, false if the result is not representable in an
538218893Sdim/// MCValue.
539218893Sdim
540218893Sdim/// NOTE: It is really important to have both the Asm and Layout arguments.
541218893Sdim/// They might look redundant, but this function can be used before layout
542218893Sdim/// is done (see the object streamer for example) and having the Asm argument
543218893Sdim/// lets us avoid relaxations early.
544218893Sdimstatic bool EvaluateSymbolicAdd(const MCAssembler *Asm,
545218893Sdim                                const MCAsmLayout *Layout,
546218893Sdim                                const SectionAddrMap *Addrs,
547218893Sdim                                bool InSet,
548218893Sdim                                const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
549205407Srdivacky                                const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
550198090Srdivacky                                MCValue &Res) {
551218893Sdim  // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy
552218893Sdim  // about dealing with modifiers. This will ultimately bite us, one day.
553218893Sdim  const MCSymbolRefExpr *LHS_A = LHS.getSymA();
554218893Sdim  const MCSymbolRefExpr *LHS_B = LHS.getSymB();
555218893Sdim  int64_t LHS_Cst = LHS.getConstant();
556218893Sdim
557218893Sdim  // Fold the result constant immediately.
558218893Sdim  int64_t Result_Cst = LHS_Cst + RHS_Cst;
559218893Sdim
560218893Sdim  assert((!Layout || Asm) &&
561218893Sdim         "Must have an assembler object if layout is given!");
562218893Sdim
563218893Sdim  // If we have a layout, we can fold resolved differences.
564218893Sdim  if (Asm) {
565218893Sdim    // First, fold out any differences which are fully resolved. By
566218893Sdim    // reassociating terms in
567218893Sdim    //   Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
568218893Sdim    // we have the four possible differences:
569218893Sdim    //   (LHS_A - LHS_B),
570218893Sdim    //   (LHS_A - RHS_B),
571218893Sdim    //   (RHS_A - LHS_B),
572218893Sdim    //   (RHS_A - RHS_B).
573221345Sdim    // Since we are attempting to be as aggressive as possible about folding, we
574218893Sdim    // attempt to evaluate each possible alternative.
575218893Sdim    AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B,
576218893Sdim                                        Result_Cst);
577218893Sdim    AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B,
578218893Sdim                                        Result_Cst);
579218893Sdim    AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B,
580218893Sdim                                        Result_Cst);
581218893Sdim    AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B,
582218893Sdim                                        Result_Cst);
583218893Sdim  }
584218893Sdim
585218893Sdim  // We can't represent the addition or subtraction of two symbols.
586218893Sdim  if ((LHS_A && RHS_A) || (LHS_B && RHS_B))
587198090Srdivacky    return false;
588198090Srdivacky
589218893Sdim  // At this point, we have at most one additive symbol and one subtractive
590218893Sdim  // symbol -- find them.
591218893Sdim  const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A;
592218893Sdim  const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B;
593218893Sdim
594218893Sdim  // If we have a negated symbol, then we must have also have a non-negated
595218893Sdim  // symbol in order to encode the expression.
596218893Sdim  if (B && !A)
597218893Sdim    return false;
598218893Sdim
599218893Sdim  Res = MCValue::get(A, B, Result_Cst);
600198090Srdivacky  return true;
601198090Srdivacky}
602198090Srdivacky
603205218Srdivackybool MCExpr::EvaluateAsRelocatable(MCValue &Res,
604218893Sdim                                   const MCAsmLayout &Layout) const {
605218893Sdim  return EvaluateAsRelocatableImpl(Res, &Layout.getAssembler(), &Layout,
606218893Sdim                                   0, false);
607218893Sdim}
608218893Sdim
609218893Sdimbool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
610218893Sdim                                       const MCAssembler *Asm,
611218893Sdim                                       const MCAsmLayout *Layout,
612218893Sdim                                       const SectionAddrMap *Addrs,
613218893Sdim                                       bool InSet) const {
614206083Srdivacky  ++stats::MCExprEvaluate;
615206083Srdivacky
616198090Srdivacky  switch (getKind()) {
617203954Srdivacky  case Target:
618205218Srdivacky    return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout);
619205407Srdivacky
620198090Srdivacky  case Constant:
621198090Srdivacky    Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
622198090Srdivacky    return true;
623198090Srdivacky
624198090Srdivacky  case SymbolRef: {
625205407Srdivacky    const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
626205407Srdivacky    const MCSymbol &Sym = SRE->getSymbol();
627198396Srdivacky
628198396Srdivacky    // Evaluate recursively if this is a variable.
629218893Sdim    if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
630218893Sdim      bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm,
631218893Sdim                                                                   Layout,
632218893Sdim                                                                   Addrs,
633218893Sdim                                                                   true);
634218893Sdim      // If we failed to simplify this to a constant, let the target
635218893Sdim      // handle it.
636218893Sdim      if (Ret && !Res.getSymA() && !Res.getSymB())
637218893Sdim        return true;
638205218Srdivacky    }
639205218Srdivacky
640205407Srdivacky    Res = MCValue::get(SRE, 0, 0);
641198090Srdivacky    return true;
642198090Srdivacky  }
643198090Srdivacky
644198090Srdivacky  case Unary: {
645198090Srdivacky    const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
646198090Srdivacky    MCValue Value;
647198090Srdivacky
648218893Sdim    if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
649218893Sdim                                                      Addrs, InSet))
650198090Srdivacky      return false;
651198090Srdivacky
652198090Srdivacky    switch (AUE->getOpcode()) {
653198090Srdivacky    case MCUnaryExpr::LNot:
654198090Srdivacky      if (!Value.isAbsolute())
655198090Srdivacky        return false;
656198090Srdivacky      Res = MCValue::get(!Value.getConstant());
657198090Srdivacky      break;
658198090Srdivacky    case MCUnaryExpr::Minus:
659198090Srdivacky      /// -(a - b + const) ==> (b - a - const)
660198090Srdivacky      if (Value.getSymA() && !Value.getSymB())
661198090Srdivacky        return false;
662205407Srdivacky      Res = MCValue::get(Value.getSymB(), Value.getSymA(),
663205407Srdivacky                         -Value.getConstant());
664198090Srdivacky      break;
665198090Srdivacky    case MCUnaryExpr::Not:
666198090Srdivacky      if (!Value.isAbsolute())
667198090Srdivacky        return false;
668205407Srdivacky      Res = MCValue::get(~Value.getConstant());
669198090Srdivacky      break;
670198090Srdivacky    case MCUnaryExpr::Plus:
671198090Srdivacky      Res = Value;
672198090Srdivacky      break;
673198090Srdivacky    }
674198090Srdivacky
675198090Srdivacky    return true;
676198090Srdivacky  }
677198090Srdivacky
678198090Srdivacky  case Binary: {
679198090Srdivacky    const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
680198090Srdivacky    MCValue LHSValue, RHSValue;
681205407Srdivacky
682218893Sdim    if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
683218893Sdim                                                  Addrs, InSet) ||
684218893Sdim        !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
685218893Sdim                                                  Addrs, InSet))
686198090Srdivacky      return false;
687198090Srdivacky
688198090Srdivacky    // We only support a few operations on non-constant expressions, handle
689198090Srdivacky    // those first.
690198090Srdivacky    if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
691198090Srdivacky      switch (ABE->getOpcode()) {
692198090Srdivacky      default:
693198090Srdivacky        return false;
694198090Srdivacky      case MCBinaryExpr::Sub:
695198090Srdivacky        // Negate RHS and add.
696218893Sdim        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
697198090Srdivacky                                   RHSValue.getSymB(), RHSValue.getSymA(),
698198090Srdivacky                                   -RHSValue.getConstant(),
699198090Srdivacky                                   Res);
700198090Srdivacky
701198090Srdivacky      case MCBinaryExpr::Add:
702218893Sdim        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
703198090Srdivacky                                   RHSValue.getSymA(), RHSValue.getSymB(),
704198090Srdivacky                                   RHSValue.getConstant(),
705198090Srdivacky                                   Res);
706198090Srdivacky      }
707198090Srdivacky    }
708198090Srdivacky
709198090Srdivacky    // FIXME: We need target hooks for the evaluation. It may be limited in
710203954Srdivacky    // width, and gas defines the result of comparisons and right shifts
711203954Srdivacky    // differently from Apple as.
712198090Srdivacky    int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
713198090Srdivacky    int64_t Result = 0;
714198090Srdivacky    switch (ABE->getOpcode()) {
715198090Srdivacky    case MCBinaryExpr::Add:  Result = LHS + RHS; break;
716198090Srdivacky    case MCBinaryExpr::And:  Result = LHS & RHS; break;
717198090Srdivacky    case MCBinaryExpr::Div:  Result = LHS / RHS; break;
718198090Srdivacky    case MCBinaryExpr::EQ:   Result = LHS == RHS; break;
719198090Srdivacky    case MCBinaryExpr::GT:   Result = LHS > RHS; break;
720198090Srdivacky    case MCBinaryExpr::GTE:  Result = LHS >= RHS; break;
721198090Srdivacky    case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
722198090Srdivacky    case MCBinaryExpr::LOr:  Result = LHS || RHS; break;
723198090Srdivacky    case MCBinaryExpr::LT:   Result = LHS < RHS; break;
724198090Srdivacky    case MCBinaryExpr::LTE:  Result = LHS <= RHS; break;
725198090Srdivacky    case MCBinaryExpr::Mod:  Result = LHS % RHS; break;
726198090Srdivacky    case MCBinaryExpr::Mul:  Result = LHS * RHS; break;
727198090Srdivacky    case MCBinaryExpr::NE:   Result = LHS != RHS; break;
728198090Srdivacky    case MCBinaryExpr::Or:   Result = LHS | RHS; break;
729198090Srdivacky    case MCBinaryExpr::Shl:  Result = LHS << RHS; break;
730198090Srdivacky    case MCBinaryExpr::Shr:  Result = LHS >> RHS; break;
731198090Srdivacky    case MCBinaryExpr::Sub:  Result = LHS - RHS; break;
732198090Srdivacky    case MCBinaryExpr::Xor:  Result = LHS ^ RHS; break;
733198090Srdivacky    }
734198090Srdivacky
735198090Srdivacky    Res = MCValue::get(Result);
736198090Srdivacky    return true;
737198090Srdivacky  }
738198090Srdivacky  }
739198090Srdivacky
740234353Sdim  llvm_unreachable("Invalid assembly expression kind!");
741198090Srdivacky}
742221345Sdim
743221345Sdimconst MCSection *MCExpr::FindAssociatedSection() const {
744221345Sdim  switch (getKind()) {
745221345Sdim  case Target:
746221345Sdim    // We never look through target specific expressions.
747221345Sdim    return cast<MCTargetExpr>(this)->FindAssociatedSection();
748221345Sdim
749221345Sdim  case Constant:
750221345Sdim    return MCSymbol::AbsolutePseudoSection;
751221345Sdim
752221345Sdim  case SymbolRef: {
753221345Sdim    const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
754221345Sdim    const MCSymbol &Sym = SRE->getSymbol();
755221345Sdim
756221345Sdim    if (Sym.isDefined())
757221345Sdim      return &Sym.getSection();
758221345Sdim
759221345Sdim    return 0;
760221345Sdim  }
761221345Sdim
762221345Sdim  case Unary:
763221345Sdim    return cast<MCUnaryExpr>(this)->getSubExpr()->FindAssociatedSection();
764221345Sdim
765221345Sdim  case Binary: {
766221345Sdim    const MCBinaryExpr *BE = cast<MCBinaryExpr>(this);
767221345Sdim    const MCSection *LHS_S = BE->getLHS()->FindAssociatedSection();
768221345Sdim    const MCSection *RHS_S = BE->getRHS()->FindAssociatedSection();
769221345Sdim
770221345Sdim    // If either section is absolute, return the other.
771221345Sdim    if (LHS_S == MCSymbol::AbsolutePseudoSection)
772221345Sdim      return RHS_S;
773221345Sdim    if (RHS_S == MCSymbol::AbsolutePseudoSection)
774221345Sdim      return LHS_S;
775221345Sdim
776221345Sdim    // Otherwise, return the first non-null section.
777221345Sdim    return LHS_S ? LHS_S : RHS_S;
778221345Sdim  }
779221345Sdim  }
780221345Sdim
781234353Sdim  llvm_unreachable("Invalid assembly expression kind!");
782221345Sdim}
783