source: src/Tuples/TupleAssignment.cc@ fd782b2

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new stuck-waitfor-destruct with_gc
Last change on this file since fd782b2 was 6eb8948, checked in by Rob Schluntz <rschlunt@…>, 9 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
RevLine 
[51587aa]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//
[5af62f1]7// TupleAssignment.cc --
[51587aa]8//
[843054c2]9// Author : Rodolfo G. Esteves
[51587aa]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
[51b73452]16#include "ResolvExpr/AlternativeFinder.h"
17#include "ResolvExpr/Alternative.h"
18#include "ResolvExpr/typeops.h"
19#include "SynTree/Expression.h"
[6eb8948]20#include "SynTree/Initializer.h"
21#include "Tuples.h"
[d3b7937]22#include "Common/SemanticError.h"
[51b73452]23
24#include <functional>
25#include <algorithm>
26#include <iterator>
27#include <iostream>
28#include <cassert>
29#include <set>
[5af62f1]30#include <unordered_set>
[51b73452]31
32namespace Tuples {
[5af62f1]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
[6eb8948]53 struct Matcher {
[5af62f1]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;
[6eb8948]60 std::list< ObjectDecl * > tmpDecls;
[5af62f1]61 };
62
[6eb8948]63 struct MassAssignMatcher : public Matcher {
[5af62f1]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
[6eb8948]71 struct MultipleAssignMatcher : public Matcher {
[5af62f1]72 public:
73 MultipleAssignMatcher( TupleAssignSpotter &spot, Expression *lhs, Expression *rhs );
74 virtual void match( std::list< Expression * > &out );
75 };
76
77 ResolvExpr::AlternativeFinder &currentFinder;
[6eb8948]78 // Expression *rhs, *lhs;
[5af62f1]79 Matcher *matcher = nullptr;
80 Options options;
81 };
82
83 bool isTupleVar( DeclarationWithType *decl ) {
84 return dynamic_cast< TupleType * >( decl->get_type() );
[51587aa]85 }
86
[5af62f1]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 ) {
[51587aa]89 if ( ! expr ) return false;
90
[5af62f1]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;
[51587aa]93 }
94
[5af62f1]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() );
[51587aa]99 }
100 return false;
101 }
102
[5af62f1]103 bool isTupleExpr( Expression *expr ) {
104 return expr->get_results().size() > 1;
[51587aa]105 }
106
[5af62f1]107 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
108 TupleAssignSpotter spotter( currentFinder );
109 spotter.spot( expr, possibilities );
110 }
[51587aa]111
[5af62f1]112 TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )
113 : currentFinder(f) {}
[51587aa]114
[5af62f1]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("?=?") ) {
[51587aa]118 for ( std::list<ResolvExpr::AltList>::iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
119 assert( ali->size() == 2 );
[5af62f1]120 ResolvExpr::Alternative op1 = ali->front(), op2 = ali->back();
[51587aa]121
[5af62f1]122 MultipleAssignMatcher multiMatcher( *this, op1.expr, op2.expr );
123 MassAssignMatcher massMatcher( *this, op1.expr, op2.expr );
[51587aa]124 if ( pointsToTuple(op1.expr) ) { // also handles tuple vars
[5af62f1]125 if ( isTuple( op2.expr ) ) {
126 matcher = &multiMatcher;
127 } else {
[51587aa]128 // mass assignment
[5af62f1]129 matcher = &massMatcher;
[51587aa]130 }
[5af62f1]131 match();
132 } else if ( isTuple( op2.expr ) ) {
133 throw SemanticError("Cannot assign a tuple value into a non-tuple lvalue.", expr);
[51587aa]134 }
135 }
136 }
137 }
138 }
139
[5af62f1]140 void TupleAssignSpotter::match() {
141 assert ( matcher != 0 );
[51587aa]142
[5af62f1]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 );
[908cc83]156 current.push_back( alts.front() );
[5af62f1]157 }
158
[6eb8948]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 ) ) );
[51587aa]169 }
170
[5af62f1]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) );
[51587aa]176 }
177
[5af62f1]178 TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, Expression *lhs, Expression *rhs ) : Matcher( spotter, lhs, rhs ) {
[51587aa]179
[5af62f1]180 if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(rhs) )
181 std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(this->rhs) );
[51587aa]182 }
183
[6eb8948]184 UntypedExpr * createAssgn( ObjectDecl *left, ObjectDecl *right ) {
[5af62f1]185 assert( left && right );
186 std::list< Expression * > args;
[6eb8948]187 args.push_back( new AddressExpr( new UntypedExpr( new NameExpr("*?"), std::list< Expression * >{ new VariableExpr( left ) } ) ) );
188 args.push_back( new VariableExpr( right ) );
[5af62f1]189 return new UntypedExpr( new NameExpr( "?=?" ), args );
[51587aa]190 }
191
[6eb8948]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
[5af62f1]205 void TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
[6eb8948]206 static UniqueName lhsNamer( "__massassign_L" );
207 static UniqueName rhsNamer( "__massassign_R" );
[5af62f1]208 assert ( ! lhs.empty() && rhs.size() == 1);
[51587aa]209
[6eb8948]210 ObjectDecl * rtmp = newObject( rhsNamer, rhs.front() );
[5af62f1]211 for ( Expression * l : lhs ) {
[6eb8948]212 ObjectDecl * ltmp = newObject( lhsNamer, new AddressExpr( l ) );
213 out.push_back( createAssgn( ltmp, rtmp ) );
214 tmpDecls.push_back( ltmp );
[5af62f1]215 }
[6eb8948]216 tmpDecls.push_back( rtmp );
[51b73452]217 }
218
[5af62f1]219 void TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
[6eb8948]220 static UniqueName lhsNamer( "__multassign_L" );
221 static UniqueName rhsNamer( "__multassign_R" );
[5af62f1]222 // xxx - need more complicated matching?
[51587aa]223 if ( lhs.size() == rhs.size() ) {
[6eb8948]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 );
[5af62f1]235 }
[51587aa]236 }
237
238 void TupleAssignSpotter::Options::print( std::ostream &ostr ) {
[5af62f1]239 for ( ResolvExpr::AltList & l : options ) {
240 for ( ResolvExpr::Alternative & alt : l ) {
241 alt.print( ostr );
242 ostr << " ";
243 }
[51587aa]244 ostr << std::endl;
245 } // for
246 }
[51b73452]247} // namespace Tuples
[51587aa]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.