source: src/Validate/ForallPointerDecay.cpp@ 9490621

ADT ast-experimental enum forall-pointer-decay pthread-emulation qualifiedEnum
Last change on this file since 9490621 was 9490621, checked in by Andrew Beach <ajbeach@…>, 4 years ago

My work in progress implementation of ForallPointerDecay for Fangren.

  • Property mode set to 100644
File size: 9.3 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// ForallPointerDecay.cpp --
8//
9// Author : Andrew Beach
10// Created On : Tue Dec 7 16:15:00 2021
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Feb 11 10:59:00 2022
13// Update Count : 0
14//
15
16#include "ForallPointerDecay.hpp"
17
18#include "AST/Copy.hpp"
19#include "AST/Decl.hpp"
20#include "AST/DeclReplacer.hpp"
21#include "AST/Pass.hpp"
22#include "CodeGen/OperatorTable.h"
23#include "Common/CodeLocation.h"
24#include "SymTab/FixFunction.h"
25
26#include "AST/Print.hpp"
27
28namespace Validate {
29
30namespace {
31
32// Create a function type only using information on the FunctionDecl.
33ast::FunctionType * makeFuncType( const ast::FunctionDecl * decl ) {
34 auto type = new ast::FunctionType( decl->type->isVarArgs );
35 for ( auto & param : decl->params ) {
36 type->params.emplace_back( param->get_type() );
37 }
38 for ( auto & ret : decl->returns ) {
39 type->returns.emplace_back( ret->get_type() );
40 }
41 for ( auto & type_param : decl->type_params ) {
42 type->forall.emplace_back(
43 new ast::TypeInstType( type_param->name, type_param ) );
44 }
45 for ( auto & assertion : decl->assertions ) {
46 type->assertions.emplace_back( new ast::VariableExpr(
47 assertion->location, assertion ) );
48 }
49 return type;
50}
51
52template<typename T>
53void append( std::vector<T> & dst, std::vector<T> & src ) {
54 dst.reserve( dst.size() + src.size() );
55 for ( auto el : src ) {
56 dst.emplace_back( std::move( el ) );
57 }
58 src.clear();
59}
60
61// Component Passes:
62/// Expand assertions from a trait instance,
63/// performing appropriate type variable substitutions.
64struct TraitExpander final {
65 using AssertionList = std::vector<ast::ptr<ast::DeclWithType>>;
66
67 static AssertionList expandTrait( const ast::TraitInstType * inst ) {
68 assertf( inst->base, "Trait instance not linked to base trait: %s",
69 toCString( inst ) );
70 AssertionList assertions;
71 // Substitute trait decl parameters for instance parameters.
72 ast::TypeSubstitution sub(
73 inst->base->params.begin(),
74 inst->base->params.end(),
75 inst->params.begin()
76 );
77 for ( const ast::ptr<ast::Decl> & decl : inst->base->members ) {
78 ast::ptr<ast::DeclWithType> copy =
79 ast::deepCopy( decl.strict_as<ast::DeclWithType>() );
80
81 int count = sub.apply( copy );
82 (void)count;
83
84 if ( auto func = copy.as<ast::FunctionDecl>() ) {
85 auto mut = ast::mutate( func );
86 mut->type = makeFuncType( func );
87 copy = mut;
88 }
89 assertions.push_back( copy );
90 }
91 return assertions;
92 }
93
94 static AssertionList expandAssertions( const AssertionList & old ) {
95 AssertionList assertions;
96 for ( const ast::ptr<ast::DeclWithType> & decl : old ) {
97 if ( auto traitInst = dynamic_cast<const ast::TraitInstType *>(
98 decl->get_type() ) ) {
99 auto moreAsserts = expandTrait( traitInst );
100 append( assertions, moreAsserts );
101 } else {
102 assertions.push_back( decl );
103 }
104 }
105 return assertions;
106 }
107
108 using TypeDeclVec = std::vector<ast::ptr<ast::TypeDecl>>;
109
110 static TypeDeclVec expandTypeDecls( const TypeDeclVec & old ) {
111 TypeDeclVec typeDecls;
112 for ( const ast::TypeDecl * typeDecl : old ) {
113 typeDecls.push_back( ast::mutate_field( typeDecl,
114 &ast::TypeDecl::assertions,
115 expandAssertions( typeDecl->assertions ) ) );
116 }
117 return typeDecls;
118 }
119
120 static AssertionList expandTrait_DR(
121 const TypeDeclVec & typeDecls, const ast::TraitInstType * inst ) {
122 assertf( inst->base, "Trait instance not linked to base trait: %s",
123 toCString( inst ) );
124 AssertionList assertions;
125 assertf( inst->params.size() == inst->base->params.size(),
126 "Trait instance has incorrect number of params: %s",
127 toCString( inst ) );
128 // Replace the TypeDecls that used to point to the trait.
129 ast::DeclReplacer::TypeMap typeMap;
130 for ( size_t i = 0 ; i < inst->params.size() ; ++i ) {
131 typeMap[ inst->base->params[i].get() ] = typeDecls[i].get();
132 }
133 for ( const ast::ptr<ast::Decl> & decl : inst->base->members ) {
134 auto copy = strict_dynamic_cast<const ast::DeclWithType *>(
135 ast::DeclReplacer::replace(
136 ast::deepCopy( decl.get() ), typeMap ) );
137 // TODO: Does DeclReplacer make this redundent?
138 if ( auto func = dynamic_cast<const ast::FunctionDecl *>(copy) ) {
139 auto mut = ast::mutate( func );
140 mut->type = makeFuncType( func );
141 copy = mut;
142 }
143 assertions.push_back( copy );
144 }
145 return assertions;
146 }
147
148 static AssertionList expandAssertions_DR(
149 const TypeDeclVec & typeDecls, const AssertionList & assertions ) {
150 AssertionList newAsserts;
151 for ( const ast::ptr<ast::DeclWithType> & assert : assertions ) {
152 if ( auto traitInst = dynamic_cast<const ast::TraitInstType *>(
153 assert->get_type() ) ) {
154 auto moreAsserts = expandTrait_DR( typeDecls, traitInst );
155 append( newAsserts, moreAsserts );
156 } else {
157 newAsserts.push_back( assert );
158 }
159 }
160 return newAsserts;
161 }
162
163 // They had better all be unique for this to work.
164 static TypeDeclVec expandTypeDecls_DR( const TypeDeclVec & old ) {
165 TypeDeclVec typeDecls;
166 for ( const ast::TypeDecl * typeDecl : old ) {
167 typeDecls.push_back( ast::mutate_field( typeDecl,
168 &ast::TypeDecl::assertions,
169 expandAssertions_DR( old, typeDecl->assertions ) ) );
170 }
171 return typeDecls;
172 }
173
174 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * decl ) {
175 if ( decl->assertions.empty() ) {
176 return decl;
177 }
178 auto mut = ast::mutate( decl );
179 //mut->assertions = expandAssertions( decl->assertions );
180 mut->assertions = expandAssertions_DR( decl->type_params, decl->assertions );
181 auto mutType = ast::mutate( mut->type.get() );
182 // *
183 mutType->params.clear();
184 for ( auto & param : mut->params ) {
185 mutType->params.emplace_back( param->get_type() );
186 }
187 mutType->returns.clear();
188 for ( auto & ret : mut->returns ) {
189 mutType->returns.emplace_back( ret->get_type() );
190 }
191 mutType->forall.clear();
192 for ( auto & type_param : mut->type_params ) {
193 mutType->forall.emplace_back(
194 new ast::TypeInstType( type_param->name, type_param ) );
195 }
196 // * /
197 mutType->assertions.clear();
198 for ( auto & assertion : mut->assertions ) {
199 mutType->assertions.emplace_back(
200 new ast::VariableExpr( mut->location, assertion ) );
201 }
202 mut->type = mutType;
203 return mut;
204 }
205
206 const ast::StructDecl * previsit( const ast::StructDecl * decl ) {
207 if ( decl->params.empty() ) {
208 return decl;
209 }
210 return ast::mutate_field( decl, &ast::StructDecl::params,
211 //expandTypeDecls( decl->params ) );
212 expandTypeDecls_DR( decl->params ) );
213 }
214
215 const ast::UnionDecl * previsit( const ast::UnionDecl * decl ) {
216 if ( decl->params.empty() ) {
217 return decl;
218 }
219 return ast::mutate_field( decl, &ast::UnionDecl::params,
220 //expandTypeDecls( decl->params ) );
221 expandTypeDecls_DR( decl->params ) );
222 }
223};
224
225std::vector<ast::ptr<ast::DeclWithType>> fixAssertionList(
226 const ast::ParseNode * node,
227 const std::vector<ast::ptr<ast::DeclWithType>> & assertions ) {
228 std::vector<ast::ptr<ast::DeclWithType>> ret;
229 for ( const auto & assn : assertions ) {
230 bool isVoid = false;
231 ret.push_back( SymTab::fixFunction( assn, isVoid ) );
232 if ( isVoid ) {
233 SemanticError( node->location, node,
234 "invalid type void in assertion of function " );
235 }
236 }
237 return ret;
238}
239
240std::vector<ast::ptr<ast::TypeDecl>> fixTypeDeclList(
241 const ast::ParseNode * node,
242 const std::vector<ast::ptr<ast::TypeDecl>> & type_params ) {
243 std::vector<ast::ptr<ast::TypeDecl>> ret;
244 ret.reserve( type_params.size() );
245 for ( const ast::TypeDecl * type_param : type_params ) {
246 auto mutParam = ast::mutate( type_param );
247 mutParam->assertions = fixAssertionList( node, mutParam->assertions );
248 ret.push_back( mutParam );
249 }
250 return ret;
251}
252
253struct AssertionFunctionFixer final {
254 const ast::FunctionDecl * previsit( const ast::FunctionDecl * decl ) {
255 if ( decl->assertions.empty() ) {
256 return decl;
257 }
258 return ast::mutate_field( decl, &ast::FunctionDecl::assertions,
259 fixAssertionList( decl, decl->assertions ) );
260 }
261
262 const ast::StructDecl * previsit( const ast::StructDecl * decl ) {
263 if ( decl->params.empty() ) {
264 return decl;
265 }
266 return ast::mutate_field( decl, &ast::StructDecl::params,
267 fixTypeDeclList( decl, decl->params ) );
268 }
269
270 const ast::UnionDecl * previsit( const ast::UnionDecl * decl ) {
271 if ( decl->params.empty() ) {
272 return decl;
273 }
274 return ast::mutate_field( decl, &ast::UnionDecl::params,
275 fixTypeDeclList( decl, decl->params ) );
276 }
277};
278
279struct OberatorChecker final {
280 void previsit( const ast::ObjectDecl * obj ) {
281 if ( CodeGen::isOperator( obj->name ) ) {
282 auto type = obj->type->stripDeclarator();
283 if ( ! dynamic_cast< const ast::FunctionType * >( type ) ) {
284 SemanticError( obj->location,
285 toCString( "operator ", obj->name.c_str(), " is not "
286 "a function or function pointer." ) );
287 }
288 }
289 }
290};
291
292struct UniqueFixCore final {
293 const ast::DeclWithType * postvisit( const ast::DeclWithType * decl ) {
294 if ( decl->uniqueId ) {
295 return decl;
296 } else {
297 auto mut = ast::mutate( decl );
298 mut->fixUniqueId();
299 return mut;
300 }
301 }
302};
303
304} // namespace
305
306void decayForallPointers( ast::TranslationUnit & transUnit ) {
307 ast::Pass<TraitExpander>::run( transUnit );
308 ast::Pass<AssertionFunctionFixer>::run( transUnit );
309 ast::Pass<OberatorChecker>::run( transUnit );
310 ast::Pass<UniqueFixCore>::run( transUnit );
311}
312
313} // namespace Validate
314
315// Local Variables: //
316// tab-width: 4 //
317// mode: c++ //
318// compile-command: "make install" //
319// End: //
Note: See TracBrowser for help on using the repository browser.