16bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//===- ThreadSafetyTraverse.h ----------------------------------*- C++ --*-===//
26bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
36bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//                     The LLVM Compiler Infrastructure
46bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
56bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// This file is distributed under the University of Illinois Open Source
66bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// License. See LICENSE.TXT for details.
76bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
86bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//===----------------------------------------------------------------------===//
96bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// This file defines a framework for doing generic traversals and rewriting
116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// operations over the Thread Safety TIL.
126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// UNDER CONSTRUCTION.  USE AT YOUR OWN RISK.
146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//===----------------------------------------------------------------------===//
166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#ifndef LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "ThreadSafetyTIL.h"
216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesnamespace clang {
236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesnamespace threadSafety {
246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesnamespace til {
256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// Defines an interface used to traverse SExprs.  Traversals have been made as
276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// generic as possible, and are intended to handle any kind of pass over the
286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// AST, e.g. visiters, copying, non-destructive rewriting, destructive
296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// (in-place) rewriting, hashing, typing, etc.
306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// Traversals implement the functional notion of a "fold" operation on SExprs.
326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// Each SExpr class provides a traverse method, which does the following:
336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//   * e->traverse(v):
346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//       // compute a result r_i for each subexpression e_i
356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//       for (i = 1..n)  r_i = v.traverse(e_i);
366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//       // combine results into a result for e,  where X is the class of e
376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//       return v.reduceX(*e, r_1, .. r_n).
386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// A visitor can control the traversal by overriding the following methods:
406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//   * v.traverse(e):
416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//       return v.traverseByCase(e), which returns v.traverseX(e)
426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//   * v.traverseX(e):   (X is the class of e)
436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//       return e->traverse(v).
446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//   * v.reduceX(*e, r_1, .. r_n):
456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//       compute a result for a node of type X
466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// The reduceX methods control the kind of traversal (visitor, copy, etc.).
48ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// They are defined in derived classes.
49ef8225444452a1486bd721f3285301fe84643b00Stephen Hines//
50ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// Class R defines the basic interface types (R_SExpr).
51ef8225444452a1486bd721f3285301fe84643b00Stephen Hinestemplate <class Self, class R>
52ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass Traversal {
536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
54ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  Self *self() { return static_cast<Self *>(this); }
556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Traverse an expression -- returning a result of type R_SExpr.
576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Override this method to do something for every expression, regardless
58ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // of which kind it is.
59ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  typename R::R_SExpr traverse(SExprRef &E, typename R::R_Ctx Ctx) {
60ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return traverse(E.get(), Ctx);
616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
63ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  typename R::R_SExpr traverse(SExpr *E, typename R::R_Ctx Ctx) {
64ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return traverseByCase(E, Ctx);
656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Helper method to call traverseX(e) on the appropriate type.
68ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  typename R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx) {
696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    switch (E->opcode()) {
706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#define TIL_OPCODE_DEF(X)                                                   \
716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    case COP_##X:                                                           \
72ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      return self()->traverse##X(cast<X>(E), Ctx);
736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "ThreadSafetyOps.def"
746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#undef TIL_OPCODE_DEF
756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// Traverse e, by static dispatch on the type "X" of e.
796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// Override these methods to do something for a particular kind of term.
806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#define TIL_OPCODE_DEF(X)                                                   \
81ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) {            \
82ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return e->traverse(*self(), Ctx);                                       \
83ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "ThreadSafetyOps.def"
856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#undef TIL_OPCODE_DEF
866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
89ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// Base class for simple reducers that don't much care about the context.
90ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass SimpleReducerBase {
916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
92ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  enum TraversalKind {
93ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    TRV_Normal,
94ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    TRV_Decl,
95ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    TRV_Lazy,
96ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    TRV_Type
97ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  };
98ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
99ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // R_Ctx defines a "context" for the traversal, which encodes information
100ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // about where a term appears.  This can be used to encoding the
101ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // "current continuation" for CPS transforms, or other information.
102ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  typedef TraversalKind R_Ctx;
103ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
104ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // Create context for an ordinary subexpression.
105ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; }
106ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
107ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // Create context for a subexpression that occurs in a declaration position
108ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // (e.g. function body).
109ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_Ctx declCtx(R_Ctx Ctx) { return TRV_Decl; }
110ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
111ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // Create context for a subexpression that occurs in a position that
112ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // should be reduced lazily.  (e.g. code body).
113ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_Ctx lazyCtx(R_Ctx Ctx) { return TRV_Lazy; }
114ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
115ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // Create context for a subexpression that occurs in a type position.
116ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; }
117ef8225444452a1486bd721f3285301fe84643b00Stephen Hines};
1186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
120ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// Base class for traversals that rewrite an SExpr to another SExpr.
121ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass CopyReducerBase : public SimpleReducerBase {
122ef8225444452a1486bd721f3285301fe84643b00Stephen Hinespublic:
1236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // R_SExpr is the result type for a traversal.
1246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // A copy or non-destructive rewrite returns a newly allocated term.
1256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  typedef SExpr *R_SExpr;
126ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  typedef BasicBlock *R_BasicBlock;
1276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Container is a minimal interface used to store results when traversing
1296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // SExprs of variable arity, such as Phi, Goto, and SCFG.
1306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  template <class T> class Container {
1316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  public:
1326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    // Allocate a new container with a capacity for n elements.
133ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {}
1346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    // Push a new element onto the container.
1366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    void push_back(T E) { Elems.push_back(E); }
1376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SimpleArray<T> Elems;
1396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  };
1406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
141ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  CopyReducerBase(MemRegionRef A) : Arena(A) {}
142ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
143ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesprotected:
144ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  MemRegionRef Arena;
145ef8225444452a1486bd721f3285301fe84643b00Stephen Hines};
146ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
147ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
148ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// Implements a traversal that makes a deep copy of an SExpr.
149ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// The default behavior of reduce##X(...) is to create a copy of the original.
150ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// Subclasses can override reduce##X to implement non-destructive rewriting
151ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// passes.
152ef8225444452a1486bd721f3285301fe84643b00Stephen Hinestemplate<class Self>
153ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass CopyReducer : public Traversal<Self, CopyReducerBase>,
154ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                    public CopyReducerBase {
155ef8225444452a1486bd721f3285301fe84643b00Stephen Hinespublic:
156ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  CopyReducer(MemRegionRef A) : CopyReducerBase(A) {}
157ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
1586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
1596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceNull() {
1606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
1616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // R_SExpr reduceFuture(...)  is never used.
1636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceUndefined(Undefined &Orig) {
1656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Undefined(Orig);
1666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceWildcard(Wildcard &Orig) {
1686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Wildcard(Orig);
1696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceLiteral(Literal &Orig) {
1726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Literal(Orig);
1736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
174ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  template<class T>
175ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_SExpr reduceLiteralT(LiteralT<T> &Orig) {
176ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return new (Arena) LiteralT<T>(Orig);
177ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
1786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceLiteralPtr(LiteralPtr &Orig) {
1796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) LiteralPtr(Orig);
1806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
1836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Function(Orig, Nvd, E0);
1846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
1866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) SFunction(Orig, Nvd, E0);
1876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
1896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Code(Orig, E0, E1);
1906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
1926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Field(Orig, E0, E1);
1936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
1966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Apply(Orig, E0, E1);
1976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
1996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) SApply(Orig, E0, E1);
2006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceProject(Project &Orig, R_SExpr E0) {
2026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Project(Orig, E0);
2036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceCall(Call &Orig, R_SExpr E0) {
2056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Call(Orig, E0);
2066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) {
2096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Alloc(Orig, E0);
2106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceLoad(Load &Orig, R_SExpr E0) {
2126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Load(Orig, E0);
2136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) {
2156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Store(Orig, E0, E1);
2166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
217ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_SExpr reduceArrayIndex(ArrayIndex &Orig, R_SExpr E0, R_SExpr E1) {
218ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return new (Arena) ArrayIndex(Orig, E0, E1);
2196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) {
2216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) ArrayAdd(Orig, E0, E1);
2226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
2246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) UnaryOp(Orig, E0);
2256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
2276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) BinaryOp(Orig, E0, E1);
2286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceCast(Cast &Orig, R_SExpr E0) {
2306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Cast(Orig, E0);
2316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) {
234ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return nullptr;  // FIXME: implement CFG rewriting
235ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
236ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
237ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                Container<Variable *> &Is, R_SExpr T) {
238ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return nullptr;  // FIXME: implement CFG rewriting
2396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
2416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Phi(Orig, std::move(As.Elems));
2426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
243ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
244ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return new (Arena) Goto(Orig, B, 0);  // FIXME: set index
2456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
247ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return new (Arena) Branch(O, C, B0, B1, 0, 0);  // FIXME: set indices
2486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceIdentifier(Identifier &Orig) {
2516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Identifier(Orig);
2526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
2546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) IfThenElse(Orig, C, T, E);
2556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
2576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Let(Orig, Nvd, B);
2586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Create a new variable from orig, and push it onto the lexical scope.
2616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Variable *enterScope(Variable &Orig, R_SExpr E0) {
2626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return new (Arena) Variable(Orig, E0);
2636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Exit the lexical scope of orig.
2656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void exitScope(const Variable &Orig) {}
2666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void enterCFG(SCFG &Cfg) {}
2686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void exitCFG(SCFG &Cfg) {}
269ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void enterBasicBlock(BasicBlock &BB) {}
270ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void exitBasicBlock(BasicBlock &BB) {}
2716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Map Variable references to their rewritten definitions.
2736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
2746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
275ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // Map BasicBlock references to their rewritten definitions.
2766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
2776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
2786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
280ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass SExprCopier : public CopyReducer<SExprCopier> {
2816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
282ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  typedef SExpr *R_SExpr;
283ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
284ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  SExprCopier(MemRegionRef A) : CopyReducer(A) { }
2856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Create a copy of e in region a.
2876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static SExpr *copy(SExpr *E, MemRegionRef A) {
2886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SExprCopier Copier(A);
289ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return Copier.traverse(E, TRV_Normal);
2906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
2916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
2926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
2946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
295ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// Base class for visit traversals.
296ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass VisitReducerBase : public SimpleReducerBase {
297ef8225444452a1486bd721f3285301fe84643b00Stephen Hinespublic:
2986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // A visitor returns a bool, representing success or failure.
2996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  typedef bool R_SExpr;
300ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  typedef bool R_BasicBlock;
3016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // A visitor "container" is a single bool, which accumulates success.
3036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  template <class T> class Container {
3046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  public:
305ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    Container(VisitReducerBase &S, unsigned N) : Success(true) {}
3066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    void push_back(bool E) { Success = Success && E; }
3076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    bool Success;
3096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  };
310ef8225444452a1486bd721f3285301fe84643b00Stephen Hines};
311ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
312ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
313ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// Implements a traversal that visits each subexpression, and returns either
314ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// true or false.
315ef8225444452a1486bd721f3285301fe84643b00Stephen Hinestemplate <class Self>
316ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass VisitReducer : public Traversal<Self, VisitReducerBase>,
317ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                     public VisitReducerBase {
318ef8225444452a1486bd721f3285301fe84643b00Stephen Hinespublic:
319ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  VisitReducer() {}
3206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
3226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceNull() { return true; }
3236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceUndefined(Undefined &Orig) { return true; }
3246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceWildcard(Wildcard &Orig) { return true; }
3256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceLiteral(Literal &Orig) { return true; }
327ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  template<class T>
328ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; }
3296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceLiteralPtr(Literal &Orig) { return true; }
3306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
3326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return Nvd && E0;
3336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
3356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return Nvd && E0;
3366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
3386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return E0 && E1;
3396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
3416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return E0 && E1;
3426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
3446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return E0 && E1;
3456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
3476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return E0 && E1;
3486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
3506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
3516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
3526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
3536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
354ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) {
355ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return E0 && E1;
356ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
3576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
3586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return E0 && E1;
3596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
3616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
3626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return E0 && E1;
3636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
3656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
3676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return Bbs.Success;
3686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
369ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
370ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                Container<Variable *> &Is, R_SExpr T) {
371ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return (As.Success && Is.Success && T);
372ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
373ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
3746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return As.Success;
3756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
376ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
3776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return true;
3786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
3806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return C;
3816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
3836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceIdentifier(Identifier &Orig) {
3846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return true;
3856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
3876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return C && T && E;
3886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
3906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return Nvd && B;
3916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
393ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  Variable *enterScope(Variable &Orig, R_SExpr E0) { return &Orig; }
3946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void exitScope(const Variable &Orig) {}
3956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void enterCFG(SCFG &Cfg) {}
3966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void exitCFG(SCFG &Cfg) {}
397ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void enterBasicBlock(BasicBlock &BB) {}
398ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void exitBasicBlock(BasicBlock &BB) {}
3996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
400ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  Variable   *reduceVariableRef  (Variable *Ovd)   { return Ovd; }
4016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
4026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
4046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool traverse(SExpr *E, TraversalKind K = TRV_Normal) {
4056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Success = Success && this->traverseByCase(E);
4066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return Success;
4076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static bool visit(SExpr *E) {
410ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    Self Visitor;
411ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return Visitor.traverse(E, TRV_Normal);
4126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesprivate:
4156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool Success;
4166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
4176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// Basic class for comparison operations over expressions.
4206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinestemplate <typename Self>
4216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesclass Comparator {
4226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesprotected:
4236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Self *self() { return reinterpret_cast<Self *>(this); }
4246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
4266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool compareByCase(SExpr *E1, SExpr* E2) {
4276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    switch (E1->opcode()) {
4286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#define TIL_OPCODE_DEF(X)                                                     \
4296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    case COP_##X:                                                             \
4306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return cast<X>(E1)->compare(cast<X>(E2), *self());
4316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "ThreadSafetyOps.def"
4326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#undef TIL_OPCODE_DEF
4336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
4346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
4366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesclass EqualsComparator : public Comparator<EqualsComparator> {
4396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
4406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Result type for the comparison, e.g. bool for simple equality,
4416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // or int for lexigraphic comparison (-1, 0, 1).  Must have one value which
4426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // denotes "true".
4436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  typedef bool CType;
4446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  CType trueResult() { return true; }
4466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool notTrue(CType ct) { return !ct; }
4476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool compareIntegers(unsigned i, unsigned j)       { return i == j; }
4496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool compareStrings (StringRef s, StringRef r)     { return s == r; }
4506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool comparePointers(const void* P, const void* Q) { return P == Q; }
4516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool compare(SExpr *E1, SExpr* E2) {
4536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (E1->opcode() != E2->opcode())
4546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return false;
4556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return compareByCase(E1, E2);
4566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // TODO -- handle alpha-renaming of variables
4596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void enterScope(Variable* V1, Variable* V2) { }
4606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void leaveScope() { }
4616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool compareVariableRefs(Variable* V1, Variable* V2) {
4636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return V1 == V2;
4646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static bool compareExprs(SExpr *E1, SExpr* E2) {
4676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    EqualsComparator Eq;
4686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return Eq.compare(E1, E2);
4696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
4716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// Pretty printer for TIL expressions
4746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinestemplate <typename Self, typename StreamType>
4756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesclass PrettyPrinter {
4766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesprivate:
4776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool Verbose;  // Print out additional information
478ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  bool Cleanup;  // Omit redundant decls.
4796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic:
481ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { }
4826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static void print(SExpr *E, StreamType &SS) {
4846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Self printer;
4856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printer.printSExpr(E, SS, Prec_MAX);
4866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesprotected:
4896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Self *self() { return reinterpret_cast<Self *>(this); }
4906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void newline(StreamType &SS) {
4926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "\n";
4936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
4946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // TODO: further distinguish between binary operations.
4966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static const unsigned Prec_Atom = 0;
4976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static const unsigned Prec_Postfix = 1;
4986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static const unsigned Prec_Unary = 2;
4996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static const unsigned Prec_Binary = 3;
5006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static const unsigned Prec_Other = 4;
5016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static const unsigned Prec_Decl = 5;
5026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static const unsigned Prec_MAX = 6;
5036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Return the precedence of a given node, for use in pretty printing.
5056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  unsigned precedence(SExpr *E) {
5066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    switch (E->opcode()) {
5076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Future:     return Prec_Atom;
5086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Undefined:  return Prec_Atom;
5096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Wildcard:   return Prec_Atom;
5106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Literal:    return Prec_Atom;
5126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_LiteralPtr: return Prec_Atom;
5136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Variable:   return Prec_Atom;
5146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Function:   return Prec_Decl;
5156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_SFunction:  return Prec_Decl;
5166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Code:       return Prec_Decl;
5176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Field:      return Prec_Decl;
5186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Apply:      return Prec_Postfix;
5206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_SApply:     return Prec_Postfix;
5216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Project:    return Prec_Postfix;
5226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Call:       return Prec_Postfix;
5246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Alloc:      return Prec_Other;
5256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Load:       return Prec_Postfix;
5266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Store:      return Prec_Other;
527ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      case COP_ArrayIndex: return Prec_Postfix;
5286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_ArrayAdd:   return Prec_Postfix;
5296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_UnaryOp:    return Prec_Unary;
5316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_BinaryOp:   return Prec_Binary;
5326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Cast:       return Prec_Unary;
5336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_SCFG:       return Prec_Decl;
535ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      case COP_BasicBlock: return Prec_MAX;
5366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Phi:        return Prec_Atom;
5376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Goto:       return Prec_Atom;
5386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Branch:     return Prec_Atom;
5396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Identifier: return Prec_Atom;
5416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_IfThenElse: return Prec_Other;
5426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case COP_Let:        return Prec_Decl;
5436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
5446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return Prec_MAX;
5456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
5466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
547ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) {
548ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (!BB) {
549ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SS << "BB_null";
550ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      return;
551ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    }
552ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << "BB_";
553ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << BB->blockID();
554ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << ":";
555ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << index;
556ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
557ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
5586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printSExpr(SExpr *E, StreamType &SS, unsigned P) {
5596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!E) {
5606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->printNull(SS);
5616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return;
5626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
5636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (self()->precedence(E) > P) {
5646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // Wrap expr in () if necessary.
5656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << "(";
5666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->printSExpr(E, SS, Prec_MAX);
5676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << ")";
5686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return;
5696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
5706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    switch (E->opcode()) {
5726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#define TIL_OPCODE_DEF(X)                                                  \
5736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    case COP_##X:                                                          \
5746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->print##X(cast<X>(E), SS);                                    \
5756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return;
5766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "ThreadSafetyOps.def"
5776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#undef TIL_OPCODE_DEF
5786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
5796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
5806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printNull(StreamType &SS) {
5826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "#null";
5836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
5846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printFuture(Future *E, StreamType &SS) {
5866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
5876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
5886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printUndefined(Undefined *E, StreamType &SS) {
5906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "#undefined";
5916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
5926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printWildcard(Wildcard *E, StreamType &SS) {
5946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "_";
5956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
5966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
5976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  template<class T>
5986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printLiteralT(LiteralT<T> *E, StreamType &SS) {
5996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << E->value();
6006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
6016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
602ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void printLiteralT(LiteralT<uint8_t> *E, StreamType &SS) {
603ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << "'" << E->value() << "'";
604ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
605ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
6066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printLiteral(Literal *E, StreamType &SS) {
607ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (E->clangExpr()) {
6086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << getSourceLiteralString(E->clangExpr());
609ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      return;
610ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    }
6116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    else {
6126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      ValueType VT = E->valueType();
6136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      switch (VT.Base) {
6146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case ValueType::BT_Void: {
6156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << "void";
6166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        return;
6176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case ValueType::BT_Bool: {
619ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        if (E->as<bool>().value())
6206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          SS << "true";
6216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        else
6226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          SS << "false";
6236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        return;
6246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case ValueType::BT_Int: {
6266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        switch (VT.Size) {
6276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        case ValueType::ST_8:
6286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          if (VT.Signed)
629ef8225444452a1486bd721f3285301fe84643b00Stephen Hines            printLiteralT(&E->as<int8_t>(), SS);
6306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          else
631ef8225444452a1486bd721f3285301fe84643b00Stephen Hines            printLiteralT(&E->as<uint8_t>(), SS);
6326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          return;
6336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        case ValueType::ST_16:
6346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          if (VT.Signed)
635ef8225444452a1486bd721f3285301fe84643b00Stephen Hines            printLiteralT(&E->as<int16_t>(), SS);
6366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          else
637ef8225444452a1486bd721f3285301fe84643b00Stephen Hines            printLiteralT(&E->as<uint16_t>(), SS);
6386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          return;
6396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        case ValueType::ST_32:
6406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          if (VT.Signed)
641ef8225444452a1486bd721f3285301fe84643b00Stephen Hines            printLiteralT(&E->as<int32_t>(), SS);
6426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          else
643ef8225444452a1486bd721f3285301fe84643b00Stephen Hines            printLiteralT(&E->as<uint32_t>(), SS);
6446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          return;
6456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        case ValueType::ST_64:
6466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          if (VT.Signed)
647ef8225444452a1486bd721f3285301fe84643b00Stephen Hines            printLiteralT(&E->as<int64_t>(), SS);
6486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          else
649ef8225444452a1486bd721f3285301fe84643b00Stephen Hines            printLiteralT(&E->as<uint64_t>(), SS);
6506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          return;
6516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        default:
6526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          break;
6536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        }
6546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        break;
6556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case ValueType::BT_Float: {
6576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        switch (VT.Size) {
6586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        case ValueType::ST_32:
659ef8225444452a1486bd721f3285301fe84643b00Stephen Hines          printLiteralT(&E->as<float>(), SS);
6606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          return;
6616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        case ValueType::ST_64:
662ef8225444452a1486bd721f3285301fe84643b00Stephen Hines          printLiteralT(&E->as<double>(), SS);
6636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          return;
6646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        default:
6656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          break;
6666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        }
6676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        break;
6686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case ValueType::BT_String: {
6706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << "\"";
671ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        printLiteralT(&E->as<StringRef>(), SS);
6726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << "\"";
6736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        return;
6746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case ValueType::BT_Pointer: {
6766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << "#ptr";
6776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        return;
6786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case ValueType::BT_ValueRef: {
6806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << "#vref";
6816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        return;
6826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
6856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "#lit";
6866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
6876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
6886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printLiteralPtr(LiteralPtr *E, StreamType &SS) {
6896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << E->clangDecl()->getNameAsString();
6906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
6916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
6926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printVariable(Variable *V, StreamType &SS, bool IsVarDecl = false) {
693ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (!IsVarDecl && Cleanup) {
694ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SExpr* E = getCanonicalVal(V);
6956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (E != V) {
6966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        printSExpr(E, SS, Prec_Atom);
6976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        return;
6986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
700ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (V->kind() == Variable::VK_LetBB)
701ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SS << V->name() << V->getBlockID() << "_" << V->getID();
702ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    else
703ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SS << V->name() << V->getID();
7046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) {
7076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    switch (sugared) {
7086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      default:
7096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << "\\(";   // Lambda
7106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        break;
7116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case 1:
7126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << "(";     // Slot declarations
7136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        break;
7146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      case 2:
7156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << ", ";    // Curried functions
7166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        break;
7176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
7186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printVariable(E->variableDecl(), SS, true);
7196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << ": ";
7206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
7216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SExpr *B = E->body();
7236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (B && B->opcode() == COP_Function)
7246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->printFunction(cast<Function>(B), SS, 2);
7256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    else {
7266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << ")";
7276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->printSExpr(B, SS, Prec_Decl);
7286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
7296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printSFunction(SFunction *E, StreamType &SS) {
7326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "@";
7336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printVariable(E->variableDecl(), SS, true);
7346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << " ";
7356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->body(), SS, Prec_Decl);
7366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printCode(Code *E, StreamType &SS) {
7396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << ": ";
7406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
7416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << " -> ";
7426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->body(), SS, Prec_Decl);
7436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printField(Field *E, StreamType &SS) {
7466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << ": ";
7476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->range(), SS, Prec_Decl-1);
7486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << " = ";
7496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->body(), SS, Prec_Decl);
7506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printApply(Apply *E, StreamType &SS, bool sugared = false) {
7536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SExpr *F = E->fun();
7546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (F->opcode() == COP_Apply) {
7556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      printApply(cast<Apply>(F), SS, true);
7566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << ", ";
7576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    } else {
7586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->printSExpr(F, SS, Prec_Postfix);
7596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << "(";
7606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
7616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->arg(), SS, Prec_MAX);
7626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!sugared)
7636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << ")$";
7646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printSApply(SApply *E, StreamType &SS) {
7676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->sfun(), SS, Prec_Postfix);
7686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (E->isDelegation()) {
7696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << "@(";
7706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->printSExpr(E->arg(), SS, Prec_MAX);
7716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << ")";
7726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
7736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printProject(Project *E, StreamType &SS) {
7766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->record(), SS, Prec_Postfix);
7776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << ".";
7786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << E->slotName();
7796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printCall(Call *E, StreamType &SS) {
7826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SExpr *T = E->target();
7836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (T->opcode() == COP_Apply) {
7846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->printApply(cast<Apply>(T), SS, true);
7856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << ")";
7866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
7876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    else {
7886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->printSExpr(T, SS, Prec_Postfix);
7896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SS << "()";
7906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
7916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printAlloc(Alloc *E, StreamType &SS) {
7946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "new ";
7956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->dataType(), SS, Prec_Other-1);
7966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
7976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printLoad(Load *E, StreamType &SS) {
7996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->pointer(), SS, Prec_Postfix);
8006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "^";
8016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printStore(Store *E, StreamType &SS) {
8046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->destination(), SS, Prec_Other-1);
8056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << " := ";
8066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->source(), SS, Prec_Other-1);
8076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
809ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void printArrayIndex(ArrayIndex *E, StreamType &SS) {
8106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->array(), SS, Prec_Postfix);
811ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << "[";
812ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    self()->printSExpr(E->index(), SS, Prec_MAX);
813ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << "]";
8146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printArrayAdd(ArrayAdd *E, StreamType &SS) {
8176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->array(), SS, Prec_Postfix);
8186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << " + ";
8196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->index(), SS, Prec_Atom);
8206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printUnaryOp(UnaryOp *E, StreamType &SS) {
8236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << getUnaryOpcodeString(E->unaryOpcode());
8246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->expr(), SS, Prec_Unary);
8256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printBinaryOp(BinaryOp *E, StreamType &SS) {
8286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
8296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " ";
8306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
8316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printCast(Cast *E, StreamType &SS) {
8346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "%";
8356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->expr(), SS, Prec_Unary);
8366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printSCFG(SCFG *E, StreamType &SS) {
839ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << "CFG {\n";
8406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    for (auto BBI : *E) {
841ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      printBasicBlock(BBI, SS);
842ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    }
843ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << "}";
844ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    newline(SS);
845ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  }
846ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
847ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void printBasicBlock(BasicBlock *E, StreamType &SS) {
848ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SS << "BB_" << E->blockID() << ":";
849ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (E->parent())
850ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SS << " BB_" << E->parent()->blockID();
851ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    newline(SS);
852ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    for (auto *A : E->arguments()) {
853ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SS << "let ";
854ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      self()->printVariable(A, SS, true);
855ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SS << " = ";
856ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      self()->printSExpr(A->definition(), SS, Prec_MAX);
857ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SS << ";";
8586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      newline(SS);
859ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    }
860ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    for (auto *I : E->instructions()) {
861ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      if (I->definition()->opcode() != COP_Store) {
8626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << "let ";
863ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        self()->printVariable(I, SS, true);
8646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        SS << " = ";
8656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
866ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      self()->printSExpr(I->definition(), SS, Prec_MAX);
867ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SS << ";";
868ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      newline(SS);
869ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    }
870ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    SExpr *T = E->terminator();
871ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (T) {
872ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      self()->printSExpr(T, SS, Prec_MAX);
873ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      SS << ";";
8746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      newline(SS);
8756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
8766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    newline(SS);
8776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printPhi(Phi *E, StreamType &SS) {
8806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "phi(";
8816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (E->status() == Phi::PH_SingleVal)
8826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      self()->printSExpr(E->values()[0], SS, Prec_MAX);
8836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    else {
8846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      unsigned i = 0;
8856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      for (auto V : E->values()) {
8866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        if (i++ > 0)
8876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          SS << ", ";
8886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        self()->printSExpr(V, SS, Prec_MAX);
8896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
8906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
8916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << ")";
8926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printGoto(Goto *E, StreamType &SS) {
8956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "goto ";
8966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printBlockLabel(SS, E->targetBlock(), E->index());
8976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printBranch(Branch *E, StreamType &SS) {
9006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "branch (";
9016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    self()->printSExpr(E->condition(), SS, Prec_MAX);
9026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << ") ";
9036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printBlockLabel(SS, E->thenBlock(), E->thenIndex());
9046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << " ";
9056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printBlockLabel(SS, E->elseBlock(), E->elseIndex());
9066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
9076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
9086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printIdentifier(Identifier *E, StreamType &SS) {
9096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << E->name();
9106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
9116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
9126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printIfThenElse(IfThenElse *E, StreamType &SS) {
9136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "if (";
9146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printSExpr(E->condition(), SS, Prec_MAX);
9156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << ") then ";
9166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printSExpr(E->thenExpr(), SS, Prec_Other);
9176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << " else ";
9186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printSExpr(E->elseExpr(), SS, Prec_Other);
9196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
9206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
9216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void printLet(Let *E, StreamType &SS) {
9226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "let ";
9236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printVariable(E->variableDecl(), SS, true);
9246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << " = ";
9256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1);
9266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SS << "; ";
9276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    printSExpr(E->body(), SS, Prec_Decl-1);
9286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
9296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
9306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
9316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
9326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} // end namespace til
9336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} // end namespace threadSafety
9346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} // end namespace clang
9356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
9366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#endif  // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
937