source: src/Tuples/Explode.cc @ ab1a9ea

ADTast-experimentalenumforall-pointer-decaypthread-emulationqualifiedEnum
Last change on this file since ab1a9ea was 74807be, checked in by Fangren Yu <f37yu@…>, 4 years ago

please do not create a node and throw it away

  • Property mode set to 100644
File size: 7.2 KB
RevLine 
[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//
7// Explode.cc --
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 : Wed Jun 12 16:40:00 2016
13// Update Count     : 3
[141b786]14//
15
16#include "Explode.h"
[8135d4c]17#include <list>                  // for list
[03321e4]18
[8135d4c]19#include "SynTree/Mutator.h"     // for Mutator
20#include "Common/PassVisitor.h"  // for PassVisitor
[141b786]21
22namespace Tuples {
23        namespace {
[0b5d871]24                // remove one level of reference from a reference type -- may be useful elsewhere.
25                Type * getReferenceBase( Type * t ) {
26                        if ( ReferenceType * refType = dynamic_cast<ReferenceType *>( t ) ) {
27                                return refType->get_base();
28                        } else {
29                                // for the moment, I want to know immediately if a non-reference type is ever passed in here.
30                                assertf( false, "getReferenceBase for non-ref: %s", toString( refType ).c_str() );
31                                return nullptr;
32                        }
33                }
34
35                struct CastExploder {
36                        bool castAdded = false;
[141b786]37                        bool foundUniqueExpr = false;
[0b5d871]38                        Expression * applyCast( Expression * expr, bool first = true ) {
[141b786]39                                if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ){
[a64644c]40                                        foundUniqueExpr = true;
[141b786]41                                        std::list< Expression * > exprs;
42                                        for ( Expression *& expr : tupleExpr->get_exprs() ) {
[0b5d871]43                                                // move cast into tuple exprs
44                                                exprs.push_back( applyCast( expr, false ) );
[141b786]45                                        }
[0b5d871]46                                        // want the top-level expression to be cast to reference type, but not nested
[141b786]47                                        // tuple expressions
48                                        if ( first ) {
[0b5d871]49                                                castAdded = true;
50                                                Expression * tupleExpr = new TupleExpr( exprs );
51                                                return new CastExpr( tupleExpr, new ReferenceType( Type::Qualifiers(), tupleExpr->result->clone() ) );
[141b786]52                                        } else {
53                                                return new TupleExpr( exprs );
54                                        }
55                                }
[0b5d871]56                                if ( dynamic_cast<ReferenceType*>( expr->result ) ) {
57                                        // don't need to cast reference type to another reference type
58                                        return expr->clone();
59                                } else {
60                                        // anything else should be cast to reference as normal
61                                        castAdded = true;
62                                        return new CastExpr( expr->clone(), new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
63                                }
[141b786]64                        }
65
[0b5d871]66                        Expression * postmutate( UniqueExpr * uniqueExpr ) {
67                                // move cast into unique expr so that the unique expr has type T& rather than
[141b786]68                                // type T. In particular, this transformation helps with generating the
[0b5d871]69                                // correct code for reference-cast member tuple expressions, since the result
70                                // should now be a tuple of references rather than a reference to a tuple.
[141b786]71                                // Still, this code is a bit awkward, and could use some improvement.
[0b5d871]72                                UniqueExpr * newUniqueExpr = new UniqueExpr( applyCast( uniqueExpr->get_expr() ), uniqueExpr->get_id() );
[141b786]73                                delete uniqueExpr;
[0b5d871]74                                if ( castAdded ) {
75                                        // if a cast was added by applyCast, then unique expr now has one more layer of reference
76                                        // than it had coming into this function. To ensure types still match correctly, need to cast
77                                        //  to reference base so that outer expressions are still correct.
78                                        castAdded = false;
79                                        Type * toType = getReferenceBase( newUniqueExpr->result );
80                                        return new CastExpr( newUniqueExpr, toType->clone() );
81                                }
82                                return newUniqueExpr;
[141b786]83                        }
84
[0b5d871]85
86                        Expression * postmutate( TupleIndexExpr * tupleExpr ) {
[141b786]87                                // tuple index expr needs to be rebuilt to ensure that the type of the
88                                // field is consistent with the type of the tuple expr, since the field
[0b5d871]89                                // may have changed from type T to T&.
90                                Expression * expr = tupleExpr->get_tuple();
[141b786]91                                tupleExpr->set_tuple( nullptr );
92                                TupleIndexExpr * ret = new TupleIndexExpr( expr, tupleExpr->get_index() );
93                                delete tupleExpr;
94                                return ret;
95                        }
96                };
97        } // namespace
98
[0b5d871]99        Expression * distributeReference( Expression * expr ) {
100                PassVisitor<CastExploder> exploder;
101                expr = expr->acceptMutator( exploder );
102                if ( ! exploder.pass.foundUniqueExpr ) {
103                        // if a UniqueExpr was found, then the cast has already been added inside the UniqueExpr as appropriate
104                        expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
[141b786]105                }
106                return expr;
107        }
[b910d15]108
109namespace {
110
111// Remove one level of reference from a reference type.
112const ast::Type * getReferenceBase( const ast::Type * t ) {
113        if ( const ast::ReferenceType * ref = dynamic_cast< const ast::ReferenceType * >( t ) ) {
114                return ref->base;
115        } else {
116                assertf( false, "getReferenceBase for non-ref: %s", toString( t ).c_str() );
117                return nullptr;
118        }
119}
120
121struct CastExploderCore {
122        bool castAdded = false;
123        bool foundUniqueExpr = false;
124        const ast::Expr * applyCast( const ast::Expr * expr, bool first = true ) {
125                // On tuple push the cast down.
126                if ( const ast::TupleExpr * tupleExpr = dynamic_cast< const ast::TupleExpr * >( expr ) ) {
127                        foundUniqueExpr = true;
128                        std::vector< ast::ptr< ast::Expr > > exprs;
129                        for ( const ast::Expr * expr : tupleExpr->exprs ) {
130                                exprs.emplace_back( applyCast( expr, false ) );
131                        }
132                        if ( first ) {
133                                castAdded = true;
[b8524ca]134                                const ast::Expr * tuple = new ast::TupleExpr{
135                                        tupleExpr->location, std::move( exprs ) };
136                                return new ast::CastExpr{ tuple, new ast::ReferenceType{ tuple->result } };
[b910d15]137                        } else {
138                                return new ast::TupleExpr( tupleExpr->location, std::move( exprs ) );
139                        }
140                }
141                if ( dynamic_cast< const ast::ReferenceType * >( expr->result.get() ) ) {
142                        return expr;
143                } else {
144                        castAdded = true;
[b8524ca]145                        return new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
[b910d15]146                }
147        }
148
[c408483]149        const ast::Expr * postvisit( const ast::UniqueExpr * node ) {
[b910d15]150                // move cast into unique expr so that the unique expr has type T& rather than
151                // type T. In particular, this transformation helps with generating the
152                // correct code for reference-cast member tuple expressions, since the result
153                // should now be a tuple of references rather than a reference to a tuple.
154                // Still, this code is a bit awkward, and could use some improvement.
155                const ast::UniqueExpr * newNode = new ast::UniqueExpr( node->location,
156                                applyCast( node->expr ), node->id );
157                if ( castAdded ) {
158                        // if a cast was added by applyCast, then unique expr now has one more layer of reference
159                        // than it had coming into this function. To ensure types still match correctly, need to cast
160                        //  to reference base so that outer expressions are still correct.
161                        castAdded = false;
162                        const ast::Type * newType = getReferenceBase( newNode->result );
[74807be]163                        return new ast::CastExpr{ newNode->location, newNode, newType };
[b910d15]164                }
165                return newNode;
166        }
167
[c408483]168        const ast::Expr * postvisit( const ast::TupleIndexExpr * tupleExpr ) {
[b910d15]169                // tuple index expr needs to be rebuilt to ensure that the type of the
170                // field is consistent with the type of the tuple expr, since the field
171                // may have changed from type T to T&.
172                return new ast::TupleIndexExpr( tupleExpr->location, tupleExpr->tuple, tupleExpr->index );
173        }
174};
175
176} // namespace
177
178const ast::Expr * distributeReference( const ast::Expr * expr ) {
179        ast::Pass<CastExploderCore> exploder;
180        expr = expr->accept( exploder );
[7ff3e522]181        if ( ! exploder.core.foundUniqueExpr ) {
[b8524ca]182                expr = new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
[b910d15]183        }
184        return expr;
185}
186
[141b786]187} // namespace Tuples
188
189// Local Variables: //
190// tab-width: 4 //
191// mode: c++ //
192// compile-command: "make install" //
193// End: //
Note: See TracBrowser for help on using the repository browser.