source: src/Validate/HoistStruct.cpp @ fc1a3e2

Last change on this file since fc1a3e2 was fc1a3e2, checked in by Andrew Beach <ajbeach@…>, 6 weeks ago

Style update. Focused on indentation and trailing whitespace.

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