source: src/Validate/HoistStruct.cpp @ 329487c

Last change on this file since 329487c was 0658672, checked in by Andrew Beach <ajbeach@…>, 17 months ago

Improved hoisting. However, I had to change some code because of other errors, so more work will have to be done. Also folded in another invariant for MemberExpr?.

  • Property mode set to 100644
File size: 5.9 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2018 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// HoistStruct.cpp -- Flattens nested type declarations.
8//
9// Author           : Andrew Beach
10// Created On       : Thr Apr 21 10:34:00 2022
11// Last Modified By : Andrew Beach
12// Last Modified On : Thr Apr 21 10:34:00 2022
13// Update Count     : 0
14//
15
16#include "Validate/HoistStruct.hpp"
17
18#include <sstream>
19
20#include "AST/DeclReplacer.hpp"
21#include "AST/Pass.hpp"
22#include "AST/TranslationUnit.hpp"
23#include "AST/Vector.hpp"
24
25namespace Validate {
26
27namespace {
28
29bool shouldHoist( ast::Decl const * decl ) {
30        return dynamic_cast< ast::StructDecl const * >( decl )
31                || dynamic_cast< ast::UnionDecl const * >( decl )
32                || dynamic_cast< ast::StaticAssertDecl const * >( decl );
33}
34
35/* This pass also does some renaming and internal field alteration, but the
36 * complex part is the actual hoisting. Hoisted declarations should always
37 * appear before the declaration they are hoisted out of and if two types are
38 * nested in the same declaration their order should not change.
39 */
40struct HoistStructCore final :
41                public ast::WithDeclsToAdd<>, public ast::WithGuards {
42        ast::StructDecl const * previsit( ast::StructDecl const * decl );
43        ast::StructDecl const * postvisit( ast::StructDecl const * decl );
44        ast::UnionDecl const * previsit( ast::UnionDecl const * decl );
45        ast::UnionDecl const * postvisit( ast::UnionDecl const * decl );
46        ast::StructInstType const * previsit( ast::StructInstType const * type );
47        ast::UnionInstType const * previsit( ast::UnionInstType const * type );
48        ast::EnumInstType const * previsit( ast::EnumInstType const * type );
49
50private:
51        template<typename AggrDecl>
52        AggrDecl const * preAggregate( AggrDecl const * );
53        template<typename AggrDecl>
54        AggrDecl const * postAggregate( AggrDecl const * );
55        template<typename InstType>
56        InstType const * preCollectionInstType( InstType const * type );
57
58        ast::AggregateDecl const * parent = nullptr;
59};
60
61void qualifiedName( ast::AggregateDecl const * decl, std::ostringstream & ss ) {
62        if ( decl->parent ) {
63                qualifiedName( decl->parent, ss );
64        }
65        ss << "__" << decl->name;
66}
67
68std::string qualifiedName( ast::AggregateDecl const * decl ) {
69        std::ostringstream ss;
70        qualifiedName( decl, ss );
71        return ss.str();
72}
73
74void extendParams( ast::vector<ast::TypeDecl> & dstParams,
75                ast::vector<ast::TypeDecl> const & srcParams ) {
76        if ( srcParams.empty() ) return;
77
78        ast::DeclReplacer::TypeMap newToOld;
79        ast::vector<ast::TypeDecl> params;
80        for ( ast::ptr<ast::TypeDecl> const & srcParam : srcParams ) {
81                ast::TypeDecl * dstParam = ast::deepCopy( srcParam.get() );
82                dstParam->init = nullptr;
83                newToOld.emplace( srcParam, dstParam );
84                for ( auto assertion : dstParam->assertions ) {
85                        assertion = ast::DeclReplacer::replace( assertion, newToOld );
86                }
87                params.emplace_back( dstParam );
88        }
89        spliceBegin( dstParams, params );
90}
91
92template<typename AggrDecl>
93AggrDecl const * HoistStructCore::preAggregate( AggrDecl const * decl ) {
94        if ( parent ) {
95                auto mut = ast::mutate( decl );
96                mut->parent = parent;
97                mut->name = qualifiedName( mut );
98                extendParams( mut->params, parent->params );
99                decl = mut;
100        }
101        GuardValue( parent ) = decl;
102        return decl;
103}
104
105template<typename AggrDecl>
106AggrDecl const * HoistStructCore::postAggregate( AggrDecl const * decl ) {
107        auto mut = ast::mutate( decl );
108        for ( auto it = mut->members.begin() ; it != mut->members.end() ; ) {
109                if ( shouldHoist( *it ) ) {
110                        // This is the place where the actual hoisting happens.
111                        declsToAddBefore.push_back( it->get() );
112                        it = mut->members.erase( it );
113                } else {
114                        ++it;
115                }
116        }
117        return mut;
118}
119
120ast::StructDecl const * HoistStructCore::previsit( ast::StructDecl const * decl ) {
121        return preAggregate( decl );
122}
123
124ast::StructDecl const * HoistStructCore::postvisit( ast::StructDecl const * decl ) {
125        return postAggregate( decl );
126}
127
128ast::UnionDecl const * HoistStructCore::previsit( ast::UnionDecl const * decl ) {
129        return preAggregate( decl );
130}
131
132ast::UnionDecl const * HoistStructCore::postvisit( ast::UnionDecl const * decl ) {
133        return postAggregate( decl );
134}
135
136ast::AggregateDecl const * commonParent(
137                ast::AggregateDecl const * lhs, ast::AggregateDecl const * rhs ) {
138        for ( auto outer = lhs ; outer ; outer = outer->parent ) {
139                for ( auto inner = rhs ; inner ; inner = inner->parent ) {
140                        if ( outer == inner ) {
141                                return outer;
142                        }
143                }
144        }
145        return nullptr;
146}
147
148template<typename InstType>
149InstType const * HoistStructCore::preCollectionInstType( InstType const * type ) {
150    if ( !type->base->parent ) return type;
151    if ( type->base->params.empty() ) return type;
152
153    InstType * mut = ast::mutate( type );
154    ast::AggregateDecl const * parent =
155        commonParent( this->parent, mut->base->parent );
156    assert( parent );
157
158    std::vector<ast::ptr<ast::Expr>> args;
159    for ( const ast::ptr<ast::TypeDecl> & param : parent->params ) {
160        args.emplace_back( new ast::TypeExpr( param->location,
161            new ast::TypeInstType( param )
162        ) );
163    }
164    spliceBegin( mut->params, args );
165    return mut;
166}
167
168template<typename InstType>
169InstType const * preInstType( InstType const * type ) {
170        assert( type->base );
171        auto mut = ast::mutate( type );
172        mut->name = mut->base->name;
173        return mut;
174}
175
176ast::StructInstType const * HoistStructCore::previsit( ast::StructInstType const * type ) {
177        return preInstType( preCollectionInstType( type ) );
178}
179
180ast::UnionInstType const * HoistStructCore::previsit( ast::UnionInstType const * type ) {
181        return preInstType( preCollectionInstType( type ) );
182}
183
184ast::EnumInstType const * HoistStructCore::previsit( ast::EnumInstType const * type ) {
185        return preInstType( type );
186}
187
188} // namespace
189
190void hoistStruct( ast::TranslationUnit & translationUnit ) {
191        ast::Pass<HoistStructCore>::run( translationUnit );
192}
193
194} // namespace Validate
195
196// Local Variables: //
197// tab-width: 4 //
198// mode: c++ //
199// compile-command: "make install" //
200// End: //
Note: See TracBrowser for help on using the repository browser.