source: src/Tuples/TupleAssignment.cc @ 6eb8948

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

make TupleAssignment? generate temporaries, add StmtExpr? for GCC statement expressions, expand tuple assignment expressions, collapse SolvedTupleExpr?, MassAssignExpr?, and MultipleAssignExpr? into TupleAssignExpr?

  • Property mode set to 100644
File size: 9.0 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 "ResolvExpr/AlternativeFinder.h"
17#include "ResolvExpr/Alternative.h"
18#include "ResolvExpr/typeops.h"
19#include "SynTree/Expression.h"
20#include "SynTree/Initializer.h"
21#include "Tuples.h"
22#include "Common/SemanticError.h"
23
24#include <functional>
25#include <algorithm>
26#include <iterator>
27#include <iostream>
28#include <cassert>
29#include <set>
30#include <unordered_set>
31
32namespace Tuples {
33        class TupleAssignSpotter {
34          public:
35                // dispatcher for Tuple (multiple and mass) assignment operations
36                TupleAssignSpotter( ResolvExpr::AlternativeFinder & );
37                void spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities );
38
39          private:
40                void match();
41                // records for assignment generation
42                struct Options {
43                        void print( std::ostream & );
44                        int size() const { return options.size(); }
45                        bool empty() const { return options.empty(); }
46                        typedef std::list< ResolvExpr::AltList >::iterator iterator;
47                        iterator begin() { return options.begin(); }
48                        iterator end() { return options.end(); }
49
50                        std::list< ResolvExpr::AltList > options;
51                };
52
53                struct Matcher {
54                  public:
55                        Matcher( TupleAssignSpotter &spotter, Expression *_lhs, Expression *_rhs );
56                        virtual ~Matcher() {}
57                        virtual void match( std::list< Expression * > &out ) = 0;
58                        std::list< Expression * > lhs, rhs;
59                        TupleAssignSpotter &spotter;
60                        std::list< ObjectDecl * > tmpDecls;
61                };
62
63                struct MassAssignMatcher : public Matcher {
64                  public:
65                        MassAssignMatcher( TupleAssignSpotter &spotter, Expression *lhs, Expression *rhs ) : Matcher( spotter, lhs, rhs ) {
66                                this->rhs.push_back( rhs );
67                        }
68                        virtual void match( std::list< Expression * > &out );
69                };
70
71                struct MultipleAssignMatcher : public Matcher {
72                  public:
73                        MultipleAssignMatcher( TupleAssignSpotter &spot, Expression *lhs, Expression *rhs );
74                        virtual void match( std::list< Expression * > &out );
75                };
76
77                ResolvExpr::AlternativeFinder &currentFinder;
78                // Expression *rhs, *lhs;
79                Matcher *matcher = nullptr;
80                Options options;
81        };
82
83        bool isTupleVar( DeclarationWithType *decl ) {
84                return dynamic_cast< TupleType * >( decl->get_type() );
85        }
86
87        /// true if expr is an expression of tuple type, i.e. a tuple expression, tuple variable, or MRV (multiple-return-value) function
88        bool isTuple( Expression *expr ) {
89                if ( ! expr ) return false;
90
91                // xxx - used to include cast to varExpr and call to isTupleVar, but this doesn't seem like it should be necessary
92                return dynamic_cast<TupleExpr *>(expr) || expr->get_results().size() > 1;
93        }
94
95        bool pointsToTuple( Expression *expr ) {
96                // also check for function returning tuple of reference types
97                if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) {
98                        return isTuple( addr->get_arg() );
99                }
100                return false;
101        }
102
103        bool isTupleExpr( Expression *expr ) {
104                return expr->get_results().size() > 1;
105        }
106
107        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
108                TupleAssignSpotter spotter( currentFinder );
109                spotter.spot( expr, possibilities );
110        }
111
112        TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )
113                : currentFinder(f) {}
114
115        void TupleAssignSpotter::spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
116                if (  NameExpr *assgnop = dynamic_cast< NameExpr * >(expr->get_function()) ) {
117                        if ( assgnop->get_name() == std::string("?=?") ) {
118                                for ( std::list<ResolvExpr::AltList>::iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
119                                        assert( ali->size() == 2 );
120                                        ResolvExpr::Alternative op1 = ali->front(), op2 = ali->back();
121
122                                        MultipleAssignMatcher multiMatcher( *this, op1.expr, op2.expr );
123                                        MassAssignMatcher massMatcher( *this, op1.expr, op2.expr );
124                                        if ( pointsToTuple(op1.expr) ) { // also handles tuple vars
125                                                if ( isTuple( op2.expr ) ) {
126                                                        matcher = &multiMatcher;
127                                                } else {
128                                                        // mass assignment
129                                                        matcher = &massMatcher;
130                                                }
131                                                match();
132                                        } else if ( isTuple( op2.expr ) ) {
133                                                throw SemanticError("Cannot assign a tuple value into a non-tuple lvalue.", expr);
134                                        }
135                                }
136                        }
137                }
138        }
139
140        void TupleAssignSpotter::match() {
141                assert ( matcher != 0 );
142
143                std::list< Expression * > new_assigns;
144                matcher->match( new_assigns );
145
146                if ( new_assigns.empty() ) return;
147                ResolvExpr::AltList current;
148                // now resolve new assignments
149                for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
150                        ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
151                        finder.findWithAdjustment(*i);
152                        // prune expressions that don't coincide with
153                        ResolvExpr::AltList alts = finder.get_alternatives();
154                        assert( alts.size() == 1 );
155                        assert( alts.front().expr != 0 );
156                        current.push_back( alts.front() );
157                }
158
159                // extract expressions from the assignment alternatives to produce a list of assignments that
160                // together form a single alternative
161                std::list< Expression *> solved_assigns;
162                for ( ResolvExpr::Alternative & alt : current ) {
163                        solved_assigns.push_back( alt.expr->clone() );
164                }
165                // xxx - need to do this??
166                // TypeEnvironment compositeEnv;
167                // simpleCombineEnvironments( i->begin(), i->end(), compositeEnv );
168                currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), currentFinder.get_environ(), ResolvExpr::sumCost( current ) ) );
169        }
170
171        TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, Expression *lhs, Expression *rhs ) : spotter(spotter) {
172                // xxx - shouldn't need to be &<tuple-expr>, just &<lvalue-tuple-type>
173                if (AddressExpr *addr = dynamic_cast<AddressExpr *>(lhs) )
174                        if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(addr->get_arg()) )
175                                std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(this->lhs) );
176        }
177
178        TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, Expression *lhs, Expression *rhs ) : Matcher( spotter, lhs, rhs ) {
179
180                if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(rhs) )
181                        std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(this->rhs) );
182        }
183
184        UntypedExpr * createAssgn( ObjectDecl *left, ObjectDecl *right ) {
185                assert( left && right );
186                std::list< Expression * > args;
187                args.push_back( new AddressExpr( new UntypedExpr( new NameExpr("*?"), std::list< Expression * >{ new VariableExpr( left ) } ) ) );
188                args.push_back( new VariableExpr( right ) );
189                return new UntypedExpr( new NameExpr( "?=?" ), args );
190        }
191
192        ObjectDecl * newObject( UniqueName & namer, Expression * expr ) {
193                Type * type;
194                assert( expr->get_results().size() >= 1 );
195                if ( expr->get_results().size() > 1 ) {
196                        TupleType * tt = new TupleType( Type::Qualifiers() );
197                        cloneAll( expr->get_results(), tt->get_types() );
198                        type = tt;
199                } else {
200                        type = expr->get_results().front()->clone();
201                }
202                return new ObjectDecl( namer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, type, new SingleInit( expr->clone() ) );
203        }
204
205        void TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
206                static UniqueName lhsNamer( "__massassign_L" );
207                static UniqueName rhsNamer( "__massassign_R" );
208                assert ( ! lhs.empty() && rhs.size() == 1);
209
210                ObjectDecl * rtmp = newObject( rhsNamer, rhs.front() );
211                for ( Expression * l : lhs ) {
212                        ObjectDecl * ltmp = newObject( lhsNamer, new AddressExpr( l ) );
213                        out.push_back( createAssgn( ltmp, rtmp ) );
214                        tmpDecls.push_back( ltmp );
215                }
216                tmpDecls.push_back( rtmp );
217        }
218
219        void TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
220                static UniqueName lhsNamer( "__multassign_L" );
221                static UniqueName rhsNamer( "__multassign_R" );
222                // xxx - need more complicated matching?
223                if ( lhs.size() == rhs.size() ) {
224                        std::list< ObjectDecl * > ltmp;
225                        std::list< ObjectDecl * > rtmp;
226                        std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), []( Expression * expr ){
227                                return newObject( lhsNamer, new AddressExpr( expr ) );
228                        });
229                        std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), []( Expression * expr ){
230                                return newObject( rhsNamer, expr );
231                        });
232                        zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), createAssgn );
233                        tmpDecls.splice( tmpDecls.end(), ltmp );
234                        tmpDecls.splice( tmpDecls.end(), rtmp );
235                }
236        }
237
238        void TupleAssignSpotter::Options::print( std::ostream &ostr ) {
239                for ( ResolvExpr::AltList & l : options ) {
240                        for ( ResolvExpr::Alternative & alt : l ) {
241                                alt.print( ostr );
242                                ostr << " ";
243                        }
244                        ostr << std::endl;
245                } // for
246        }
247} // namespace Tuples
248
249// Local Variables: //
250// tab-width: 4 //
251// mode: c++ //
252// compile-command: "make install" //
253// End: //
Note: See TracBrowser for help on using the repository browser.