source: src/Tuples/TupleExpansionNew.cpp

Last change on this file was b7fd9daf, checked in by Fangren Yu <f37yu@…>, 8 months ago

Merge branch 'new-ast-unique-expr'

  • Property mode set to 100644
File size: 5.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// TupleExpansionNew.cpp --
8//
9// Author           : Henry Xue
10// Created On       : Mon Aug 23 15:36:09 2021
11// Last Modified By : Henry Xue
12// Last Modified On : Mon Aug 23 15:36:09 2021
13// Update Count     : 1
14//
15
16#include "Tuples.h"
17
18namespace Tuples {
19namespace {
20        struct MemberTupleExpander final : public ast::WithShortCircuiting, public ast::WithVisitorRef< MemberTupleExpander > {
21                void previsit( const ast::UntypedMemberExpr * ) { visit_children = false; }
22        const ast::Expr * postvisit( const ast::UntypedMemberExpr * memberExpr );
23        };
24        struct UniqueExprExpander final : public ast::WithDeclsToAdd<> {
25                const ast::Expr * postvisit( const ast::UniqueExpr * unqExpr );
26                std::map< int, ast::ptr<ast::Expr> > decls; // not vector, because order added may not be increasing order
27        };
28} // namespace
29
30void expandMemberTuples( ast::TranslationUnit & translationUnit ) {
31        ast::Pass< MemberTupleExpander >::run( translationUnit );
32}
33
34namespace {
35        namespace {
36                /// given a expression representing the member and an expression representing the aggregate,
37                /// reconstructs a flattened UntypedMemberExpr with the right precedence
38                const ast::Expr * reconstructMemberExpr( const ast::Expr * member, const ast::Expr * aggr, const CodeLocation & loc ) {
39                        if ( auto memberExpr = dynamic_cast< const ast::UntypedMemberExpr * >( member ) ) {
40                                // construct a new UntypedMemberExpr with the correct structure , and recursively
41                                // expand that member expression.
42                                ast::Pass< MemberTupleExpander > expander;
43                                auto inner = new ast::UntypedMemberExpr( loc, memberExpr->aggregate, aggr );
44                                auto newMemberExpr = new ast::UntypedMemberExpr( loc, memberExpr->member, inner );
45                                //delete memberExpr;
46                                return newMemberExpr->accept( expander );
47                        } else {
48                                // not a member expression, so there is nothing to do but attach and return
49                                return new ast::UntypedMemberExpr( loc, member, aggr );
50                        }
51                }
52        }
53
54        const ast::Expr * MemberTupleExpander::postvisit( const ast::UntypedMemberExpr * memberExpr ) {
55                const CodeLocation loc = memberExpr->location;
56        if ( auto tupleExpr = memberExpr->member.as< ast::UntypedTupleExpr >() ) {
57                        auto mutExpr = mutate( tupleExpr );
58                        ast::ptr< ast::Expr > aggr = memberExpr->aggregate->accept( *visitor );
59                        // aggregate expressions which might be impure must be wrapped in unique expressions
60                        if ( Tuples::maybeImpureIgnoreUnique( memberExpr->aggregate ) ) aggr = new ast::UniqueExpr( loc, aggr );
61                        for ( auto & expr : mutExpr->exprs ) {
62                                expr = reconstructMemberExpr( expr, aggr, loc );
63                        }
64                        //delete aggr;
65                        return mutExpr;
66                } else {
67                        // there may be a tuple expr buried in the aggregate
68                        return new ast::UntypedMemberExpr( loc, memberExpr->member, memberExpr->aggregate->accept( *visitor ) );
69                }
70        }
71} // namespace
72
73void expandUniqueExpr( ast::TranslationUnit & translationUnit ) {
74        ast::Pass< UniqueExprExpander >::run( translationUnit );
75}
76
77namespace {
78        const ast::Expr * UniqueExprExpander::postvisit( const ast::UniqueExpr * unqExpr ) {
79                const CodeLocation loc = unqExpr->location;
80                const int id = unqExpr->id;
81
82                // on first time visiting a unique expr with a particular ID, generate the expression that replaces all UniqueExprs with that ID,
83                // and lookup on subsequent hits. This ensures that all unique exprs with the same ID reference the same variable.
84                if ( ! decls.count( id ) ) {
85                        ast::ptr< ast::Expr > assignUnq;
86                        const ast::VariableExpr * var = unqExpr->var;
87                        if ( unqExpr->object ) {
88                                // an object was generated to represent this unique expression -- it should be added to the list of declarations now
89                                declsToAddBefore.push_back( unqExpr->object.as< ast::Decl >() );
90                                // deep copy required due to unresolved issues with UniqueExpr
91                                assignUnq = ast::UntypedExpr::createAssign( loc, var, unqExpr->expr );
92                        } else {
93                                const auto commaExpr = unqExpr->expr.strict_as< ast::CommaExpr >();
94                                assignUnq = commaExpr->arg1;
95                        }
96                        auto finished = new ast::ObjectDecl( loc, toString( "_unq", id, "_finished_" ), new ast::BasicType( ast::BasicType::Kind::Bool ),
97                                new ast::SingleInit( loc, ast::ConstantExpr::from_int( loc, 0 ) ), {}, ast::Linkage::Cforall );
98                        declsToAddBefore.push_back( finished );
99                        // (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N))
100                        // This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code.
101                        auto assignFinished = ast::UntypedExpr::createAssign( loc, new ast::VariableExpr( loc, finished ),
102                                ast::ConstantExpr::from_int( loc, 1 ) );
103                        auto condExpr = new ast::ConditionalExpr( loc, new ast::VariableExpr( loc, finished ), var,
104                                new ast::CommaExpr( loc, new ast::CommaExpr( loc, assignUnq, assignFinished ), var ) );
105                        condExpr->result = var->result;
106                        condExpr->env = unqExpr->env;
107                        decls[id] = condExpr;
108                }
109                //delete unqExpr;
110                return ast::deepCopy(decls[id].get());
111        }
112} // namespace
113} // namespace Tuples
Note: See TracBrowser for help on using the repository browser.