source: src/Validate/HoistStruct.cpp@ f5212ca

Last change on this file since f5212ca was 8b4faf6, checked in by JiadaL <j82liang@…>, 21 months ago

Hoist nested enum in Struct

  • 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.