source: src/Tuples/Explode.cc@ 11ab0b4a

Last change on this file since 11ab0b4a was bccd70a, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Removed internal code from TypeSubstitution header. It caused a chain of include problems, which have been corrected.

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