| [141b786] | 1 | //
 | 
|---|
 | 2 | // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // The contents of this file are covered under the licence agreement in the
 | 
|---|
 | 5 | // file "LICENCE" distributed with Cforall.
 | 
|---|
 | 6 | //
 | 
|---|
| [c92bdcc] | 7 | // Explode.hpp --
 | 
|---|
| [141b786] | 8 | //
 | 
|---|
 | 9 | // Author           : Rob Schluntz
 | 
|---|
 | 10 | // Created On       : Wed Nov 9 13:12:24 2016
 | 
|---|
| [b910d15] | 11 | // Last Modified By : Andrew Beach
 | 
|---|
 | 12 | // Last Modified On : Mon Jun 17 14:36:00 2019
 | 
|---|
 | 13 | // Update Count     : 4
 | 
|---|
| [141b786] | 14 | //
 | 
|---|
 | 15 | 
 | 
|---|
| [6b0b624] | 16 | #pragma once
 | 
|---|
| [141b786] | 17 | 
 | 
|---|
| [62194cb] | 18 | #include <iterator>                     // for back_inserter, back_insert_iterator
 | 
|---|
 | 19 | #include <utility>                      // for forward
 | 
|---|
| [141b786] | 20 | 
 | 
|---|
| [432ce7a] | 21 | #include "AST/Expr.hpp"
 | 
|---|
 | 22 | #include "ResolvExpr/Candidate.hpp"     // for Candidate, CandidateList
 | 
|---|
 | 23 | #include "ResolvExpr/ExplodedArg.hpp"   // for ExplodedArg
 | 
|---|
| [c92bdcc] | 24 | #include "Tuples.hpp"                   // for maybeImpure
 | 
|---|
| [141b786] | 25 | 
 | 
|---|
| [432ce7a] | 26 | namespace ast {
 | 
|---|
 | 27 |         class SymbolTable;
 | 
|---|
 | 28 | }
 | 
|---|
 | 29 | 
 | 
|---|
| [141b786] | 30 | namespace Tuples {
 | 
|---|
| [432ce7a] | 31 | 
 | 
|---|
| [b910d15] | 32 | const ast::Expr * distributeReference( const ast::Expr * );
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | /// Append candidate to an OutputIterator of Candidates.
 | 
|---|
 | 35 | template<typename OutputIterator>
 | 
|---|
 | 36 | void append( OutputIterator out, const ast::Expr * expr, const ast::TypeEnvironment & env,
 | 
|---|
 | 37 |                 const ast::OpenVarSet & open, const ast::AssertionList & need,
 | 
|---|
 | 38 |                 const ResolvExpr::Cost & cost, const ResolvExpr::Cost & cvtCost ) {
 | 
|---|
 | 39 |         ast::TypeEnvironment copyEnv = env;
 | 
|---|
 | 40 |         ast::OpenVarSet copyOpen = open;
 | 
|---|
 | 41 |         ast::AssertionSet set;
 | 
|---|
 | 42 |         mergeAssertionSet( set, need );
 | 
|---|
 | 43 |         *out++ = std::make_shared<ResolvExpr::Candidate>( expr, std::move( copyEnv ),
 | 
|---|
 | 44 |                 std::move( copyOpen ), std::move( set ), cost, cvtCost );
 | 
|---|
 | 45 | }
 | 
|---|
 | 46 | 
 | 
|---|
 | 47 | /// Append candidate to an ExplodedArg.
 | 
|---|
 | 48 | static inline void append( ResolvExpr::ExplodedArg& ea, const ast::Expr * expr,
 | 
|---|
 | 49 |                 const ast::TypeEnvironment&, const ast::OpenVarSet&,
 | 
|---|
 | 50 |                 const ast::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
 | 
|---|
 | 51 |         // I'm not sure why most of the arguments are unused. But they were in the old version.
 | 
|---|
 | 52 |         ea.exprs.emplace_back( expr );
 | 
|---|
 | 53 | }
 | 
|---|
 | 54 | 
 | 
|---|
 | 55 | /// Check if the expression is a cast to a reference type, return it if it is.
 | 
|---|
 | 56 | static inline const ast::CastExpr * isReferenceCast( const ast::Expr * expr ) {
 | 
|---|
 | 57 |         if ( const ast::CastExpr * cast = dynamic_cast< const ast::CastExpr * >( expr ) ) {
 | 
|---|
 | 58 |                 if ( dynamic_cast< const ast::ReferenceType * >( cast->result.get() ) ) {
 | 
|---|
 | 59 |                         return cast;
 | 
|---|
 | 60 |                 }
 | 
|---|
 | 61 |         }
 | 
|---|
 | 62 |         return nullptr;
 | 
|---|
 | 63 | }
 | 
|---|
 | 64 | 
 | 
|---|
 | 65 | /// helper function (indirectely) used by explode
 | 
|---|
 | 66 | template< typename Output >
 | 
|---|
 | 67 | void explodeRecursive(
 | 
|---|
| [7870799] | 68 |         const ast::CastExpr *, const ResolvExpr::Candidate &,
 | 
|---|
 | 69 |         const ast::SymbolTable &, Output &&
 | 
|---|
| [b910d15] | 70 | ) {
 | 
|---|
 | 71 | }
 | 
|---|
 | 72 | 
 | 
|---|
| [432ce7a] | 73 | /// helper function used by explode
 | 
|---|
 | 74 | template< typename Output >
 | 
|---|
| [b910d15] | 75 | void explodeUnique(
 | 
|---|
 | 76 |         const ast::ptr< ast::Expr > & expr, const ResolvExpr::Candidate & arg,
 | 
|---|
 | 77 |         const ast::SymbolTable & symtab, Output && out, bool isTupleAssign
 | 
|---|
| [432ce7a] | 78 | ) {
 | 
|---|
| [b910d15] | 79 |         // Tuple assignment can use a faster method if it is cast. Uses recursive exploding.
 | 
|---|
 | 80 |         if ( isTupleAssign ) if ( const ast::CastExpr * castExpr = isReferenceCast( expr ) ) {
 | 
|---|
 | 81 |                 ResolvExpr::CandidateList candidates;
 | 
|---|
 | 82 |                 explodeUnique( castExpr->arg, arg, symtab, back_inserter( candidates ), true );
 | 
|---|
 | 83 |                 for ( ResolvExpr::CandidateRef & cand : candidates ) {
 | 
|---|
 | 84 |                         // Distribute the reference cast over all components of the candidate.
 | 
|---|
 | 85 |                         append( std::forward<Output>(out), distributeReference( cand->expr ), cand->env,
 | 
|---|
 | 86 |                                 cand->open, cand->need, cand->cost, cand->cvtCost );
 | 
|---|
 | 87 |                 }
 | 
|---|
 | 88 |                 return;
 | 
|---|
 | 89 |         }
 | 
|---|
 | 90 |         const ast::Type * res = expr->result->stripReferences();
 | 
|---|
 | 91 |         if ( const ast::TupleType * tupleType = dynamic_cast< const ast::TupleType * >( res ) ) {
 | 
|---|
 | 92 |                 if ( const ast::ptr< ast::TupleExpr > & tupleExpr = expr.as< ast::TupleExpr >() ) {
 | 
|---|
 | 93 |                         // Open the tuple expr and continue on its components.
 | 
|---|
 | 94 |                         for ( const ast::Expr * expr : tupleExpr->exprs ) {
 | 
|---|
 | 95 |                                 explodeUnique( expr, arg, symtab, std::forward<Output>(out), isTupleAssign );
 | 
|---|
 | 96 |                         }
 | 
|---|
 | 97 |                 } else {
 | 
|---|
 | 98 |                         ast::ptr< ast::Expr > local = expr;
 | 
|---|
 | 99 |                         // Expressions which may have side effects require a single unique instance.
 | 
|---|
 | 100 |                         if ( Tuples::maybeImpureIgnoreUnique( local ) ) {
 | 
|---|
 | 101 |                                 local = new ast::UniqueExpr( local->location, local );
 | 
|---|
 | 102 |                         }
 | 
|---|
 | 103 |                         // Cast a reference away to a value-type to allow further explosion.
 | 
|---|
| [417117e] | 104 |                         if ( local->result.as< ast::ReferenceType >() ) {
 | 
|---|
| [b8524ca] | 105 |                                 local = new ast::CastExpr{ local, tupleType };
 | 
|---|
| [b910d15] | 106 |                         }
 | 
|---|
 | 107 |                         // Now we have to go across the tuple via indexing.
 | 
|---|
 | 108 |                         for ( unsigned int i = 0 ; i < tupleType->size() ; ++i ) {
 | 
|---|
 | 109 |                                 ast::TupleIndexExpr * idx = new ast::TupleIndexExpr( local->location, local, i );
 | 
|---|
 | 110 |                                 explodeUnique( idx, arg, symtab, std::forward<Output>(out), isTupleAssign );
 | 
|---|
 | 111 |                                 // TODO: We need more input to figure out the exact lifetimes of these types.
 | 
|---|
 | 112 |                                 // delete idx;
 | 
|---|
 | 113 |                         }
 | 
|---|
 | 114 |                 }
 | 
|---|
 | 115 |         } else {
 | 
|---|
 | 116 |                 // For atomic/non-tuple types, no explosion is used.
 | 
|---|
 | 117 |                 append( std::forward<Output>(out), expr, arg.env, arg.open, arg.need, arg.cost,
 | 
|---|
 | 118 |                         arg.cvtCost );
 | 
|---|
 | 119 |         }
 | 
|---|
| [432ce7a] | 120 | }
 | 
|---|
 | 121 | 
 | 
|---|
 | 122 | /// expands a tuple-valued candidate into multiple candidates, each with a non-tuple type
 | 
|---|
 | 123 | template< typename Output >
 | 
|---|
| [b910d15] | 124 | void explode(
 | 
|---|
 | 125 |         const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out,
 | 
|---|
| [432ce7a] | 126 |         bool isTupleAssign = false
 | 
|---|
 | 127 | ) {
 | 
|---|
 | 128 |         explodeUnique( arg.expr, arg, symtab, std::forward< Output >( out ), isTupleAssign );
 | 
|---|
 | 129 | }
 | 
|---|
 | 130 | 
 | 
|---|
| [234b1cb] | 131 | /// explode list of candidates into flattened list of candidates
 | 
|---|
 | 132 | template< typename Output >
 | 
|---|
| [7870799] | 133 | void explode(
 | 
|---|
 | 134 |         const ResolvExpr::CandidateList & cands, const ast::SymbolTable & symtab, Output && out,
 | 
|---|
| [234b1cb] | 135 |         bool isTupleAssign = false
 | 
|---|
 | 136 | ) {
 | 
|---|
 | 137 |         for ( const ResolvExpr::CandidateRef & cand : cands ) {
 | 
|---|
 | 138 |                 explode( *cand, symtab, std::forward< Output >( out ), isTupleAssign );
 | 
|---|
 | 139 |         }
 | 
|---|
 | 140 | }
 | 
|---|
 | 141 | 
 | 
|---|
| [141b786] | 142 | } // namespace Tuples
 | 
|---|
 | 143 | 
 | 
|---|
 | 144 | // Local Variables: //
 | 
|---|
 | 145 | // tab-width: 4 //
 | 
|---|
 | 146 | // mode: c++ //
 | 
|---|
 | 147 | // compile-command: "make install" //
 | 
|---|
 | 148 | // End: //
 | 
|---|