source: src/Tuples/TupleExpansionNew.cpp@ 120867e

ADT ast-experimental pthread-emulation qualifiedEnum
Last change on this file since 120867e was b7fd9daf, checked in by Fangren Yu <f37yu@…>, 4 years 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.