source: src/Tuples/TupleExpansion.cc @ 77971f6

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 77971f6 was 77971f6, checked in by Rob Schluntz <rschlunt@…>, 6 years ago

resolve ctor/dtors for UniqueExprs?

  • Property mode set to 100644
File size: 10.8 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                unqExpr = safe_dynamic_cast< UniqueExpr * > ( Parent::mutate( unqExpr ) );
144                if ( ! decls.count( unqExpr->get_id() ) ) {
145                        // 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.
146
147                        // 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
148                        // need to construct/destruct unique exprs in general - maybe it's not worth it and fixInit should handle UniqueExpr explicitly?
149                        // currently, tmp is being destructed before unqExpr is used, which suggests there should be a separate lifetime for unqExpr from the tmp_ret
150
151                        // if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( unqExpr->get_expr() ) ) {
152                        //      if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( commaExpr->get_arg2() ) ) {
153                        //              // steal existing decl from expr
154                        //              if ( ObjectDecl * decl = dynamic_cast< ObjectDecl * >( varExpr->get_var() ) ) {
155                        //                      decls[unqExpr->get_id()] = decl;
156                        //                      return unqExpr->get_expr()->clone();
157                        //              }
158                        //      }
159                        // }
160
161                        ObjectDecl * objDecl = unqExpr->get_object();
162                        unqExpr->set_object( nullptr );
163                        decls[unqExpr->get_id()] = objDecl;
164                        addDeclaration( objDecl );
165                }
166                return new VariableExpr( decls[unqExpr->get_id()] );
167        }
168
169        Expression * TupleAssignExpander::mutate( TupleAssignExpr * assnExpr ) {
170                // xxx - Parent::mutate?
171                CompoundStmt * compoundStmt = new CompoundStmt( noLabels );
172                std::list< Statement * > & stmts = compoundStmt->get_kids();
173                for ( ObjectDecl * obj : assnExpr->get_tempDecls() ) {
174                        stmts.push_back( new DeclStmt( noLabels, obj ) );
175                }
176                TupleExpr * tupleExpr = new TupleExpr( assnExpr->get_assigns() );
177                assert( tupleExpr->get_result() );
178                stmts.push_back( new ExprStmt( noLabels, tupleExpr ) );
179                assnExpr->get_tempDecls().clear();
180                assnExpr->get_assigns().clear();
181                delete assnExpr;
182                return new StmtExpr( compoundStmt );
183        }
184
185        Type * TupleTypeReplacer::mutate( TupleType * tupleType ) {
186                std::string mangleName = SymTab::Mangler::mangleType( tupleType );
187                TupleType * newType = safe_dynamic_cast< TupleType * > ( Parent::mutate( tupleType ) );
188                if ( ! typeMap.count( mangleName ) ) {
189                        // generate struct type to replace tuple type
190                        StructDecl * decl = new StructDecl( "_tuple_type_" + mangleName );
191                        decl->set_body( true );
192                        int cnt = 0;
193                        for ( Type * t : *newType ) {
194                                decl->get_members().push_back( new ObjectDecl( "field_"+std::to_string(++cnt), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, t->clone(), nullptr ) );
195                        }
196                        typeMap[mangleName] = decl;
197                        addDeclaration( decl );
198                }
199                Type::Qualifiers qualifiers = newType->get_qualifiers();
200                delete newType;
201                return new StructInstType( qualifiers, typeMap[mangleName] );
202        }
203
204        Expression * TupleIndexExpander::mutate( TupleIndexExpr * tupleExpr ) {
205                Expression * tuple = maybeMutate( tupleExpr->get_tuple(), *this );
206                assert( tuple );
207                tupleExpr->set_tuple( nullptr );
208                unsigned int idx = tupleExpr->get_index();
209                delete tupleExpr;
210
211                StructInstType * type = safe_dynamic_cast< StructInstType * >( tuple->get_result() );
212                StructDecl * structDecl = type->get_baseStruct();
213                assert( structDecl->get_members().size() > idx );
214                Declaration * member = *std::next(structDecl->get_members().begin(), idx);
215                return new MemberExpr( safe_dynamic_cast< DeclarationWithType * >( member ), tuple );
216        }
217
218        Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs ) {
219                if ( result->isVoid() ) {
220                        // void result - don't need to produce a value for cascading - just output a chain of comma exprs
221                        assert( ! exprs.empty() );
222                        std::list< Expression * >::const_iterator iter = exprs.begin();
223                        Expression * expr = *iter++;
224                        for ( ; iter != exprs.end(); ++iter ) {
225                                expr = new CommaExpr( expr, *iter );
226                        }
227                        return expr;
228                } else {
229                        // typed tuple expression - produce a compound literal which performs each of the expressions
230                        // as a distinct part of its initializer - the produced compound literal may be used as part of
231                        // another expression
232                        std::list< Initializer * > inits;
233                        for ( Expression * expr : exprs ) {
234                                inits.push_back( new SingleInit( expr ) );
235                        }
236                        return new CompoundLiteralExpr( result, new ListInit( inits ) );
237                }
238        }
239
240        Expression * TupleExprExpander::mutate( TupleExpr * tupleExpr ) {
241                // recursively expand sub-tuple-expressions
242                tupleExpr = safe_dynamic_cast<TupleExpr *>(Parent::mutate(tupleExpr));
243                Type * result = tupleExpr->get_result();
244                std::list< Expression * > exprs = tupleExpr->get_exprs();
245                assert( result );
246
247                // remove data from shell and delete it
248                tupleExpr->set_result( nullptr );
249                tupleExpr->get_exprs().clear();
250                delete tupleExpr;
251
252                return replaceTupleExpr( result, exprs );
253        }
254
255        Type * makeTupleType( const std::list< Expression * > & exprs ) {
256                // produce the TupleType which aggregates the types of the exprs
257                TupleType *tupleType = new TupleType( Type::Qualifiers(true, true, true, true, true, false) );
258                Type::Qualifiers &qualifiers = tupleType->get_qualifiers();
259                for ( Expression * expr : exprs ) {
260                        assert( expr->get_result() );
261                        if ( expr->get_result()->isVoid() ) {
262                                // if the type of any expr is void, the type of the entire tuple is void
263                                delete tupleType;
264                                return new VoidType( Type::Qualifiers() );
265                        }
266                        Type * type = expr->get_result()->clone();
267                        tupleType->get_types().push_back( type );
268                        // the qualifiers on the tuple type are the qualifiers that exist on all component types
269                        qualifiers &= type->get_qualifiers();
270                } // for
271                return tupleType;
272        }
273
274        namespace {
275                /// 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
276                class ImpurityDetector : public Visitor {
277                public:
278                        typedef Visitor Parent;
279                        virtual void visit( ApplicationExpr * appExpr ) { maybeImpure = true;   }
280                        virtual void visit( UntypedExpr * untypedExpr ) { maybeImpure = true; }
281                        bool maybeImpure = false;
282                };
283        } // namespace
284
285        bool maybeImpure( Expression * expr ) {
286                ImpurityDetector detector;
287                expr->accept( detector );
288                return detector.maybeImpure;
289        }
290} // namespace Tuples
291
292// Local Variables: //
293// tab-width: 4 //
294// mode: c++ //
295// compile-command: "make install" //
296// End: //
297
Note: See TracBrowser for help on using the repository browser.