source: src/Validate/ForallPointerDecay.cpp@ 51b8582

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

So it was a bug in old code that seemed to be cancelling itself out but the new version does not have it. This solution got everything but one test (a polymorphic function calling itself) working.

  • Property mode set to 100644
File size: 9.2 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 auto mutType = ast::mutate( mut->type.get() );
181 // *
182 mutType->params.clear();
183 for ( auto & param : mut->params ) {
184 mutType->params.emplace_back( param->get_type() );
185 }
186 mutType->returns.clear();
187 for ( auto & ret : mut->returns ) {
188 mutType->returns.emplace_back( ret->get_type() );
189 }
190 mutType->forall.clear();
191 for ( auto & type_param : mut->type_params ) {
192 mutType->forall.emplace_back(
193 new ast::TypeInstType( type_param->name, type_param ) );
194 }
195 // * /
196 mutType->assertions.clear();
197 for ( auto & assertion : mut->assertions ) {
198 mutType->assertions.emplace_back(
199 new ast::VariableExpr( mut->location, assertion ) );
200 }
201 mut->type = mutType;
202 return mut;
203 }
204
205 const ast::StructDecl * previsit( const ast::StructDecl * decl ) {
206 if ( decl->params.empty() ) {
207 return decl;
208 }
209 return ast::mutate_field( decl, &ast::StructDecl::params,
210 expandTypeDecls( decl->params ) );
211 }
212
213 const ast::UnionDecl * previsit( const ast::UnionDecl * decl ) {
214 if ( decl->params.empty() ) {
215 return decl;
216 }
217 return ast::mutate_field( decl, &ast::UnionDecl::params,
218 expandTypeDecls( decl->params ) );
219 }
220};
221
222std::vector<ast::ptr<ast::DeclWithType>> fixAssertionList(
223 const ast::ParseNode * node,
224 const std::vector<ast::ptr<ast::DeclWithType>> & assertions ) {
225 std::vector<ast::ptr<ast::DeclWithType>> ret;
226 for ( const auto & assn : assertions ) {
227 bool isVoid = false;
228 ret.push_back( SymTab::fixFunction( assn, isVoid ) );
229 if ( isVoid ) {
230 SemanticError( node->location, node,
231 "invalid type void in assertion of function " );
232 }
233 }
234 return ret;
235}
236
237std::vector<ast::ptr<ast::TypeDecl>> fixTypeDeclList(
238 const ast::ParseNode * node,
239 const std::vector<ast::ptr<ast::TypeDecl>> & type_params ) {
240 std::vector<ast::ptr<ast::TypeDecl>> ret;
241 ret.reserve( type_params.size() );
242 for ( const ast::TypeDecl * type_param : type_params ) {
243 auto mutParam = ast::mutate( type_param );
244 mutParam->assertions = fixAssertionList( node, mutParam->assertions );
245 ret.push_back( mutParam );
246 }
247 return ret;
248}
249
250struct AssertionFunctionFixer final {
251 const ast::FunctionDecl * previsit( const ast::FunctionDecl * decl ) {
252 if ( decl->assertions.empty() ) {
253 return decl;
254 }
255 return ast::mutate_field( decl, &ast::FunctionDecl::assertions,
256 fixAssertionList( decl, decl->assertions ) );
257 }
258
259 const ast::StructDecl * previsit( const ast::StructDecl * decl ) {
260 if ( decl->params.empty() ) {
261 return decl;
262 }
263 return ast::mutate_field( decl, &ast::StructDecl::params,
264 fixTypeDeclList( decl, decl->params ) );
265 }
266
267 const ast::UnionDecl * previsit( const ast::UnionDecl * decl ) {
268 if ( decl->params.empty() ) {
269 return decl;
270 }
271 return ast::mutate_field( decl, &ast::UnionDecl::params,
272 fixTypeDeclList( decl, decl->params ) );
273 }
274};
275
276struct OberatorChecker final {
277 void previsit( const ast::ObjectDecl * obj ) {
278 if ( CodeGen::isOperator( obj->name ) ) {
279 auto type = obj->type->stripDeclarator();
280 if ( ! dynamic_cast< const ast::FunctionType * >( type ) ) {
281 SemanticError( obj->location,
282 toCString( "operator ", obj->name.c_str(), " is not "
283 "a function or function pointer." ) );
284 }
285 }
286 }
287};
288
289struct UniqueFixCore final {
290 const ast::DeclWithType * postvisit( const ast::DeclWithType * decl ) {
291 if ( decl->uniqueId ) {
292 return decl;
293 } else {
294 auto mut = ast::mutate( decl );
295 mut->fixUniqueId();
296 return mut;
297 }
298 }
299};
300
301} // namespace
302
303void decayForallPointers( ast::TranslationUnit & transUnit ) {
304 ast::Pass<TraitExpander>::run( transUnit );
305 ast::Pass<AssertionFunctionFixer>::run( transUnit );
306 ast::Pass<OberatorChecker>::run( transUnit );
307 ast::Pass<UniqueFixCore>::run( transUnit );
308}
309
310} // namespace Validate
311
312// Local Variables: //
313// tab-width: 4 //
314// mode: c++ //
315// compile-command: "make install" //
316// End: //
Note: See TracBrowser for help on using the repository browser.