source: src/Validate/HoistStruct.cpp@ 36e6f10

Last change on this file since 36e6f10 was 0658672, checked in by Andrew Beach <ajbeach@…>, 2 years 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.