~ubuntu-branches/ubuntu/quantal/llvm-3.1/quantal

« back to all changes in this revision

Viewing changes to lib/MC/MCExpr.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2012-03-29 19:09:51 UTC
  • Revision ID: package-import@ubuntu.com-20120329190951-aq83ivog4cg8bxun
Tags: upstream-3.1~svn153643
ImportĀ upstreamĀ versionĀ 3.1~svn153643

Show diffs side-by-side

added added

removed removed

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