Bug Summary

File:lib/MC/MCExpr.cpp
Warning:line 765, column 43
Division by zero

Annotated Source Code

/build/llvm-toolchain-snapshot-6.0~svn318693/lib/MC/MCExpr.cpp

1//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/MC/MCExpr.h"
11#include "llvm/ADT/Statistic.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCAsmInfo.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/Casting.h"
21#include "llvm/Support/Compiler.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/raw_ostream.h"
25#include <cassert>
26#include <cstdint>
27
28using namespace llvm;
29
30#define DEBUG_TYPE"mcexpr" "mcexpr"
31
32namespace {
33namespace stats {
34
35STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations")static llvm::Statistic MCExprEvaluate = {"mcexpr", "MCExprEvaluate"
, "Number of MCExpr evaluations", {0}, false}
;
36
37} // end namespace stats
38} // end anonymous namespace
39
40void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const {
41 switch (getKind()) {
42 case MCExpr::Target:
43 return cast<MCTargetExpr>(this)->printImpl(OS, MAI);
44 case MCExpr::Constant:
45 OS << cast<MCConstantExpr>(*this).getValue();
46 return;
47
48 case MCExpr::SymbolRef: {
49 const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this);
50 const MCSymbol &Sym = SRE.getSymbol();
51 // Parenthesize names that start with $ so that they don't look like
52 // absolute names.
53 bool UseParens =
54 !InParens && !Sym.getName().empty() && Sym.getName()[0] == '$';
55 if (UseParens) {
56 OS << '(';
57 Sym.print(OS, MAI);
58 OS << ')';
59 } else
60 Sym.print(OS, MAI);
61
62 if (SRE.getKind() != MCSymbolRefExpr::VK_None)
63 SRE.printVariantKind(OS);
64
65 return;
66 }
67
68 case MCExpr::Unary: {
69 const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this);
70 switch (UE.getOpcode()) {
71 case MCUnaryExpr::LNot: OS << '!'; break;
72 case MCUnaryExpr::Minus: OS << '-'; break;
73 case MCUnaryExpr::Not: OS << '~'; break;
74 case MCUnaryExpr::Plus: OS << '+'; break;
75 }
76 UE.getSubExpr()->print(OS, MAI);
77 return;
78 }
79
80 case MCExpr::Binary: {
81 const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);
82
83 // Only print parens around the LHS if it is non-trivial.
84 if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
85 BE.getLHS()->print(OS, MAI);
86 } else {
87 OS << '(';
88 BE.getLHS()->print(OS, MAI);
89 OS << ')';
90 }
91
92 switch (BE.getOpcode()) {
93 case MCBinaryExpr::Add:
94 // Print "X-42" instead of "X+-42".
95 if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {
96 if (RHSC->getValue() < 0) {
97 OS << RHSC->getValue();
98 return;
99 }
100 }
101
102 OS << '+';
103 break;
104 case MCBinaryExpr::AShr: OS << ">>"; break;
105 case MCBinaryExpr::And: OS << '&'; break;
106 case MCBinaryExpr::Div: OS << '/'; break;
107 case MCBinaryExpr::EQ: OS << "=="; break;
108 case MCBinaryExpr::GT: OS << '>'; break;
109 case MCBinaryExpr::GTE: OS << ">="; break;
110 case MCBinaryExpr::LAnd: OS << "&&"; break;
111 case MCBinaryExpr::LOr: OS << "||"; break;
112 case MCBinaryExpr::LShr: 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::Sub: OS << '-'; break;
121 case MCBinaryExpr::Xor: OS << '^'; break;
122 }
123
124 // Only print parens around the LHS if it is non-trivial.
125 if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
126 BE.getRHS()->print(OS, MAI);
127 } else {
128 OS << '(';
129 BE.getRHS()->print(OS, MAI);
130 OS << ')';
131 }
132 return;
133 }
134 }
135
136 llvm_unreachable("Invalid expression kind!")::llvm::llvm_unreachable_internal("Invalid expression kind!",
"/build/llvm-toolchain-snapshot-6.0~svn318693/lib/MC/MCExpr.cpp"
, 136)
;
137}
138
139#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
140LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void MCExpr::dump() const {
141 dbgs() << *this;
142 dbgs() << '\n';
143}
144#endif
145
146/* *** */
147
148const MCBinaryExpr *MCBinaryExpr::create(Opcode Opc, const MCExpr *LHS,
149 const MCExpr *RHS, MCContext &Ctx,
150 SMLoc Loc) {
151 return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc);
152}
153
154const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr,
155 MCContext &Ctx, SMLoc Loc) {
156 return new (Ctx) MCUnaryExpr(Opc, Expr, Loc);
157}
158
159const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx) {
160 return new (Ctx) MCConstantExpr(Value);
161}
162
163/* *** */
164
165MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,
166 const MCAsmInfo *MAI, SMLoc Loc)
167 : MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind),
168 UseParensForSymbolVariant(MAI->useParensForSymbolVariant()),
169 HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()),
170 Symbol(Symbol) {
171 assert(Symbol)(static_cast <bool> (Symbol) ? void (0) : __assert_fail
("Symbol", "/build/llvm-toolchain-snapshot-6.0~svn318693/lib/MC/MCExpr.cpp"
, 171, __extension__ __PRETTY_FUNCTION__))
;
172}
173
174const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym,
175 VariantKind Kind,
176 MCContext &Ctx, SMLoc Loc) {
177 return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo(), Loc);
178}
179
180const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind,
181 MCContext &Ctx) {
182 return create(Ctx.getOrCreateSymbol(Name), Kind, Ctx);
183}
184
185StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
186 switch (Kind) {
187 case VK_Invalid: return "<<invalid>>";
188 case VK_None: return "<<none>>";
189
190 case VK_DTPOFF: return "DTPOFF";
191 case VK_DTPREL: return "DTPREL";
192 case VK_GOT: return "GOT";
193 case VK_GOTOFF: return "GOTOFF";
194 case VK_GOTREL: return "GOTREL";
195 case VK_GOTPCREL: return "GOTPCREL";
196 case VK_GOTTPOFF: return "GOTTPOFF";
197 case VK_INDNTPOFF: return "INDNTPOFF";
198 case VK_NTPOFF: return "NTPOFF";
199 case VK_GOTNTPOFF: return "GOTNTPOFF";
200 case VK_PLT: return "PLT";
201 case VK_TLSGD: return "TLSGD";
202 case VK_TLSLD: return "TLSLD";
203 case VK_TLSLDM: return "TLSLDM";
204 case VK_TPOFF: return "TPOFF";
205 case VK_TPREL: return "TPREL";
206 case VK_TLSCALL: return "tlscall";
207 case VK_TLSDESC: return "tlsdesc";
208 case VK_TLVP: return "TLVP";
209 case VK_TLVPPAGE: return "TLVPPAGE";
210 case VK_TLVPPAGEOFF: return "TLVPPAGEOFF";
211 case VK_PAGE: return "PAGE";
212 case VK_PAGEOFF: return "PAGEOFF";
213 case VK_GOTPAGE: return "GOTPAGE";
214 case VK_GOTPAGEOFF: return "GOTPAGEOFF";
215 case VK_SECREL: return "SECREL32";
216 case VK_SIZE: return "SIZE";
217 case VK_WEAKREF: return "WEAKREF";
218 case VK_X86_ABS8: return "ABS8";
219 case VK_ARM_NONE: return "none";
220 case VK_ARM_GOT_PREL: return "GOT_PREL";
221 case VK_ARM_TARGET1: return "target1";
222 case VK_ARM_TARGET2: return "target2";
223 case VK_ARM_PREL31: return "prel31";
224 case VK_ARM_SBREL: return "sbrel";
225 case VK_ARM_TLSLDO: return "tlsldo";
226 case VK_ARM_TLSDESCSEQ: return "tlsdescseq";
227 case VK_PPC_LO: return "l";
228 case VK_PPC_HI: return "h";
229 case VK_PPC_HA: return "ha";
230 case VK_PPC_HIGHER: return "higher";
231 case VK_PPC_HIGHERA: return "highera";
232 case VK_PPC_HIGHEST: return "highest";
233 case VK_PPC_HIGHESTA: return "highesta";
234 case VK_PPC_GOT_LO: return "got@l";
235 case VK_PPC_GOT_HI: return "got@h";
236 case VK_PPC_GOT_HA: return "got@ha";
237 case VK_PPC_TOCBASE: return "tocbase";
238 case VK_PPC_TOC: return "toc";
239 case VK_PPC_TOC_LO: return "toc@l";
240 case VK_PPC_TOC_HI: return "toc@h";
241 case VK_PPC_TOC_HA: return "toc@ha";
242 case VK_PPC_DTPMOD: return "dtpmod";
243 case VK_PPC_TPREL_LO: return "tprel@l";
244 case VK_PPC_TPREL_HI: return "tprel@h";
245 case VK_PPC_TPREL_HA: return "tprel@ha";
246 case VK_PPC_TPREL_HIGHER: return "tprel@higher";
247 case VK_PPC_TPREL_HIGHERA: return "tprel@highera";
248 case VK_PPC_TPREL_HIGHEST: return "tprel@highest";
249 case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta";
250 case VK_PPC_DTPREL_LO: return "dtprel@l";
251 case VK_PPC_DTPREL_HI: return "dtprel@h";
252 case VK_PPC_DTPREL_HA: return "dtprel@ha";
253 case VK_PPC_DTPREL_HIGHER: return "dtprel@higher";
254 case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera";
255 case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest";
256 case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta";
257 case VK_PPC_GOT_TPREL: return "got@tprel";
258 case VK_PPC_GOT_TPREL_LO: return "got@tprel@l";
259 case VK_PPC_GOT_TPREL_HI: return "got@tprel@h";
260 case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha";
261 case VK_PPC_GOT_DTPREL: return "got@dtprel";
262 case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l";
263 case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h";
264 case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha";
265 case VK_PPC_TLS: return "tls";
266 case VK_PPC_GOT_TLSGD: return "got@tlsgd";
267 case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l";
268 case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h";
269 case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha";
270 case VK_PPC_TLSGD: return "tlsgd";
271 case VK_PPC_GOT_TLSLD: return "got@tlsld";
272 case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";
273 case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";
274 case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";
275 case VK_PPC_TLSLD: return "tlsld";
276 case VK_PPC_LOCAL: return "local";
277 case VK_COFF_IMGREL32: return "IMGREL";
278 case VK_Hexagon_PCREL: return "PCREL";
279 case VK_Hexagon_LO16: return "LO16";
280 case VK_Hexagon_HI16: return "HI16";
281 case VK_Hexagon_GPREL: return "GPREL";
282 case VK_Hexagon_GD_GOT: return "GDGOT";
283 case VK_Hexagon_LD_GOT: return "LDGOT";
284 case VK_Hexagon_GD_PLT: return "GDPLT";
285 case VK_Hexagon_LD_PLT: return "LDPLT";
286 case VK_Hexagon_IE: return "IE";
287 case VK_Hexagon_IE_GOT: return "IEGOT";
288 case VK_WebAssembly_FUNCTION: return "FUNCTION";
289 case VK_WebAssembly_TYPEINDEX: return "TYPEINDEX";
290 case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";
291 case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";
292 case VK_AMDGPU_REL32_LO: return "rel32@lo";
293 case VK_AMDGPU_REL32_HI: return "rel32@hi";
294 }
295 llvm_unreachable("Invalid variant kind")::llvm::llvm_unreachable_internal("Invalid variant kind", "/build/llvm-toolchain-snapshot-6.0~svn318693/lib/MC/MCExpr.cpp"
, 295)
;
296}
297
298MCSymbolRefExpr::VariantKind
299MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
300 return StringSwitch<VariantKind>(Name.lower())
301 .Case("dtprel", VK_DTPREL)
302 .Case("dtpoff", VK_DTPOFF)
303 .Case("got", VK_GOT)
304 .Case("gotoff", VK_GOTOFF)
305 .Case("gotrel", VK_GOTREL)
306 .Case("gotpcrel", VK_GOTPCREL)
307 .Case("gottpoff", VK_GOTTPOFF)
308 .Case("indntpoff", VK_INDNTPOFF)
309 .Case("ntpoff", VK_NTPOFF)
310 .Case("gotntpoff", VK_GOTNTPOFF)
311 .Case("plt", VK_PLT)
312 .Case("tlscall", VK_TLSCALL)
313 .Case("tlsdesc", VK_TLSDESC)
314 .Case("tlsgd", VK_TLSGD)
315 .Case("tlsld", VK_TLSLD)
316 .Case("tlsldm", VK_TLSLDM)
317 .Case("tpoff", VK_TPOFF)
318 .Case("tprel", VK_TPREL)
319 .Case("tlvp", VK_TLVP)
320 .Case("tlvppage", VK_TLVPPAGE)
321 .Case("tlvppageoff", VK_TLVPPAGEOFF)
322 .Case("page", VK_PAGE)
323 .Case("pageoff", VK_PAGEOFF)
324 .Case("gotpage", VK_GOTPAGE)
325 .Case("gotpageoff", VK_GOTPAGEOFF)
326 .Case("imgrel", VK_COFF_IMGREL32)
327 .Case("secrel32", VK_SECREL)
328 .Case("size", VK_SIZE)
329 .Case("abs8", VK_X86_ABS8)
330 .Case("l", VK_PPC_LO)
331 .Case("h", VK_PPC_HI)
332 .Case("ha", VK_PPC_HA)
333 .Case("higher", VK_PPC_HIGHER)
334 .Case("highera", VK_PPC_HIGHERA)
335 .Case("highest", VK_PPC_HIGHEST)
336 .Case("highesta", VK_PPC_HIGHESTA)
337 .Case("got@l", VK_PPC_GOT_LO)
338 .Case("got@h", VK_PPC_GOT_HI)
339 .Case("got@ha", VK_PPC_GOT_HA)
340 .Case("local", VK_PPC_LOCAL)
341 .Case("tocbase", VK_PPC_TOCBASE)
342 .Case("toc", VK_PPC_TOC)
343 .Case("toc@l", VK_PPC_TOC_LO)
344 .Case("toc@h", VK_PPC_TOC_HI)
345 .Case("toc@ha", VK_PPC_TOC_HA)
346 .Case("tls", VK_PPC_TLS)
347 .Case("dtpmod", VK_PPC_DTPMOD)
348 .Case("tprel@l", VK_PPC_TPREL_LO)
349 .Case("tprel@h", VK_PPC_TPREL_HI)
350 .Case("tprel@ha", VK_PPC_TPREL_HA)
351 .Case("tprel@higher", VK_PPC_TPREL_HIGHER)
352 .Case("tprel@highera", VK_PPC_TPREL_HIGHERA)
353 .Case("tprel@highest", VK_PPC_TPREL_HIGHEST)
354 .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA)
355 .Case("dtprel@l", VK_PPC_DTPREL_LO)
356 .Case("dtprel@h", VK_PPC_DTPREL_HI)
357 .Case("dtprel@ha", VK_PPC_DTPREL_HA)
358 .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER)
359 .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA)
360 .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST)
361 .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA)
362 .Case("got@tprel", VK_PPC_GOT_TPREL)
363 .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO)
364 .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI)
365 .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA)
366 .Case("got@dtprel", VK_PPC_GOT_DTPREL)
367 .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO)
368 .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI)
369 .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA)
370 .Case("got@tlsgd", VK_PPC_GOT_TLSGD)
371 .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO)
372 .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI)
373 .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA)
374 .Case("got@tlsld", VK_PPC_GOT_TLSLD)
375 .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO)
376 .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI)
377 .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA)
378 .Case("gdgot", VK_Hexagon_GD_GOT)
379 .Case("gdplt", VK_Hexagon_GD_PLT)
380 .Case("iegot", VK_Hexagon_IE_GOT)
381 .Case("ie", VK_Hexagon_IE)
382 .Case("ldgot", VK_Hexagon_LD_GOT)
383 .Case("ldplt", VK_Hexagon_LD_PLT)
384 .Case("pcrel", VK_Hexagon_PCREL)
385 .Case("none", VK_ARM_NONE)
386 .Case("got_prel", VK_ARM_GOT_PREL)
387 .Case("target1", VK_ARM_TARGET1)
388 .Case("target2", VK_ARM_TARGET2)
389 .Case("prel31", VK_ARM_PREL31)
390 .Case("sbrel", VK_ARM_SBREL)
391 .Case("tlsldo", VK_ARM_TLSLDO)
392 .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
393 .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
394 .Case("rel32@lo", VK_AMDGPU_REL32_LO)
395 .Case("rel32@hi", VK_AMDGPU_REL32_HI)
396 .Default(VK_Invalid);
397}
398
399void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const {
400 if (UseParensForSymbolVariant)
401 OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')';
402 else
403 OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind());
404}
405
406/* *** */
407
408void MCTargetExpr::anchor() {}
409
410/* *** */
411
412bool MCExpr::evaluateAsAbsolute(int64_t &Res) const {
413 return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr);
414}
415
416bool MCExpr::evaluateAsAbsolute(int64_t &Res,
417 const MCAsmLayout &Layout) const {
418 return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr);
419}
420
421bool MCExpr::evaluateAsAbsolute(int64_t &Res,
422 const MCAsmLayout &Layout,
423 const SectionAddrMap &Addrs) const {
424 return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs);
425}
426
427bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
428 return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr);
429}
430
431bool MCExpr::evaluateKnownAbsolute(int64_t &Res,
432 const MCAsmLayout &Layout) const {
433 return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr,
434 true);
435}
436
437bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
438 const MCAsmLayout *Layout,
439 const SectionAddrMap *Addrs) const {
440 // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us
441 // absolutize differences across sections and that is what the MachO writer
442 // uses Addrs for.
443 return evaluateAsAbsolute(Res, Asm, Layout, Addrs, Addrs);
444}
445
446bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
447 const MCAsmLayout *Layout,
448 const SectionAddrMap *Addrs, bool InSet) const {
449 MCValue Value;
450
451 // Fast path constants.
452 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) {
453 Res = CE->getValue();
454 return true;
455 }
456
457 bool IsRelocatable =
458 evaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet);
459
460 // Record the current value.
461 Res = Value.getConstant();
462
463 return IsRelocatable && Value.isAbsolute();
464}
465
466/// \brief Helper method for \see EvaluateSymbolAdd().
467static void AttemptToFoldSymbolOffsetDifference(
468 const MCAssembler *Asm, const MCAsmLayout *Layout,
469 const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A,
470 const MCSymbolRefExpr *&B, int64_t &Addend) {
471 if (!A || !B)
472 return;
473
474 const MCSymbol &SA = A->getSymbol();
475 const MCSymbol &SB = B->getSymbol();
476
477 if (SA.isUndefined() || SB.isUndefined())
478 return;
479
480 if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))
481 return;
482
483 if (SA.getFragment() == SB.getFragment() && !SA.isVariable() &&
484 !SB.isVariable()) {
485 Addend += (SA.getOffset() - SB.getOffset());
486
487 // Pointers to Thumb symbols need to have their low-bit set to allow
488 // for interworking.
489 if (Asm->isThumbFunc(&SA))
490 Addend |= 1;
491
492 // Clear the symbol expr pointers to indicate we have folded these
493 // operands.
494 A = B = nullptr;
495 return;
496 }
497
498 if (!Layout)
499 return;
500
501 const MCSection &SecA = *SA.getFragment()->getParent();
502 const MCSection &SecB = *SB.getFragment()->getParent();
503
504 if ((&SecA != &SecB) && !Addrs)
505 return;
506
507 // Eagerly evaluate.
508 Addend += Layout->getSymbolOffset(A->getSymbol()) -
509 Layout->getSymbolOffset(B->getSymbol());
510 if (Addrs && (&SecA != &SecB))
511 Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB));
512
513 // Pointers to Thumb symbols need to have their low-bit set to allow
514 // for interworking.
515 if (Asm->isThumbFunc(&SA))
516 Addend |= 1;
517
518 // Clear the symbol expr pointers to indicate we have folded these
519 // operands.
520 A = B = nullptr;
521}
522
523/// \brief Evaluate the result of an add between (conceptually) two MCValues.
524///
525/// This routine conceptually attempts to construct an MCValue:
526/// Result = (Result_A - Result_B + Result_Cst)
527/// from two MCValue's LHS and RHS where
528/// Result = LHS + RHS
529/// and
530/// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
531///
532/// This routine attempts to aggresively fold the operands such that the result
533/// is representable in an MCValue, but may not always succeed.
534///
535/// \returns True on success, false if the result is not representable in an
536/// MCValue.
537
538/// NOTE: It is really important to have both the Asm and Layout arguments.
539/// They might look redundant, but this function can be used before layout
540/// is done (see the object streamer for example) and having the Asm argument
541/// lets us avoid relaxations early.
542static bool
543EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout,
544 const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS,
545 const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B,
546 int64_t RHS_Cst, MCValue &Res) {
547 // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy
548 // about dealing with modifiers. This will ultimately bite us, one day.
549 const MCSymbolRefExpr *LHS_A = LHS.getSymA();
550 const MCSymbolRefExpr *LHS_B = LHS.getSymB();
551 int64_t LHS_Cst = LHS.getConstant();
552
553 // Fold the result constant immediately.
554 int64_t Result_Cst = LHS_Cst + RHS_Cst;
555
556 assert((!Layout || Asm) &&(static_cast <bool> ((!Layout || Asm) && "Must have an assembler object if layout is given!"
) ? void (0) : __assert_fail ("(!Layout || Asm) && \"Must have an assembler object if layout is given!\""
, "/build/llvm-toolchain-snapshot-6.0~svn318693/lib/MC/MCExpr.cpp"
, 557, __extension__ __PRETTY_FUNCTION__))
557 "Must have an assembler object if layout is given!")(static_cast <bool> ((!Layout || Asm) && "Must have an assembler object if layout is given!"
) ? void (0) : __assert_fail ("(!Layout || Asm) && \"Must have an assembler object if layout is given!\""
, "/build/llvm-toolchain-snapshot-6.0~svn318693/lib/MC/MCExpr.cpp"
, 557, __extension__ __PRETTY_FUNCTION__))
;
558
559 // If we have a layout, we can fold resolved differences.
560 if (Asm) {
561 // First, fold out any differences which are fully resolved. By
562 // reassociating terms in
563 // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
564 // we have the four possible differences:
565 // (LHS_A - LHS_B),
566 // (LHS_A - RHS_B),
567 // (RHS_A - LHS_B),
568 // (RHS_A - RHS_B).
569 // Since we are attempting to be as aggressive as possible about folding, we
570 // attempt to evaluate each possible alternative.
571 AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B,
572 Result_Cst);
573 AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B,
574 Result_Cst);
575 AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B,
576 Result_Cst);
577 AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B,
578 Result_Cst);
579 }
580
581 // We can't represent the addition or subtraction of two symbols.
582 if ((LHS_A && RHS_A) || (LHS_B && RHS_B))
583 return false;
584
585 // At this point, we have at most one additive symbol and one subtractive
586 // symbol -- find them.
587 const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A;
588 const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B;
589
590 Res = MCValue::get(A, B, Result_Cst);
591 return true;
592}
593
594bool MCExpr::evaluateAsRelocatable(MCValue &Res,
595 const MCAsmLayout *Layout,
596 const MCFixup *Fixup) const {
597 MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr;
598 return evaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr,
599 false);
600}
601
602bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const {
603 MCAssembler *Assembler = &Layout.getAssembler();
604 return evaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr,
1
Calling 'MCExpr::evaluateAsRelocatableImpl'
605 true);
606}
607
608static bool canExpand(const MCSymbol &Sym, bool InSet) {
609 const MCExpr *Expr = Sym.getVariableValue();
610 const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
611 if (Inner) {
612 if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
613 return false;
614 }
615
616 if (InSet)
617 return true;
618 return !Sym.isInSection();
619}
620
621bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
622 const MCAsmLayout *Layout,
623 const MCFixup *Fixup,
624 const SectionAddrMap *Addrs,
625 bool InSet) const {
626 ++stats::MCExprEvaluate;
13
Calling 'Statistic::operator++'
16
Returning from 'Statistic::operator++'
627
628 switch (getKind()) {
2
Control jumps to 'case Binary:' at line 707
4
Control jumps to 'case Binary:' at line 707
6
Control jumps to 'case Binary:' at line 707
8
Control jumps to 'case Binary:' at line 707
17
Calling 'MCExpr::getKind'
18
Returning from 'MCExpr::getKind'
19
Control jumps to 'case Binary:' at line 707
629 case Target:
630 return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Layout,
631 Fixup);
632
633 case Constant:
634 Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
635 return true;
636
637 case SymbolRef: {
638 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
639 const MCSymbol &Sym = SRE->getSymbol();
640
641 // Evaluate recursively if this is a variable.
642 if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None &&
643 canExpand(Sym, InSet)) {
644 bool IsMachO = SRE->hasSubsectionsViaSymbols();
645 if (Sym.getVariableValue()->evaluateAsRelocatableImpl(
646 Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) {
647 if (!IsMachO)
648 return true;
649
650 const MCSymbolRefExpr *A = Res.getSymA();
651 const MCSymbolRefExpr *B = Res.getSymB();
652 // FIXME: This is small hack. Given
653 // a = b + 4
654 // .long a
655 // the OS X assembler will completely drop the 4. We should probably
656 // include it in the relocation or produce an error if that is not
657 // possible.
658 // Allow constant expressions.
659 if (!A && !B)
660 return true;
661 // Allows aliases with zero offset.
662 if (Res.getConstant() == 0 && (!A || !B))
663 return true;
664 }
665 }
666
667 Res = MCValue::get(SRE, nullptr, 0);
668 return true;
669 }
670
671 case Unary: {
672 const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
673 MCValue Value;
674
675 if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Layout, Fixup,
676 Addrs, InSet))
677 return false;
678
679 switch (AUE->getOpcode()) {
680 case MCUnaryExpr::LNot:
681 if (!Value.isAbsolute())
682 return false;
683 Res = MCValue::get(!Value.getConstant());
684 break;
685 case MCUnaryExpr::Minus:
686 /// -(a - b + const) ==> (b - a - const)
687 if (Value.getSymA() && !Value.getSymB())
688 return false;
689
690 // The cast avoids undefined behavior if the constant is INT64_MIN.
691 Res = MCValue::get(Value.getSymB(), Value.getSymA(),
692 -(uint64_t)Value.getConstant());
693 break;
694 case MCUnaryExpr::Not:
695 if (!Value.isAbsolute())
696 return false;
697 Res = MCValue::get(~Value.getConstant());
698 break;
699 case MCUnaryExpr::Plus:
700 Res = Value;
701 break;
702 }
703
704 return true;
705 }
706
707 case Binary: {
708 const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
709 MCValue LHSValue, RHSValue;
9
Calling defaulted default constructor for 'MCValue'
11
Returning from default constructor for 'MCValue'
20
Calling defaulted default constructor for 'MCValue'
21
Returning from default constructor for 'MCValue'
22
Calling defaulted default constructor for 'MCValue'
23
Returning from default constructor for 'MCValue'
710
711 if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup,
24
Calling 'MCBinaryExpr::getLHS'
25
Returning from 'MCBinaryExpr::getLHS'
26
Assuming the condition is false
30
Taking false branch
48
Taking false branch
712 Addrs, InSet) ||
713 !ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup,
3
Calling 'MCExpr::evaluateAsRelocatableImpl'
5
Calling 'MCExpr::evaluateAsRelocatableImpl'
7
Calling 'MCExpr::evaluateAsRelocatableImpl'
12
Calling 'MCExpr::evaluateAsRelocatableImpl'
27
Calling 'MCBinaryExpr::getRHS'
28
Returning from 'MCBinaryExpr::getRHS'
29
Assuming the condition is false
47
Returning from 'MCExpr::evaluateAsRelocatableImpl'
714 Addrs, InSet))
715 return false;
716
717 // We only support a few operations on non-constant expressions, handle
718 // those first.
719 if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {
31
Assuming the condition is false
32
Assuming the condition is false
33
Taking false branch
49
Taking false branch
720 switch (ABE->getOpcode()) {
721 default:
722 return false;
723 case MCBinaryExpr::Sub:
724 // Negate RHS and add.
725 // The cast avoids undefined behavior if the constant is INT64_MIN.
726 return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
727 RHSValue.getSymB(), RHSValue.getSymA(),
728 -(uint64_t)RHSValue.getConstant(), Res);
729
730 case MCBinaryExpr::Add:
731 return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
732 RHSValue.getSymA(), RHSValue.getSymB(),
733 RHSValue.getConstant(), Res);
734 }
735 }
736
737 // FIXME: We need target hooks for the evaluation. It may be limited in
738 // width, and gas defines the result of comparisons differently from
739 // Apple as.
740 int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
34
Calling 'MCValue::getConstant'
35
Returning from 'MCValue::getConstant'
36
Calling 'MCValue::getConstant'
37
Returning from 'MCValue::getConstant'
50
Calling 'MCValue::getConstant'
52
Returning from 'MCValue::getConstant'
53
'RHS' initialized to 0
741 int64_t Result = 0;
742 switch (ABE->getOpcode()) {
38
Calling 'MCBinaryExpr::getOpcode'
39
Returning from 'MCBinaryExpr::getOpcode'
40
Control jumps to 'case LAnd:' at line 760
54
Control jumps to 'case Mod:' at line 765
743 case MCBinaryExpr::AShr: Result = LHS >> RHS; break;
744 case MCBinaryExpr::Add: Result = LHS + RHS; break;
745 case MCBinaryExpr::And: Result = LHS & RHS; break;
746 case MCBinaryExpr::Div:
747 // Handle division by zero. gas just emits a warning and keeps going,
748 // we try to be stricter.
749 // FIXME: Currently the caller of this function has no way to understand
750 // we're bailing out because of 'division by zero'. Therefore, it will
751 // emit a 'expected relocatable expression' error. It would be nice to
752 // change this code to emit a better diagnostic.
753 if (RHS == 0)
754 return false;
755 Result = LHS / RHS;
756 break;
757 case MCBinaryExpr::EQ: Result = LHS == RHS; break;
758 case MCBinaryExpr::GT: Result = LHS > RHS; break;
759 case MCBinaryExpr::GTE: Result = LHS >= RHS; break;
760 case MCBinaryExpr::LAnd: Result = LHS && RHS; break;
41
Assuming 'LHS' is 0
42
Execution continues on line 774
761 case MCBinaryExpr::LOr: Result = LHS || RHS; break;
762 case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break;
763 case MCBinaryExpr::LT: Result = LHS < RHS; break;
764 case MCBinaryExpr::LTE: Result = LHS <= RHS; break;
765 case MCBinaryExpr::Mod: Result = LHS % RHS; break;
55
Division by zero
766 case MCBinaryExpr::Mul: Result = LHS * RHS; break;
767 case MCBinaryExpr::NE: Result = LHS != RHS; break;
768 case MCBinaryExpr::Or: Result = LHS | RHS; break;
769 case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break;
770 case MCBinaryExpr::Sub: Result = LHS - RHS; break;
771 case MCBinaryExpr::Xor: Result = LHS ^ RHS; break;
772 }
773
774 Res = MCValue::get(Result);
43
Calling 'MCValue::get'
46
Returning from 'MCValue::get'
775 return true;
776 }
777 }
778
779 llvm_unreachable("Invalid assembly expression kind!")::llvm::llvm_unreachable_internal("Invalid assembly expression kind!"
, "/build/llvm-toolchain-snapshot-6.0~svn318693/lib/MC/MCExpr.cpp"
, 779)
;
780}
781
782MCFragment *MCExpr::findAssociatedFragment() const {
783 switch (getKind()) {
784 case Target:
785 // We never look through target specific expressions.
786 return cast<MCTargetExpr>(this)->findAssociatedFragment();
787
788 case Constant:
789 return MCSymbol::AbsolutePseudoFragment;
790
791 case SymbolRef: {
792 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
793 const MCSymbol &Sym = SRE->getSymbol();
794 return Sym.getFragment();
795 }
796
797 case Unary:
798 return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment();
799
800 case Binary: {
801 const MCBinaryExpr *BE = cast<MCBinaryExpr>(this);
802 MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment();
803 MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment();
804
805 // If either is absolute, return the other.
806 if (LHS_F == MCSymbol::AbsolutePseudoFragment)
807 return RHS_F;
808 if (RHS_F == MCSymbol::AbsolutePseudoFragment)
809 return LHS_F;
810
811 // Not always correct, but probably the best we can do without more context.
812 if (BE->getOpcode() == MCBinaryExpr::Sub)
813 return MCSymbol::AbsolutePseudoFragment;
814
815 // Otherwise, return the first non-null fragment.
816 return LHS_F ? LHS_F : RHS_F;
817 }
818 }
819
820 llvm_unreachable("Invalid assembly expression kind!")::llvm::llvm_unreachable_internal("Invalid assembly expression kind!"
, "/build/llvm-toolchain-snapshot-6.0~svn318693/lib/MC/MCExpr.cpp"
, 820)
;
821}

/build/llvm-toolchain-snapshot-6.0~svn318693/include/llvm/MC/MCValue.h

1//===-- llvm/MC/MCValue.h - MCValue class -----------------------*- C++ -*-===//
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// This file contains the declaration of the MCValue class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_MC_MCVALUE_H
15#define LLVM_MC_MCVALUE_H
16
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCSymbol.h"
19#include "llvm/Support/DataTypes.h"
20#include <cassert>
21
22namespace llvm {
23class MCAsmInfo;
24class raw_ostream;
25
26/// \brief This represents an "assembler immediate".
27///
28/// In its most general form, this can hold ":Kind:(SymbolA - SymbolB +
29/// imm64)". Not all targets supports relocations of this general form, but we
30/// need to represent this anyway.
31///
32/// In general both SymbolA and SymbolB will also have a modifier
33/// analogous to the top-level Kind. Current targets are not expected
34/// to make use of both though. The choice comes down to whether
35/// relocation modifiers apply to the closest symbol or the whole
36/// expression.
37///
38/// Note that this class must remain a simple POD value class, because we need
39/// it to live in unions etc.
40class MCValue {
41 const MCSymbolRefExpr *SymA = nullptr, *SymB = nullptr;
42 int64_t Cst = 0;
10
The value 0 is assigned to 'RHSValue.Cst'
43 uint32_t RefKind = 0;
44
45public:
46 MCValue() = default;
47 int64_t getConstant() const { return Cst; }
51
Returning zero
48 const MCSymbolRefExpr *getSymA() const { return SymA; }
49 const MCSymbolRefExpr *getSymB() const { return SymB; }
50 uint32_t getRefKind() const { return RefKind; }
51
52 /// \brief Is this an absolute (as opposed to relocatable) value.
53 bool isAbsolute() const { return !SymA && !SymB; }
54
55 /// \brief Print the value to the stream \p OS.
56 void print(raw_ostream &OS) const;
57
58 /// \brief Print the value to stderr.
59 void dump() const;
60
61 MCSymbolRefExpr::VariantKind getAccessVariant() const;
62
63 static MCValue get(const MCSymbolRefExpr *SymA,
64 const MCSymbolRefExpr *SymB = nullptr,
65 int64_t Val = 0, uint32_t RefKind = 0) {
66 MCValue R;
67 R.Cst = Val;
68 R.SymA = SymA;
69 R.SymB = SymB;
70 R.RefKind = RefKind;
71 return R;
72 }
73
74 static MCValue get(int64_t Val) {
75 MCValue R;
44
Calling defaulted default constructor for 'MCValue'
45
Returning from default constructor for 'MCValue'
76 R.Cst = Val;
77 R.SymA = nullptr;
78 R.SymB = nullptr;
79 R.RefKind = 0;
80 return R;
81 }
82
83};
84
85} // end namespace llvm
86
87#endif

/build/llvm-toolchain-snapshot-6.0~svn318693/include/llvm/ADT/Statistic.h

1//===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===//
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// This file defines the 'Statistic' class, which is designed to be an easy way
11// to expose various metrics from passes. These statistics are printed at the
12// end of a run (from llvm_shutdown), when the -stats command line option is
13// passed on the command line.
14//
15// This is useful for reporting information like the number of instructions
16// simplified, optimized or removed by various transformations, like this:
17//
18// static Statistic NumInstsKilled("gcse", "Number of instructions killed");
19//
20// Later, in the code: ++NumInstsKilled;
21//
22// NOTE: Statistics *must* be declared as global variables.
23//
24//===----------------------------------------------------------------------===//
25
26#ifndef LLVM_ADT_STATISTIC_H
27#define LLVM_ADT_STATISTIC_H
28
29#include "llvm/Support/Atomic.h"
30#include "llvm/Support/Compiler.h"
31#include <atomic>
32#include <memory>
33
34namespace llvm {
35
36class raw_ostream;
37class raw_fd_ostream;
38
39class Statistic {
40public:
41 const char *DebugType;
42 const char *Name;
43 const char *Desc;
44 std::atomic<unsigned> Value;
45 bool Initialized;
46
47 unsigned getValue() const { return Value.load(std::memory_order_relaxed); }
48 const char *getDebugType() const { return DebugType; }
49 const char *getName() const { return Name; }
50 const char *getDesc() const { return Desc; }
51
52 /// construct - This should only be called for non-global statistics.
53 void construct(const char *debugtype, const char *name, const char *desc) {
54 DebugType = debugtype;
55 Name = name;
56 Desc = desc;
57 Value = 0;
58 Initialized = false;
59 }
60
61 // Allow use of this class as the value itself.
62 operator unsigned() const { return getValue(); }
63
64#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
65 const Statistic &operator=(unsigned Val) {
66 Value.store(Val, std::memory_order_relaxed);
67 return init();
68 }
69
70 const Statistic &operator++() {
71 Value.fetch_add(1, std::memory_order_relaxed);
14
Calling '__atomic_base::fetch_add'
15
Returning from '__atomic_base::fetch_add'
72 return init();
73 }
74
75 unsigned operator++(int) {
76 init();
77 return Value.fetch_add(1, std::memory_order_relaxed);
78 }
79
80 const Statistic &operator--() {
81 Value.fetch_sub(1, std::memory_order_relaxed);
82 return init();
83 }
84
85 unsigned operator--(int) {
86 init();
87 return Value.fetch_sub(1, std::memory_order_relaxed);
88 }
89
90 const Statistic &operator+=(unsigned V) {
91 if (V == 0)
92 return *this;
93 Value.fetch_add(V, std::memory_order_relaxed);
94 return init();
95 }
96
97 const Statistic &operator-=(unsigned V) {
98 if (V == 0)
99 return *this;
100 Value.fetch_sub(V, std::memory_order_relaxed);
101 return init();
102 }
103
104 void updateMax(unsigned V) {
105 unsigned PrevMax = Value.load(std::memory_order_relaxed);
106 // Keep trying to update max until we succeed or another thread produces
107 // a bigger max than us.
108 while (V > PrevMax && !Value.compare_exchange_weak(
109 PrevMax, V, std::memory_order_relaxed)) {
110 }
111 init();
112 }
113
114#else // Statistics are disabled in release builds.
115
116 const Statistic &operator=(unsigned Val) {
117 return *this;
118 }
119
120 const Statistic &operator++() {
121 return *this;
122 }
123
124 unsigned operator++(int) {
125 return 0;
126 }
127
128 const Statistic &operator--() {
129 return *this;
130 }
131
132 unsigned operator--(int) {
133 return 0;
134 }
135
136 const Statistic &operator+=(const unsigned &V) {
137 return *this;
138 }
139
140 const Statistic &operator-=(const unsigned &V) {
141 return *this;
142 }
143
144 void updateMax(unsigned V) {}
145
146#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
147
148protected:
149 Statistic &init() {
150 bool tmp = Initialized;
151 sys::MemoryFence();
152 if (!tmp) RegisterStatistic();
153 TsanHappensAfter(this);
154 return *this;
155 }
156
157 void RegisterStatistic();
158};
159
160// STATISTIC - A macro to make definition of statistics really simple. This
161// automatically passes the DEBUG_TYPE of the file into the statistic.
162#define STATISTIC(VARNAME, DESC)static llvm::Statistic VARNAME = {"mcexpr", "VARNAME", DESC, {
0}, false}
\
163 static llvm::Statistic VARNAME = {DEBUG_TYPE"mcexpr", #VARNAME, DESC, {0}, false}
164
165/// \brief Enable the collection and printing of statistics.
166void EnableStatistics(bool PrintOnExit = true);
167
168/// \brief Check if statistics are enabled.
169bool AreStatisticsEnabled();
170
171/// \brief Return a file stream to print our output on.
172std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile();
173
174/// \brief Print statistics to the file returned by CreateInfoOutputFile().
175void PrintStatistics();
176
177/// \brief Print statistics to the given output stream.
178void PrintStatistics(raw_ostream &OS);
179
180/// Print statistics in JSON format. This does include all global timers (\see
181/// Timer, TimerGroup). Note that the timers are cleared after printing and will
182/// not be printed in human readable form or in a second call of
183/// PrintStatisticsJSON().
184void PrintStatisticsJSON(raw_ostream &OS);
185
186} // end namespace llvm
187
188#endif // LLVM_ADT_STATISTIC_H