source: src/Tuples/TupleExpansion.cc @ f0121d7

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since f0121d7 was f0121d7, checked in by Rob Schluntz <rschlunt@…>, 6 years ago

refactor genCtorInit, generate ConstructorInit? for UniqueExpr?

  • Property mode set to 100644
File size: 11.1 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// TupleAssignment.cc --
8//
9// Author           : Rodolfo G. Esteves
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Mon May 18 15:02:53 2015
13// Update Count     : 2
14//
15
16#include <iterator>
17#include <iostream>
18#include <cassert>
19#include "Tuples.h"
20#include "GenPoly/DeclMutator.h"
21#include "SynTree/Mutator.h"
22#include "SynTree/Statement.h"
23#include "SynTree/Declaration.h"
24#include "SynTree/Type.h"
25#include "SynTree/Expression.h"
26#include "SynTree/Initializer.h"
27#include "SymTab/Mangler.h"
28#include "Common/ScopedMap.h"
29#include "ResolvExpr/typeops.h"
30#include "InitTweak/GenInit.h"
31
32namespace Tuples {
33        namespace {
34                class MemberTupleExpander : public Mutator {
35                public:
36                        typedef Mutator Parent;
37                        virtual Expression * mutate( UntypedMemberExpr * memberExpr );
38                };
39
40                class UniqueExprExpander : public GenPoly::DeclMutator {
41                public:
42                        typedef GenPoly::DeclMutator Parent;
43                        virtual Expression * mutate( UniqueExpr * unqExpr );
44                        std::map< int, ObjectDecl * > decls; // not vector, because order added may not be increasing order
45                };
46
47                class TupleAssignExpander : public Mutator {
48                public:
49                        typedef Mutator Parent;
50                        virtual Expression * mutate( TupleAssignExpr * tupleExpr );
51                };
52
53                class TupleTypeReplacer : public GenPoly::DeclMutator {
54                  public:
55                        typedef GenPoly::DeclMutator Parent;
56
57                        virtual Type * mutate( TupleType * tupleType );
58
59                        virtual CompoundStmt * mutate( CompoundStmt * stmt ) {
60                                typeMap.beginScope();
61                                stmt = Parent::mutate( stmt );
62                                typeMap.endScope();
63                                return stmt;
64                        }
65                  private:
66                        ScopedMap< std::string, StructDecl * > typeMap;
67                };
68
69                class TupleIndexExpander : public Mutator {
70                public:
71                        typedef Mutator Parent;
72                        virtual Expression * mutate( TupleIndexExpr * tupleExpr );
73                };
74
75                class TupleExprExpander : public Mutator {
76                public:
77                        typedef Mutator Parent;
78                        virtual Expression * mutate( TupleExpr * tupleExpr );
79                };
80        }
81
82        void expandMemberTuples( std::list< Declaration * > & translationUnit ) {
83                MemberTupleExpander expander;
84                mutateAll( translationUnit, expander );
85        }
86
87        void expandUniqueExpr( std::list< Declaration * > & translationUnit ) {
88                UniqueExprExpander unqExpander;
89                unqExpander.mutateDeclarationList( translationUnit );
90        }
91
92        void expandTuples( std::list< Declaration * > & translationUnit ) {
93                TupleAssignExpander assnExpander;
94                mutateAll( translationUnit, assnExpander );
95
96                TupleTypeReplacer replacer;
97                replacer.mutateDeclarationList( translationUnit );
98
99                TupleIndexExpander idxExpander;
100                mutateAll( translationUnit, idxExpander );
101
102                TupleExprExpander exprExpander;
103                mutateAll( translationUnit, exprExpander );
104        }
105
106        namespace {
107                /// given a expression representing the member and an expression representing the aggregate,
108                /// reconstructs a flattened UntypedMemberExpr with the right precedence
109                Expression * reconstructMemberExpr( Expression * member, UniqueExpr * aggr ) {
110                        if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( member ) ) {
111                                // construct a new UntypedMemberExpr with the correct structure , and recursively
112                                // expand that member expression.
113                                MemberTupleExpander expander;
114                                UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member(), new UntypedMemberExpr( memberExpr->get_aggregate(), aggr->clone() ) );
115
116                                memberExpr->set_member(nullptr);
117                                memberExpr->set_aggregate(nullptr);
118                                delete memberExpr;
119                                return newMemberExpr->acceptMutator( expander );
120                        } else {
121                                // not a member expression, so there is nothing to do but attach and return
122                                return new UntypedMemberExpr( member, aggr->clone() );
123                        }
124                }
125        }
126
127        Expression * MemberTupleExpander::mutate( UntypedMemberExpr * memberExpr ) {
128                if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * > ( memberExpr->get_member() ) ) {
129                        UniqueExpr * unqExpr = new UniqueExpr( memberExpr->get_aggregate()->clone() );
130                        for ( Expression *& expr : tupleExpr->get_exprs() ) {
131                                expr = reconstructMemberExpr( expr, unqExpr );
132                        }
133                        delete unqExpr;
134                        return tupleExpr;
135                } else {
136                        // there may be a tuple expr buried in the aggregate
137                        // xxx - this is a memory leak
138                        return new UntypedMemberExpr( memberExpr->get_member()->clone(), memberExpr->get_aggregate()->acceptMutator( *this ) );
139                }
140        }
141
142        Expression * UniqueExprExpander::mutate( UniqueExpr * unqExpr ) {
143                static UniqueName tempNamer( "_unq_expr_" );
144                unqExpr = safe_dynamic_cast< UniqueExpr * > ( Parent::mutate( unqExpr ) );
145                if ( ! decls.count( unqExpr->get_id() ) ) {
146                        // xxx - it's possible (likely?) that expressions can appear in the wrong order because of this. Need to ensure they're placed in the correct location.
147
148                        // xxx - this doesn't work, because it would need to be placed after fixInit, but fixInit doesn't know (and shouldn't have to know) about the existance of UniqueExprs - i.e. it will visit them twice
149                        // need to construct/destruct unique exprs in general - maybe it's not worth it and fixInit should handle UniqueExpr explicitly?
150                        // currently, tmp is being destructed before unqExpr is used, which suggests there should be a separate lifetime for unqExpr from the tmp_ret
151
152                        // if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( unqExpr->get_expr() ) ) {
153                        //      if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( commaExpr->get_arg2() ) ) {
154                        //              // steal existing decl from expr
155                        //              if ( ObjectDecl * decl = dynamic_cast< ObjectDecl * >( varExpr->get_var() ) ) {
156                        //                      decls[unqExpr->get_id()] = decl;
157                        //                      return unqExpr->get_expr()->clone();
158                        //              }
159                        //      }
160                        // }
161
162                        // xxx - attach a resolved ConstructorInit node?
163                        // xxx - is it possible to make the objDecl's type const?
164                        ObjectDecl * objDecl = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, unqExpr->get_result()->clone(), nullptr );
165                        // must be done on two lines because genCtorInit accesses objDecl's fields
166                        objDecl->set_init( InitTweak::genCtorInit( objDecl ) );
167
168                        decls[unqExpr->get_id()] = objDecl;
169                        addDeclaration( objDecl );
170                }
171                return new VariableExpr( decls[unqExpr->get_id()] );
172        }
173
174        Expression * TupleAssignExpander::mutate( TupleAssignExpr * assnExpr ) {
175                // xxx - Parent::mutate?
176                CompoundStmt * compoundStmt = new CompoundStmt( noLabels );
177                std::list< Statement * > & stmts = compoundStmt->get_kids();
178                for ( ObjectDecl * obj : assnExpr->get_tempDecls() ) {
179                        stmts.push_back( new DeclStmt( noLabels, obj ) );
180                }
181                TupleExpr * tupleExpr = new TupleExpr( assnExpr->get_assigns() );
182                assert( tupleExpr->get_result() );
183                stmts.push_back( new ExprStmt( noLabels, tupleExpr ) );
184                assnExpr->get_tempDecls().clear();
185                assnExpr->get_assigns().clear();
186                delete assnExpr;
187                return new StmtExpr( compoundStmt );
188        }
189
190        Type * TupleTypeReplacer::mutate( TupleType * tupleType ) {
191                std::string mangleName = SymTab::Mangler::mangleType( tupleType );
192                TupleType * newType = safe_dynamic_cast< TupleType * > ( Parent::mutate( tupleType ) );
193                if ( ! typeMap.count( mangleName ) ) {
194                        // generate struct type to replace tuple type
195                        StructDecl * decl = new StructDecl( "_tuple_type_" + mangleName );
196                        decl->set_body( true );
197                        int cnt = 0;
198                        for ( Type * t : *newType ) {
199                                decl->get_members().push_back( new ObjectDecl( "field_"+std::to_string(++cnt), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, t->clone(), nullptr ) );
200                        }
201                        typeMap[mangleName] = decl;
202                        addDeclaration( decl );
203                }
204                Type::Qualifiers qualifiers = newType->get_qualifiers();
205                delete newType;
206                return new StructInstType( qualifiers, typeMap[mangleName] );
207        }
208
209        Expression * TupleIndexExpander::mutate( TupleIndexExpr * tupleExpr ) {
210                Expression * tuple = maybeMutate( tupleExpr->get_tuple(), *this );
211                assert( tuple );
212                tupleExpr->set_tuple( nullptr );
213                unsigned int idx = tupleExpr->get_index();
214                delete tupleExpr;
215
216                StructInstType * type = safe_dynamic_cast< StructInstType * >( tuple->get_result() );
217                StructDecl * structDecl = type->get_baseStruct();
218                assert( structDecl->get_members().size() > idx );
219                Declaration * member = *std::next(structDecl->get_members().begin(), idx);
220                return new MemberExpr( safe_dynamic_cast< DeclarationWithType * >( member ), tuple );
221        }
222
223        Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs ) {
224                if ( result->isVoid() ) {
225                        // void result - don't need to produce a value for cascading - just output a chain of comma exprs
226                        assert( ! exprs.empty() );
227                        std::list< Expression * >::const_iterator iter = exprs.begin();
228                        Expression * expr = *iter++;
229                        for ( ; iter != exprs.end(); ++iter ) {
230                                expr = new CommaExpr( expr, *iter );
231                        }
232                        return expr;
233                } else {
234                        // typed tuple expression - produce a compound literal which performs each of the expressions
235                        // as a distinct part of its initializer - the produced compound literal may be used as part of
236                        // another expression
237                        std::list< Initializer * > inits;
238                        for ( Expression * expr : exprs ) {
239                                inits.push_back( new SingleInit( expr ) );
240                        }
241                        return new CompoundLiteralExpr( result, new ListInit( inits ) );
242                }
243        }
244
245        Expression * TupleExprExpander::mutate( TupleExpr * tupleExpr ) {
246                // recursively expand sub-tuple-expressions
247                tupleExpr = safe_dynamic_cast<TupleExpr *>(Parent::mutate(tupleExpr));
248                Type * result = tupleExpr->get_result();
249                std::list< Expression * > exprs = tupleExpr->get_exprs();
250                assert( result );
251
252                // remove data from shell and delete it
253                tupleExpr->set_result( nullptr );
254                tupleExpr->get_exprs().clear();
255                delete tupleExpr;
256
257                return replaceTupleExpr( result, exprs );
258        }
259
260        Type * makeTupleType( const std::list< Expression * > & exprs ) {
261                // produce the TupleType which aggregates the types of the exprs
262                TupleType *tupleType = new TupleType( Type::Qualifiers(true, true, true, true, true, false) );
263                Type::Qualifiers &qualifiers = tupleType->get_qualifiers();
264                for ( Expression * expr : exprs ) {
265                        assert( expr->get_result() );
266                        if ( expr->get_result()->isVoid() ) {
267                                // if the type of any expr is void, the type of the entire tuple is void
268                                delete tupleType;
269                                return new VoidType( Type::Qualifiers() );
270                        }
271                        Type * type = expr->get_result()->clone();
272                        tupleType->get_types().push_back( type );
273                        // the qualifiers on the tuple type are the qualifiers that exist on all component types
274                        qualifiers &= type->get_qualifiers();
275                } // for
276                return tupleType;
277        }
278
279        namespace {
280                /// determines if impurity (read: side-effects) may exist in a piece of code. Currently gives a very crude approximation, wherein any function call expression means the code may be impure
281                class ImpurityDetector : public Visitor {
282                public:
283                        typedef Visitor Parent;
284                        virtual void visit( ApplicationExpr * appExpr ) { maybeImpure = true;   }
285                        virtual void visit( UntypedExpr * untypedExpr ) { maybeImpure = true; }
286                        bool maybeImpure = false;
287                };
288        } // namespace
289
290        bool maybeImpure( Expression * expr ) {
291                ImpurityDetector detector;
292                expr->accept( detector );
293                return detector.maybeImpure;
294        }
295} // namespace Tuples
296
297// Local Variables: //
298// tab-width: 4 //
299// mode: c++ //
300// compile-command: "make install" //
301// End: //
302
Note: See TracBrowser for help on using the repository browser.