source: src/GenPoly/Box.cc@ 6182039

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 6182039 was c10ee66, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

fix nested generic member expressions, fix generic union member expression, silence some generated code warnings

  • Property mode set to 100644
File size: 86.6 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 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// Box.cc --
8//
9// Author : Richard C. Bilson
10// Created On : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Mar 17 09:06:37 2017
13// Update Count : 339
14//
15
16#include <algorithm>
17#include <iterator>
18#include <list>
19#include <map>
20#include <set>
21#include <stack>
22#include <string>
23#include <utility>
24#include <vector>
25#include <cassert>
26
27#include "Box.h"
28#include "DeclMutator.h"
29#include "PolyMutator.h"
30#include "FindFunction.h"
31#include "ScopedSet.h"
32#include "ScrubTyVars.h"
33
34#include "Parser/ParseNode.h"
35
36#include "SynTree/Attribute.h"
37#include "SynTree/Constant.h"
38#include "SynTree/Declaration.h"
39#include "SynTree/Expression.h"
40#include "SynTree/Initializer.h"
41#include "SynTree/Mutator.h"
42#include "SynTree/Statement.h"
43#include "SynTree/Type.h"
44#include "SynTree/TypeSubstitution.h"
45
46#include "ResolvExpr/TypeEnvironment.h"
47#include "ResolvExpr/TypeMap.h"
48#include "ResolvExpr/typeops.h"
49
50#include "SymTab/Indexer.h"
51#include "SymTab/Mangler.h"
52
53#include "Common/ScopedMap.h"
54#include "Common/SemanticError.h"
55#include "Common/UniqueName.h"
56#include "Common/utility.h"
57
58#include "InitTweak/InitTweak.h"
59
60#include <ext/functional> // temporary
61
62namespace GenPoly {
63 namespace {
64 const std::list<Label> noLabels;
65
66 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
67
68 /// Adds layout-generation functions to polymorphic types
69 class LayoutFunctionBuilder final : public DeclMutator {
70 unsigned int functionNesting; // current level of nested functions
71 public:
72 LayoutFunctionBuilder() : functionNesting( 0 ) {}
73
74 using DeclMutator::mutate;
75 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
76 virtual Declaration *mutate( StructDecl *structDecl ) override;
77 virtual Declaration *mutate( UnionDecl *unionDecl ) override;
78 };
79
80 /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
81 class Pass1 final : public PolyMutator {
82 public:
83 Pass1();
84
85 using PolyMutator::mutate;
86 virtual Expression *mutate( ApplicationExpr *appExpr ) override;
87 virtual Expression *mutate( AddressExpr *addrExpr ) override;
88 virtual Expression *mutate( UntypedExpr *expr ) override;
89 virtual DeclarationWithType* mutate( FunctionDecl *functionDecl ) override;
90 virtual TypeDecl *mutate( TypeDecl *typeDecl ) override;
91 virtual Expression *mutate( CommaExpr *commaExpr ) override;
92 virtual Expression *mutate( ConditionalExpr *condExpr ) override;
93 virtual Statement * mutate( ReturnStmt *returnStmt ) override;
94 virtual Type *mutate( PointerType *pointerType ) override;
95 virtual Type * mutate( FunctionType *functionType ) override;
96
97 virtual void doBeginScope() override;
98 virtual void doEndScope() override;
99 private:
100 /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
101 void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
102 /// passes extra type parameters into a polymorphic function application
103 void passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
104 /// wraps a function application with a new temporary for the out-parameter return value
105 Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
106 /// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment
107 void replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params );
108 /// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete).
109 /// If `doClone` is set to false, will not clone interior types
110 Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true );
111 /// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value
112 Expression *addDynRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *polyType, std::list< Expression *>::iterator &arg );
113 Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
114 void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
115 void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
116 void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
117 /// Stores assignment operators from assertion list in local map of assignment operations
118 void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
119 FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
120 /// Replaces intrinsic operator functions with their arithmetic desugaring
121 Expression *handleIntrinsics( ApplicationExpr *appExpr );
122 /// Inserts a new temporary variable into the current scope with an auto-generated name
123 ObjectDecl *makeTemporary( Type *type );
124
125 ScopedMap< std::string, DeclarationWithType* > adapters; ///< Set of adapter functions in the current scope
126
127 std::map< ApplicationExpr *, Expression * > retVals;
128
129 DeclarationWithType *retval;
130 UniqueName tempNamer;
131 };
132
133 /// * Moves polymorphic returns in function types to pointer-type parameters
134 /// * adds type size and assertion parameters to parameter lists
135 class Pass2 final : public PolyMutator {
136 public:
137 template< typename DeclClass >
138 DeclClass *handleDecl( DeclClass *decl, Type *type );
139 template< typename AggDecl >
140 AggDecl * handleAggDecl( AggDecl * aggDecl );
141
142 typedef PolyMutator Parent;
143 using Parent::mutate;
144 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
145 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override;
146 virtual StructDecl *mutate( StructDecl *structDecl ) override;
147 virtual UnionDecl *mutate( UnionDecl *unionDecl ) override;
148 virtual TypeDecl *mutate( TypeDecl *typeDecl ) override;
149 virtual TypedefDecl *mutate( TypedefDecl *typedefDecl ) override;
150 virtual Type *mutate( PointerType *pointerType ) override;
151 virtual Type *mutate( FunctionType *funcType ) override;
152
153 private:
154 void addAdapters( FunctionType *functionType );
155
156 std::map< UniqueId, std::string > adapterName;
157 };
158
159 /// Replaces member and size/align/offsetof expressions on polymorphic generic types with calculated expressions.
160 /// * Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
161 /// * Calculates polymorphic offsetof expressions from offset array
162 /// * Inserts dynamic calculation of polymorphic type layouts where needed
163 class PolyGenericCalculator final : public PolyMutator {
164 public:
165 typedef PolyMutator Parent;
166 using Parent::mutate;
167
168 PolyGenericCalculator();
169
170 template< typename DeclClass >
171 DeclClass *handleDecl( DeclClass *decl, Type *type );
172 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
173 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override;
174 virtual TypedefDecl *mutate( TypedefDecl *objectDecl ) override;
175 virtual TypeDecl *mutate( TypeDecl *objectDecl ) override;
176 virtual Statement *mutate( DeclStmt *declStmt ) override;
177 virtual Type *mutate( PointerType *pointerType ) override;
178 virtual Type *mutate( FunctionType *funcType ) override;
179 virtual Expression *mutate( MemberExpr *memberExpr ) override;
180 virtual Expression *mutate( SizeofExpr *sizeofExpr ) override;
181 virtual Expression *mutate( AlignofExpr *alignofExpr ) override;
182 virtual Expression *mutate( OffsetofExpr *offsetofExpr ) override;
183 virtual Expression *mutate( OffsetPackExpr *offsetPackExpr ) override;
184
185 virtual void doBeginScope() override;
186 virtual void doEndScope() override;
187
188 private:
189 /// Makes a new variable in the current scope with the given name, type & optional initializer
190 ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
191 /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
192 bool findGeneric( Type *ty );
193 /// adds type parameters to the layout call; will generate the appropriate parameters if needed
194 void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
195
196 /// Enters a new scope for type-variables, adding the type variables from ty
197 void beginTypeScope( Type *ty );
198 /// Exits the type-variable scope
199 void endTypeScope();
200
201 ScopedSet< std::string > knownLayouts; ///< Set of generic type layouts known in the current scope, indexed by sizeofName
202 ScopedSet< std::string > knownOffsets; ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
203 UniqueName bufNamer; ///< Namer for VLA buffers
204 };
205
206 /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable
207 class Pass3 final : public PolyMutator {
208 public:
209 template< typename DeclClass >
210 DeclClass *handleDecl( DeclClass *decl, Type *type );
211
212 using PolyMutator::mutate;
213 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
214 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override;
215 virtual TypedefDecl *mutate( TypedefDecl *objectDecl ) override;
216 virtual TypeDecl *mutate( TypeDecl *objectDecl ) override;
217 virtual Type *mutate( PointerType *pointerType ) override;
218 virtual Type *mutate( FunctionType *funcType ) override;
219 private:
220 };
221
222 } // anonymous namespace
223
224 /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
225 template< typename MutatorType >
226 inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) {
227 bool seenIntrinsic = false;
228 SemanticError errors;
229 for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
230 try {
231 if ( *i ) {
232 if ( (*i)->get_linkage() == LinkageSpec::Intrinsic ) {
233 seenIntrinsic = true;
234 } else if ( seenIntrinsic ) {
235 seenIntrinsic = false; // break on this line when debugging for end of prelude
236 }
237
238 *i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) );
239 assert( *i );
240 } // if
241 } catch( SemanticError &e ) {
242 e.set_location( (*i)->location );
243 errors.append( e );
244 } // try
245 } // for
246 if ( ! errors.isEmpty() ) {
247 throw errors;
248 } // if
249 }
250
251 void box( std::list< Declaration *>& translationUnit ) {
252 LayoutFunctionBuilder layoutBuilder;
253 Pass1 pass1;
254 Pass2 pass2;
255 PolyGenericCalculator polyCalculator;
256 Pass3 pass3;
257
258 layoutBuilder.mutateDeclarationList( translationUnit );
259 mutateTranslationUnit/*All*/( translationUnit, pass1 );
260 mutateTranslationUnit/*All*/( translationUnit, pass2 );
261 mutateTranslationUnit/*All*/( translationUnit, polyCalculator );
262 mutateTranslationUnit/*All*/( translationUnit, pass3 );
263 }
264
265 ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
266
267 DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {
268 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
269 ++functionNesting;
270 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
271 --functionNesting;
272 return functionDecl;
273 }
274
275 /// Get a list of type declarations that will affect a layout function
276 std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
277 std::list< TypeDecl * > otypeDecls;
278
279 for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
280 if ( (*decl)->isComplete() ) {
281 otypeDecls.push_back( *decl );
282 }
283 }
284
285 return otypeDecls;
286 }
287
288 /// Adds parameters for otype layout to a function type
289 void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
290 BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
291
292 for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
293 TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );
294 std::string paramName = mangleType( &paramType );
295 layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( paramName ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
296 layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( paramName ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
297 }
298 }
299
300 /// Builds a layout function declaration
301 FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, unsigned int functionNesting, FunctionType *layoutFnType ) {
302 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
303 // because each unit generates copies of the default routines for each aggregate.
304 FunctionDecl *layoutDecl = new FunctionDecl( layoutofName( typeDecl ),
305 functionNesting > 0 ? Type::StorageClasses() : Type::StorageClasses( Type::Static ),
306 LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ),
307 std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) );
308 layoutDecl->fixUniqueId();
309 return layoutDecl;
310 }
311
312 /// Makes a unary operation
313 Expression *makeOp( const std::string &name, Expression *arg ) {
314 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
315 expr->get_args().push_back( arg );
316 return expr;
317 }
318
319 /// Makes a binary operation
320 Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {
321 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
322 expr->get_args().push_back( lhs );
323 expr->get_args().push_back( rhs );
324 return expr;
325 }
326
327 /// Returns the dereference of a local pointer variable
328 Expression *derefVar( ObjectDecl *var ) {
329 return makeOp( "*?", new VariableExpr( var ) );
330 }
331
332 /// makes an if-statement with a single-expression if-block and no then block
333 Statement *makeCond( Expression *cond, Expression *ifPart ) {
334 return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 );
335 }
336
337 /// makes a statement that assigns rhs to lhs if lhs < rhs
338 Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {
339 return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );
340 }
341
342 /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)
343 Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {
344 // check that the lhs is zeroed out to the level of rhs
345 Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );
346 // if not aligned, increment to alignment
347 Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );
348 return makeCond( ifCond, ifExpr );
349 }
350
351 /// adds an expression to a compound statement
352 void addExpr( CompoundStmt *stmts, Expression *expr ) {
353 stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );
354 }
355
356 /// adds a statement to a compound statement
357 void addStmt( CompoundStmt *stmts, Statement *stmt ) {
358 stmts->get_kids().push_back( stmt );
359 }
360
361 Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
362 // do not generate layout function for "empty" tag structs
363 if ( structDecl->get_members().empty() ) return structDecl;
364
365 // get parameters that can change layout, exiting early if none
366 std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
367 if ( otypeParams.empty() ) return structDecl;
368
369 // build layout function signature
370 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
371 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
372 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
373
374 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
375 layoutFnType->get_parameters().push_back( sizeParam );
376 ObjectDecl *alignParam = new ObjectDecl( alignofName( structDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
377 layoutFnType->get_parameters().push_back( alignParam );
378 ObjectDecl *offsetParam = new ObjectDecl( offsetofName( structDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
379 layoutFnType->get_parameters().push_back( offsetParam );
380 addOtypeParams( layoutFnType, otypeParams );
381
382 // build function decl
383 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, functionNesting, layoutFnType );
384
385 // calculate struct layout in function body
386
387 // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size)
388 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) );
389 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
390 unsigned long n_members = 0;
391 bool firstMember = true;
392 for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) {
393 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
394 assert( dwt );
395 Type *memberType = dwt->get_type();
396
397 if ( firstMember ) {
398 firstMember = false;
399 } else {
400 // make sure all members after the first (automatically aligned at 0) are properly padded for alignment
401 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
402 }
403
404 // place current size in the current offset index
405 addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from_ulong( n_members ) ) ),
406 derefVar( sizeParam ) ) );
407 ++n_members;
408
409 // add member size to current size
410 addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
411
412 // take max of member alignment and global alignment
413 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
414 }
415 // make sure the type is end-padded to a multiple of its alignment
416 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
417
418 addDeclarationAfter( layoutDecl );
419 return structDecl;
420 }
421
422 Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
423 // do not generate layout function for "empty" tag unions
424 if ( unionDecl->get_members().empty() ) return unionDecl;
425
426 // get parameters that can change layout, exiting early if none
427 std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
428 if ( otypeParams.empty() ) return unionDecl;
429
430 // build layout function signature
431 FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
432 BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
433 PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
434
435 ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
436 layoutFnType->get_parameters().push_back( sizeParam );
437 ObjectDecl *alignParam = new ObjectDecl( alignofName( unionDecl->get_name() ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
438 layoutFnType->get_parameters().push_back( alignParam );
439 addOtypeParams( layoutFnType, otypeParams );
440
441 // build function decl
442 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, functionNesting, layoutFnType );
443
444 // calculate union layout in function body
445 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
446 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
447 for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {
448 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
449 assert( dwt );
450 Type *memberType = dwt->get_type();
451
452 // take max member size and global size
453 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
454
455 // take max of member alignment and global alignment
456 addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
457 }
458 // make sure the type is end-padded to a multiple of its alignment
459 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
460
461 addDeclarationAfter( layoutDecl );
462 return unionDecl;
463 }
464
465 ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
466
467 namespace {
468 std::string makePolyMonoSuffix( FunctionType * function, const TyVarMap &tyVars ) {
469 std::stringstream name;
470
471 // NOTE: this function previously used isPolyObj, which failed to produce
472 // the correct thing in some situations. It's not clear to me why this wasn't working.
473
474 // if the return type or a parameter type involved polymorphic types, then the adapter will need
475 // to take those polymorphic types as pointers. Therefore, there can be two different functions
476 // with the same mangled name, so we need to further mangle the names.
477 for ( std::list< DeclarationWithType *>::iterator retval = function->get_returnVals().begin(); retval != function->get_returnVals().end(); ++retval ) {
478 if ( isPolyType( (*retval)->get_type(), tyVars ) ) {
479 name << "P";
480 } else {
481 name << "M";
482 }
483 }
484 name << "_";
485 std::list< DeclarationWithType *> &paramList = function->get_parameters();
486 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
487 if ( isPolyType( (*arg)->get_type(), tyVars ) ) {
488 name << "P";
489 } else {
490 name << "M";
491 }
492 } // for
493 return name.str();
494 }
495
496 std::string mangleAdapterName( FunctionType * function, const TyVarMap &tyVars ) {
497 return SymTab::Mangler::mangle( function ) + makePolyMonoSuffix( function, tyVars );
498 }
499
500 std::string makeAdapterName( const std::string &mangleName ) {
501 return "_adapter" + mangleName;
502 }
503
504 Pass1::Pass1() : tempNamer( "_temp" ) {}
505
506 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
507 if ( functionDecl->get_statements() ) { // empty routine body ?
508 doBeginScope();
509 scopeTyVars.beginScope();
510
511 DeclarationWithType *oldRetval = retval;
512
513 // process polymorphic return value
514 retval = nullptr;
515 if ( isDynRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() != LinkageSpec::C ) {
516 retval = functionDecl->get_functionType()->get_returnVals().front();
517
518 // give names to unnamed return values
519 if ( retval->get_name() == "" ) {
520 retval->set_name( "_retparm" );
521 retval->set_linkage( LinkageSpec::C );
522 } // if
523 } // if
524
525 FunctionType *functionType = functionDecl->get_functionType();
526 makeTyVarMap( functionDecl->get_functionType(), scopeTyVars );
527
528 std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
529 std::list< FunctionType *> functions;
530 for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
531 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
532 findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter );
533 } // for
534 } // for
535 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
536 findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter );
537 } // for
538
539 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
540 std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
541 if ( adapters.find( mangleName ) == adapters.end() ) {
542 std::string adapterName = makeAdapterName( mangleName );
543 adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), nullptr ) ) );
544 } // if
545 } // for
546
547 functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );
548
549 scopeTyVars.endScope();
550 retval = oldRetval;
551 doEndScope();
552 } // if
553 return functionDecl;
554 }
555
556 TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) {
557 addToTyVarMap( typeDecl, scopeTyVars );
558 return Mutator::mutate( typeDecl );
559 }
560
561 Expression *Pass1::mutate( CommaExpr *commaExpr ) {
562 // Attempting to find application expressions that were mutated by the copy constructor passes
563 // to use an explicit return variable, so that the variable can be reused as a parameter to the
564 // call rather than creating a new temp variable. Previously this step was an optimization, but
565 // with the introduction of tuples and UniqueExprs, it is necessary to ensure that they use the same variable.
566 // Essentially, looking for pattern: (x=f(...), x)
567 // To compound the issue, the right side can be *x, etc. because of lvalue-returning functions
568 if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) {
569 if ( InitTweak::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
570 assert( assign->get_args().size() == 2 );
571 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) {
572 // first argument is assignable, so it must be an lvalue, so it should be legal to take its address.
573 retVals[appExpr] = assign->get_args().front();
574 }
575 }
576 }
577
578 commaExpr->set_arg1( maybeMutate( commaExpr->get_arg1(), *this ) );
579 commaExpr->set_arg2( maybeMutate( commaExpr->get_arg2(), *this ) );
580 return commaExpr;
581 }
582
583 Expression *Pass1::mutate( ConditionalExpr *condExpr ) {
584 condExpr->set_arg1( maybeMutate( condExpr->get_arg1(), *this ) );
585 condExpr->set_arg2( maybeMutate( condExpr->get_arg2(), *this ) );
586 condExpr->set_arg3( maybeMutate( condExpr->get_arg3(), *this ) );
587 return condExpr;
588
589 }
590
591 void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
592 Type *polyType = isPolyType( parmType, exprTyVars );
593 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
594 std::string typeName = mangleType( polyType );
595 if ( seenTypes.count( typeName ) ) return;
596
597 arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
598 arg++;
599 arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
600 arg++;
601 if ( dynamic_cast< StructInstType* >( polyType ) ) {
602 if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
603 // zero-length arrays are forbidden by C, so don't pass offset for empty struct
604 if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) {
605 arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType->clone() ) );
606 arg++;
607 }
608 } else {
609 throw SemanticError( "Cannot pass non-struct type for generic struct" );
610 }
611 }
612
613 seenTypes.insert( typeName );
614 }
615 }
616
617 void Pass1::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
618 // pass size/align for type variables
619 for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
620 ResolvExpr::EqvClass eqvClass;
621 assert( env );
622 if ( tyParm->second.isComplete ) {
623 Type *concrete = env->lookup( tyParm->first );
624 if ( concrete ) {
625 arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) );
626 arg++;
627 arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) );
628 arg++;
629 } else {
630 // xxx - should this be an assertion?
631 std::string x = env ? toString( *env ) : "missing env";
632 throw SemanticError( x + "\n" + "unbound type variable: " + tyParm->first + " in application ", appExpr );
633 } // if
634 } // if
635 } // for
636
637 // add size/align for generic types to parameter list
638 if ( ! appExpr->get_function()->has_result() ) return;
639 FunctionType *funcType = getFunctionType( appExpr->get_function()->get_result() );
640 assert( funcType );
641
642 std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin();
643 std::list< Expression* >::const_iterator fnArg = arg;
644 std::set< std::string > seenTypes; ///< names for generic types we've seen
645
646 // a polymorphic return type may need to be added to the argument list
647 if ( polyRetType ) {
648 Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
649 passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
650 ++fnArg; // skip the return parameter in the argument list
651 }
652
653 // add type information args for presently unseen types in parameter list
654 for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
655 if ( ! (*fnArg)->get_result() ) continue;
656 Type * argType = (*fnArg)->get_result();
657 passArgTypeVars( appExpr, (*fnParm)->get_type(), argType, arg, exprTyVars, seenTypes );
658 }
659 }
660
661 ObjectDecl *Pass1::makeTemporary( Type *type ) {
662 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 );
663 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
664 return newObj;
665 }
666
667 Expression *Pass1::addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ) {
668 // Create temporary to hold return value of polymorphic function and produce that temporary as a result
669 // using a comma expression.
670 assert( retType );
671
672 Expression * paramExpr = nullptr;
673 // try to use existing return value parameter if it exists, otherwise create a new temporary
674 if ( retVals.count( appExpr ) ) {
675 paramExpr = retVals[appExpr]->clone();
676 } else {
677 ObjectDecl *newObj = makeTemporary( retType->clone() );
678 paramExpr = new VariableExpr( newObj );
679 }
680 Expression * retExpr = paramExpr->clone();
681
682 // If the type of the temporary is not polymorphic, box temporary by taking its address;
683 // otherwise the temporary is already boxed and can be used directly.
684 if ( ! isPolyType( paramExpr->get_result(), scopeTyVars, env ) ) {
685 paramExpr = new AddressExpr( paramExpr );
686 } // if
687 arg = appExpr->get_args().insert( arg, paramExpr ); // add argument to function call
688 arg++;
689 // Build a comma expression to call the function and emulate a normal return.
690 CommaExpr *commaExpr = new CommaExpr( appExpr, retExpr );
691 commaExpr->set_env( appExpr->get_env() );
692 appExpr->set_env( 0 );
693 return commaExpr;
694 }
695
696 void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) {
697 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
698 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
699 assertf(paramType, "Aggregate parameters should be type expressions");
700 paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) );
701 }
702 }
703
704 Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) {
705 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
706 Type *concrete = env->lookup( typeInst->get_name() );
707 if ( concrete == 0 ) {
708 // xxx - should this be an assertion?
709 std::string x = env ? toString( *env ) : "missing env";
710 throw SemanticError( x + "\n" + "Unbound type variable " + typeInst->get_name() + " in ", appExpr );
711 } // if
712 return concrete;
713 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
714 if ( doClone ) {
715 structType = structType->clone();
716 }
717 replaceParametersWithConcrete( appExpr, structType->get_parameters() );
718 return structType;
719 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
720 if ( doClone ) {
721 unionType = unionType->clone();
722 }
723 replaceParametersWithConcrete( appExpr, unionType->get_parameters() );
724 return unionType;
725 }
726 return type;
727 }
728
729 Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *dynType, std::list< Expression *>::iterator &arg ) {
730 assert( env );
731 Type *concrete = replaceWithConcrete( appExpr, dynType );
732 // add out-parameter for return value
733 return addRetParam( appExpr, function, concrete, arg );
734 }
735
736 Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
737 Expression *ret = appExpr;
738// if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) {
739 if ( isDynRet( function, tyVars ) ) {
740 ret = addRetParam( appExpr, function, function->get_returnVals().front()->get_type(), arg );
741 } // if
742 std::string mangleName = mangleAdapterName( function, tyVars );
743 std::string adapterName = makeAdapterName( mangleName );
744
745 // cast adaptee to void (*)(), since it may have any type inside a polymorphic function
746 Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
747 appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) );
748 appExpr->set_function( new NameExpr( adapterName ) ); // xxx - result is never set on NameExpr
749
750 return ret;
751 }
752
753 void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
754 assert( arg->has_result() );
755 if ( isPolyType( param, exprTyVars ) ) {
756 if ( isPolyType( arg->get_result() ) ) {
757 // if the argument's type is polymorphic, we don't need to box again!
758 return;
759 } else if ( arg->get_result()->get_lvalue() ) {
760 // VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue)
761 // xxx - need to test that this code is still reachable
762 if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) {
763 commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) );
764 } else {
765 arg = new AddressExpr( arg );
766 }
767 if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
768 // silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
769 arg = new CastExpr( arg, param->clone() );
770 }
771 } else {
772 // use type computed in unification to declare boxed variables
773 Type * newType = param->clone();
774 if ( env ) env->apply( newType );
775 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, newType, 0 );
776 newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
777 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
778 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
779 assign->get_args().push_back( new VariableExpr( newObj ) );
780 assign->get_args().push_back( arg );
781 stmtsToAdd.push_back( new ExprStmt( noLabels, assign ) );
782 arg = new AddressExpr( new VariableExpr( newObj ) );
783 } // if
784 } // if
785 }
786
787 /// cast parameters to polymorphic functions so that types are replaced with
788 /// void * if they are type parameters in the formal type.
789 /// this gets rid of warnings from gcc.
790 void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
791 if ( getFunctionType( formal ) ) {
792 Type * newType = formal->clone();
793 newType = ScrubTyVars::scrub( newType, tyVars );
794 actual = new CastExpr( actual, newType );
795 } // if
796 }
797
798 void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
799 for ( std::list< DeclarationWithType *>::const_iterator param = function->get_parameters().begin(); param != function->get_parameters().end(); ++param, ++arg ) {
800 assertf( arg != appExpr->get_args().end(), "boxParams: missing argument for param %s to %s in %s", toString( *param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
801 addCast( *arg, (*param)->get_type(), exprTyVars );
802 boxParam( (*param)->get_type(), *arg, exprTyVars );
803 } // for
804 }
805
806 void Pass1::addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
807 std::list< Expression *>::iterator cur = arg;
808 for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
809 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
810 InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
811 if ( inferParam == appExpr->get_inferParams().end() ) {
812 std::cerr << "looking for assertion: " << (*assert) << std::endl << appExpr << std::endl;
813 }
814 assertf( inferParam != appExpr->get_inferParams().end(), "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" );
815 Expression *newExpr = inferParam->second.expr->clone();
816 addCast( newExpr, (*assert)->get_type(), tyVars );
817 boxParam( (*assert)->get_type(), newExpr, tyVars );
818 appExpr->get_args().insert( cur, newExpr );
819 } // for
820 } // for
821 }
822
823 void makeRetParm( FunctionType *funcType ) {
824 DeclarationWithType *retParm = funcType->get_returnVals().front();
825
826 // make a new parameter that is a pointer to the type of the old return value
827 retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
828 funcType->get_parameters().push_front( retParm );
829
830 // we don't need the return value any more
831 funcType->get_returnVals().clear();
832 }
833
834 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ) {
835 // actually make the adapter type
836 FunctionType *adapter = adaptee->clone();
837// if ( ! adapter->get_returnVals().empty() && isPolyType( adapter->get_returnVals().front()->get_type(), tyVars ) ) {
838 if ( isDynRet( adapter, tyVars ) ) {
839 makeRetParm( adapter );
840 } // if
841 adapter->get_parameters().push_front( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ) );
842 return adapter;
843 }
844
845 Expression *makeAdapterArg( DeclarationWithType *param, DeclarationWithType *arg, DeclarationWithType *realParam, const TyVarMap &tyVars ) {
846 assert( param );
847 assert( arg );
848 if ( isPolyType( realParam->get_type(), tyVars ) ) {
849 if ( ! isPolyType( arg->get_type() ) ) {
850 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
851 deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
852 deref->set_result( arg->get_type()->clone() );
853 return deref;
854 } // if
855 } // if
856 return new VariableExpr( param );
857 }
858
859 void addAdapterParams( ApplicationExpr *adapteeApp, std::list< DeclarationWithType *>::iterator arg, std::list< DeclarationWithType *>::iterator param, std::list< DeclarationWithType *>::iterator paramEnd, std::list< DeclarationWithType *>::iterator realParam, const TyVarMap &tyVars ) {
860 UniqueName paramNamer( "_p" );
861 for ( ; param != paramEnd; ++param, ++arg, ++realParam ) {
862 if ( (*param)->get_name() == "" ) {
863 (*param)->set_name( paramNamer.newName() );
864 (*param)->set_linkage( LinkageSpec::C );
865 } // if
866 adapteeApp->get_args().push_back( makeAdapterArg( *param, *arg, *realParam, tyVars ) );
867 } // for
868 }
869
870 FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
871 FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
872 adapterType = ScrubTyVars::scrub( adapterType, tyVars );
873 DeclarationWithType *adapteeDecl = adapterType->get_parameters().front();
874 adapteeDecl->set_name( "_adaptee" );
875 ApplicationExpr *adapteeApp = new ApplicationExpr( new CastExpr( new VariableExpr( adapteeDecl ), new PointerType( Type::Qualifiers(), realType ) ) );
876 Statement *bodyStmt;
877
878 Type::ForallList::iterator tyArg = realType->get_forall().begin();
879 Type::ForallList::iterator tyParam = adapterType->get_forall().begin();
880 Type::ForallList::iterator realTyParam = adaptee->get_forall().begin();
881 for ( ; tyParam != adapterType->get_forall().end(); ++tyArg, ++tyParam, ++realTyParam ) {
882 assert( tyArg != realType->get_forall().end() );
883 std::list< DeclarationWithType *>::iterator assertArg = (*tyArg)->get_assertions().begin();
884 std::list< DeclarationWithType *>::iterator assertParam = (*tyParam)->get_assertions().begin();
885 std::list< DeclarationWithType *>::iterator realAssertParam = (*realTyParam)->get_assertions().begin();
886 for ( ; assertParam != (*tyParam)->get_assertions().end(); ++assertArg, ++assertParam, ++realAssertParam ) {
887 assert( assertArg != (*tyArg)->get_assertions().end() );
888 adapteeApp->get_args().push_back( makeAdapterArg( *assertParam, *assertArg, *realAssertParam, tyVars ) );
889 } // for
890 } // for
891
892 std::list< DeclarationWithType *>::iterator arg = realType->get_parameters().begin();
893 std::list< DeclarationWithType *>::iterator param = adapterType->get_parameters().begin();
894 std::list< DeclarationWithType *>::iterator realParam = adaptee->get_parameters().begin();
895 param++; // skip adaptee parameter in the adapter type
896 if ( realType->get_returnVals().empty() ) {
897 // void return
898 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
899 bodyStmt = new ExprStmt( noLabels, adapteeApp );
900// } else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
901 } else if ( isDynType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
902 // return type T
903 if ( (*param)->get_name() == "" ) {
904 (*param)->set_name( "_ret" );
905 (*param)->set_linkage( LinkageSpec::C );
906 } // if
907 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
908 UntypedExpr *deref = UntypedExpr::createDeref( new CastExpr( new VariableExpr( *param++ ), new PointerType( Type::Qualifiers(), realType->get_returnVals().front()->get_type()->clone() ) ) );
909 assign->get_args().push_back( deref );
910 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
911 assign->get_args().push_back( adapteeApp );
912 bodyStmt = new ExprStmt( noLabels, assign );
913 } else {
914 // adapter for a function that returns a monomorphic value
915 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
916 bodyStmt = new ReturnStmt( noLabels, adapteeApp );
917 } // if
918 CompoundStmt *adapterBody = new CompoundStmt( noLabels );
919 adapterBody->get_kids().push_back( bodyStmt );
920 std::string adapterName = makeAdapterName( mangleName );
921 return new FunctionDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, adapterType, adapterBody );
922 }
923
924 void Pass1::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
925 // collect a list of function types passed as parameters or implicit parameters (assertions)
926 std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
927 std::list< FunctionType *> functions;
928 for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
929 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
930 findFunction( (*assert)->get_type(), functions, exprTyVars, needsAdapter );
931 } // for
932 } // for
933 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
934 findFunction( (*arg)->get_type(), functions, exprTyVars, needsAdapter );
935 } // for
936
937 // parameter function types for which an appropriate adapter has been generated. we cannot use the types
938 // after applying substitutions, since two different parameter types may be unified to the same type
939 std::set< std::string > adaptersDone;
940
941 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
942 FunctionType *originalFunction = (*funType)->clone();
943 FunctionType *realFunction = (*funType)->clone();
944 std::string mangleName = SymTab::Mangler::mangle( realFunction );
945
946 // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
947 // pre-substitution parameter function type.
948 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
949 adaptersDone.insert( adaptersDone.begin(), mangleName );
950
951 // apply substitution to type variables to figure out what the adapter's type should look like
952 assert( env );
953 env->apply( realFunction );
954 mangleName = SymTab::Mangler::mangle( realFunction );
955 mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
956
957 typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
958 AdapterIter adapter = adapters.find( mangleName );
959 if ( adapter == adapters.end() ) {
960 // adapter has not been created yet in the current scope, so define it
961 FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars );
962 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
963 adapter = answer.first;
964 stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
965 } // if
966 assert( adapter != adapters.end() );
967
968 // add the appropriate adapter as a parameter
969 appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
970 } // if
971 } // for
972 } // passAdapters
973
974 Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, Type *polyType, bool isIncr ) {
975 NameExpr *opExpr;
976 if ( isIncr ) {
977 opExpr = new NameExpr( "?+=?" );
978 } else {
979 opExpr = new NameExpr( "?-=?" );
980 } // if
981 UntypedExpr *addAssign = new UntypedExpr( opExpr );
982 if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
983 addAssign->get_args().push_back( address->get_arg() );
984 } else {
985 addAssign->get_args().push_back( appExpr->get_args().front() );
986 } // if
987 addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) );
988 addAssign->set_result( appExpr->get_result()->clone() );
989 if ( appExpr->get_env() ) {
990 addAssign->set_env( appExpr->get_env() );
991 appExpr->set_env( 0 );
992 } // if
993 appExpr->get_args().clear();
994 delete appExpr;
995 return addAssign;
996 }
997
998 Expression *Pass1::handleIntrinsics( ApplicationExpr *appExpr ) {
999 if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->get_function() ) ) {
1000 if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
1001 if ( varExpr->get_var()->get_name() == "?[?]" ) {
1002 assert( appExpr->has_result() );
1003 assert( appExpr->get_args().size() == 2 );
1004 Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
1005 Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_result(), scopeTyVars, env );
1006 assert( ! baseType1 || ! baseType2 ); // the arguments cannot both be polymorphic pointers
1007 UntypedExpr *ret = 0;
1008 if ( baseType1 || baseType2 ) { // one of the arguments is a polymorphic pointer
1009 ret = new UntypedExpr( new NameExpr( "?+?" ) );
1010 } // if
1011 if ( baseType1 ) {
1012 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1013 multiply->get_args().push_back( appExpr->get_args().back() );
1014 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
1015 ret->get_args().push_back( appExpr->get_args().front() );
1016 ret->get_args().push_back( multiply );
1017 } else if ( baseType2 ) {
1018 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1019 multiply->get_args().push_back( appExpr->get_args().front() );
1020 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
1021 ret->get_args().push_back( multiply );
1022 ret->get_args().push_back( appExpr->get_args().back() );
1023 } // if
1024 if ( baseType1 || baseType2 ) {
1025 ret->set_result( appExpr->get_result()->clone() );
1026 if ( appExpr->get_env() ) {
1027 ret->set_env( appExpr->get_env() );
1028 appExpr->set_env( 0 );
1029 } // if
1030 appExpr->get_args().clear();
1031 delete appExpr;
1032 return ret;
1033 } // if
1034 } else if ( varExpr->get_var()->get_name() == "*?" ) {
1035 assert( appExpr->has_result() );
1036 assert( ! appExpr->get_args().empty() );
1037 if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) {
1038 Expression *ret = appExpr->get_args().front();
1039 delete ret->get_result();
1040 ret->set_result( appExpr->get_result()->clone() );
1041 if ( appExpr->get_env() ) {
1042 ret->set_env( appExpr->get_env() );
1043 appExpr->set_env( 0 );
1044 } // if
1045 appExpr->get_args().clear();
1046 delete appExpr;
1047 return ret;
1048 } // if
1049 } else if ( varExpr->get_var()->get_name() == "?++" || varExpr->get_var()->get_name() == "?--" ) {
1050 assert( appExpr->has_result() );
1051 assert( appExpr->get_args().size() == 1 );
1052 if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
1053 Type *tempType = appExpr->get_result()->clone();
1054 if ( env ) {
1055 env->apply( tempType );
1056 } // if
1057 ObjectDecl *newObj = makeTemporary( tempType );
1058 VariableExpr *tempExpr = new VariableExpr( newObj );
1059 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
1060 assignExpr->get_args().push_back( tempExpr->clone() );
1061 if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
1062 assignExpr->get_args().push_back( address->get_arg()->clone() );
1063 } else {
1064 assignExpr->get_args().push_back( appExpr->get_args().front()->clone() );
1065 } // if
1066 CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "?++" ) );
1067 return new CommaExpr( firstComma, tempExpr );
1068 } // if
1069 } else if ( varExpr->get_var()->get_name() == "++?" || varExpr->get_var()->get_name() == "--?" ) {
1070 assert( appExpr->has_result() );
1071 assert( appExpr->get_args().size() == 1 );
1072 if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
1073 return makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "++?" );
1074 } // if
1075 } else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
1076 assert( appExpr->has_result() );
1077 assert( appExpr->get_args().size() == 2 );
1078 Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
1079 Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_result(), scopeTyVars, env );
1080 if ( baseType1 && baseType2 ) {
1081 UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
1082 divide->get_args().push_back( appExpr );
1083 divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
1084 divide->set_result( appExpr->get_result()->clone() );
1085 if ( appExpr->get_env() ) {
1086 divide->set_env( appExpr->get_env() );
1087 appExpr->set_env( 0 );
1088 } // if
1089 return divide;
1090 } else if ( baseType1 ) {
1091 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1092 multiply->get_args().push_back( appExpr->get_args().back() );
1093 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
1094 appExpr->get_args().back() = multiply;
1095 } else if ( baseType2 ) {
1096 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1097 multiply->get_args().push_back( appExpr->get_args().front() );
1098 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
1099 appExpr->get_args().front() = multiply;
1100 } // if
1101 } else if ( varExpr->get_var()->get_name() == "?+=?" || varExpr->get_var()->get_name() == "?-=?" ) {
1102 assert( appExpr->has_result() );
1103 assert( appExpr->get_args().size() == 2 );
1104 Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env );
1105 if ( baseType ) {
1106 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1107 multiply->get_args().push_back( appExpr->get_args().back() );
1108 multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) );
1109 appExpr->get_args().back() = multiply;
1110 } // if
1111 } // if
1112 return appExpr;
1113 } // if
1114 } // if
1115 return 0;
1116 }
1117
1118 Expression *Pass1::mutate( ApplicationExpr *appExpr ) {
1119 // std::cerr << "mutate appExpr: ";
1120 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
1121 // std::cerr << i->first << " ";
1122 // }
1123 // std::cerr << "\n";
1124 appExpr->get_function()->acceptMutator( *this );
1125 mutateAll( appExpr->get_args(), *this );
1126
1127 assert( appExpr->get_function()->has_result() );
1128 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
1129 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
1130
1131 if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
1132 return newExpr;
1133 } // if
1134
1135 Expression *ret = appExpr;
1136
1137 std::list< Expression *>::iterator arg = appExpr->get_args().begin();
1138 std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
1139
1140 TyVarMap exprTyVars( TypeDecl::Data{} );
1141 makeTyVarMap( function, exprTyVars ); // xxx - should this take into account the variables already bound in scopeTyVars (i.e. remove them from exprTyVars?)
1142 ReferenceToType *dynRetType = isDynRet( function, exprTyVars );
1143
1144 // NOTE: addDynRetParam needs to know the actual (generated) return type so it can make a temp variable, so pass the result type from the appExpr
1145 // passTypeVars needs to know the program-text return type (i.e. the distinction between _conc_T30 and T3(int))
1146 // concRetType may not be a good name in one or both of these places. A more appropriate name change is welcome.
1147 if ( dynRetType ) {
1148 Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();
1149 ret = addDynRetParam( appExpr, function, concRetType, arg ); // xxx - used to use dynRetType instead of concRetType
1150 } else if ( needsAdapter( function, scopeTyVars ) && ! needsAdapter( function, exprTyVars) ) { // xxx - exprTyVars is used above...?
1151 // xxx - the ! needsAdapter check may be incorrect. It seems there is some situation where an adapter is applied where it shouldn't be, and this fixes it for some cases. More investigation is needed.
1152
1153 // std::cerr << "needs adapter: ";
1154 // printTyVarMap( std::cerr, scopeTyVars );
1155 // std::cerr << *env << std::endl;
1156 // change the application so it calls the adapter rather than the passed function
1157 ret = applyAdapter( appExpr, function, arg, scopeTyVars );
1158 } // if
1159 arg = appExpr->get_args().begin();
1160
1161 Type *concRetType = replaceWithConcrete( appExpr, dynRetType );
1162 passTypeVars( appExpr, concRetType, arg, exprTyVars ); // xxx - used to use dynRetType instead of concRetType; this changed so that the correct type paramaters are passed for return types (it should be the concrete type's parameters, not the formal type's)
1163 addInferredParams( appExpr, function, arg, exprTyVars );
1164
1165 arg = paramBegin;
1166
1167 boxParams( appExpr, function, arg, exprTyVars );
1168 passAdapters( appExpr, function, exprTyVars );
1169
1170 return ret;
1171 }
1172
1173 Expression *Pass1::mutate( UntypedExpr *expr ) {
1174 if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
1175 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
1176 if ( name->get_name() == "*?" ) {
1177 Expression *ret = expr->get_args().front();
1178 expr->get_args().clear();
1179 delete expr;
1180 return ret->acceptMutator( *this );
1181 } // if
1182 } // if
1183 } // if
1184 return PolyMutator::mutate( expr );
1185 }
1186
1187 Expression *Pass1::mutate( AddressExpr *addrExpr ) {
1188 assert( addrExpr->get_arg()->has_result() && ! addrExpr->get_arg()->get_result()->isVoid() );
1189
1190 bool needs = false;
1191 if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->get_arg() ) ) {
1192 if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
1193 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
1194 if ( name->get_name() == "*?" ) {
1195 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
1196 assert( appExpr->get_function()->has_result() );
1197 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
1198 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
1199 needs = needsAdapter( function, scopeTyVars );
1200 } // if
1201 } // if
1202 } // if
1203 } // if
1204 } // if
1205 // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
1206 // out of the if condition.
1207 bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env );
1208 addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
1209 if ( polytype || needs ) {
1210 Expression *ret = addrExpr->get_arg();
1211 delete ret->get_result();
1212 ret->set_result( addrExpr->get_result()->clone() );
1213 addrExpr->set_arg( 0 );
1214 delete addrExpr;
1215 return ret;
1216 } else {
1217 return addrExpr;
1218 } // if
1219 }
1220
1221 Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
1222 if ( retval && returnStmt->get_expr() ) {
1223 assert( returnStmt->get_expr()->has_result() && ! returnStmt->get_expr()->get_result()->isVoid() );
1224 delete returnStmt->get_expr();
1225 returnStmt->set_expr( 0 );
1226 } else {
1227 returnStmt->set_expr( mutateExpression( returnStmt->get_expr() ) );
1228 } // if
1229 return returnStmt;
1230 }
1231
1232 Type * Pass1::mutate( PointerType *pointerType ) {
1233 scopeTyVars.beginScope();
1234 makeTyVarMap( pointerType, scopeTyVars );
1235
1236 Type *ret = Mutator::mutate( pointerType );
1237
1238 scopeTyVars.endScope();
1239 return ret;
1240 }
1241
1242 Type * Pass1::mutate( FunctionType *functionType ) {
1243 scopeTyVars.beginScope();
1244 makeTyVarMap( functionType, scopeTyVars );
1245
1246 Type *ret = Mutator::mutate( functionType );
1247
1248 scopeTyVars.endScope();
1249 return ret;
1250 }
1251
1252 void Pass1::doBeginScope() {
1253 adapters.beginScope();
1254 }
1255
1256 void Pass1::doEndScope() {
1257 adapters.endScope();
1258 }
1259
1260////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
1261
1262 void Pass2::addAdapters( FunctionType *functionType ) {
1263 std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
1264 std::list< FunctionType *> functions;
1265 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
1266 Type *orig = (*arg)->get_type();
1267 findAndReplaceFunction( orig, functions, scopeTyVars, needsAdapter );
1268 (*arg)->set_type( orig );
1269 }
1270 std::set< std::string > adaptersDone;
1271 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
1272 std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
1273 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
1274 std::string adapterName = makeAdapterName( mangleName );
1275 paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) );
1276 adaptersDone.insert( adaptersDone.begin(), mangleName );
1277 }
1278 }
1279// deleteAll( functions );
1280 }
1281
1282 template< typename DeclClass >
1283 DeclClass * Pass2::handleDecl( DeclClass *decl, Type *type ) {
1284 DeclClass *ret = static_cast< DeclClass *>( Parent::mutate( decl ) );
1285
1286 return ret;
1287 }
1288
1289 /// determines if `pref` is a prefix of `str`
1290 bool isPrefix( const std::string & str, const std::string & pref ) {
1291 if ( pref.size() > str.size() ) return false;
1292 auto its = std::mismatch( pref.begin(), pref.end(), str.begin() );
1293 return its.first == pref.end();
1294 }
1295
1296 DeclarationWithType * Pass2::mutate( FunctionDecl *functionDecl ) {
1297 functionDecl = safe_dynamic_cast< FunctionDecl * > ( handleDecl( functionDecl, functionDecl->get_functionType() ) );
1298 FunctionType * ftype = functionDecl->get_functionType();
1299 if ( ! ftype->get_returnVals().empty() && functionDecl->get_statements() ) {
1300 if ( functionDecl->get_name() != "?=?" && ! isPrefix( functionDecl->get_name(), "_thunk" ) && ! isPrefix( functionDecl->get_name(), "_adapter" ) ) { // xxx - remove check for ?=? once reference types are in; remove check for prefix once thunks properly use ctor/dtors
1301 assert( ftype->get_returnVals().size() == 1 );
1302 DeclarationWithType * retval = ftype->get_returnVals().front();
1303 if ( retval->get_name() == "" ) {
1304 retval->set_name( "_retval" );
1305 }
1306 functionDecl->get_statements()->get_kids().push_front( new DeclStmt( noLabels, retval ) );
1307 DeclarationWithType * newRet = retval->clone(); // for ownership purposes
1308 ftype->get_returnVals().front() = newRet;
1309 }
1310 }
1311 // errors should have been caught by this point, remove initializers from parameters to allow correct codegen of default arguments
1312 for ( Declaration * param : functionDecl->get_functionType()->get_parameters() ) {
1313 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( param ) ) {
1314 delete obj->get_init();
1315 obj->set_init( nullptr );
1316 }
1317 }
1318 return functionDecl;
1319 }
1320
1321 ObjectDecl * Pass2::mutate( ObjectDecl *objectDecl ) {
1322 return handleDecl( objectDecl, objectDecl->get_type() );
1323 }
1324
1325 template< typename AggDecl >
1326 AggDecl * Pass2::handleAggDecl( AggDecl * aggDecl ) {
1327 // prevent tyVars from leaking into containing scope
1328 scopeTyVars.beginScope();
1329 Parent::mutate( aggDecl );
1330 scopeTyVars.endScope();
1331 return aggDecl;
1332 }
1333
1334 StructDecl * Pass2::mutate( StructDecl *aggDecl ) {
1335 return handleAggDecl( aggDecl );
1336 }
1337
1338 UnionDecl * Pass2::mutate( UnionDecl *aggDecl ) {
1339 return handleAggDecl( aggDecl );
1340 }
1341
1342 TypeDecl * Pass2::mutate( TypeDecl *typeDecl ) {
1343 addToTyVarMap( typeDecl, scopeTyVars );
1344 if ( typeDecl->get_base() ) {
1345 return handleDecl( typeDecl, typeDecl->get_base() );
1346 } else {
1347 return Parent::mutate( typeDecl );
1348 }
1349 }
1350
1351 TypedefDecl * Pass2::mutate( TypedefDecl *typedefDecl ) {
1352 return handleDecl( typedefDecl, typedefDecl->get_base() );
1353 }
1354
1355 Type * Pass2::mutate( PointerType *pointerType ) {
1356 scopeTyVars.beginScope();
1357 makeTyVarMap( pointerType, scopeTyVars );
1358
1359 Type *ret = Parent::mutate( pointerType );
1360
1361 scopeTyVars.endScope();
1362 return ret;
1363 }
1364
1365 Type *Pass2::mutate( FunctionType *funcType ) {
1366 scopeTyVars.beginScope();
1367 makeTyVarMap( funcType, scopeTyVars );
1368
1369 // move polymorphic return type to parameter list
1370 if ( isDynRet( funcType ) ) {
1371 ObjectDecl *ret = safe_dynamic_cast< ObjectDecl* >( funcType->get_returnVals().front() );
1372 ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
1373 funcType->get_parameters().push_front( ret );
1374 funcType->get_returnVals().pop_front();
1375 ret->set_init( nullptr ); // xxx - memory leak?
1376 }
1377
1378 // add size/align and assertions for type parameters to parameter list
1379 std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
1380 std::list< DeclarationWithType *> inferredParams;
1381 ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 );
1382 ObjectDecl newPtr( "", Type::StorageClasses(), LinkageSpec::C, 0,
1383 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
1384 for ( Type::ForallList::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
1385 ObjectDecl *sizeParm, *alignParm;
1386 // add all size and alignment parameters to parameter list
1387 if ( (*tyParm)->isComplete() ) {
1388 TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm );
1389 std::string parmName = mangleType( &parmType );
1390
1391 sizeParm = newObj.clone();
1392 sizeParm->set_name( sizeofName( parmName ) );
1393 last = funcType->get_parameters().insert( last, sizeParm );
1394 ++last;
1395
1396 alignParm = newObj.clone();
1397 alignParm->set_name( alignofName( parmName ) );
1398 last = funcType->get_parameters().insert( last, alignParm );
1399 ++last;
1400 }
1401 // move all assertions into parameter list
1402 for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
1403// *assert = (*assert)->acceptMutator( *this );
1404 inferredParams.push_back( *assert );
1405 }
1406 (*tyParm)->get_assertions().clear();
1407 }
1408
1409 // add size/align for generic parameter types to parameter list
1410 std::set< std::string > seenTypes; // sizeofName for generic types we've seen
1411 for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
1412 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
1413 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
1414 std::string typeName = mangleType( polyType );
1415 if ( seenTypes.count( typeName ) ) continue;
1416
1417 ObjectDecl *sizeParm, *alignParm, *offsetParm;
1418 sizeParm = newObj.clone();
1419 sizeParm->set_name( sizeofName( typeName ) );
1420 last = funcType->get_parameters().insert( last, sizeParm );
1421 ++last;
1422
1423 alignParm = newObj.clone();
1424 alignParm->set_name( alignofName( typeName ) );
1425 last = funcType->get_parameters().insert( last, alignParm );
1426 ++last;
1427
1428 if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyType ) ) {
1429 // NOTE zero-length arrays are illegal in C, so empty structs have no offset array
1430 if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) {
1431 offsetParm = newPtr.clone();
1432 offsetParm->set_name( offsetofName( typeName ) );
1433 last = funcType->get_parameters().insert( last, offsetParm );
1434 ++last;
1435 }
1436 }
1437
1438 seenTypes.insert( typeName );
1439 }
1440 }
1441
1442 // splice assertion parameters into parameter list
1443 funcType->get_parameters().splice( last, inferredParams );
1444 addAdapters( funcType );
1445 mutateAll( funcType->get_returnVals(), *this );
1446 mutateAll( funcType->get_parameters(), *this );
1447
1448 scopeTyVars.endScope();
1449 return funcType;
1450 }
1451
1452////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////////////////////////
1453
1454 PolyGenericCalculator::PolyGenericCalculator()
1455 : Parent(), knownLayouts(), knownOffsets(), bufNamer( "_buf" ) {}
1456
1457 void PolyGenericCalculator::beginTypeScope( Type *ty ) {
1458 scopeTyVars.beginScope();
1459 makeTyVarMap( ty, scopeTyVars );
1460 }
1461
1462 void PolyGenericCalculator::endTypeScope() {
1463 scopeTyVars.endScope();
1464 }
1465
1466 template< typename DeclClass >
1467 DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) {
1468 beginTypeScope( type );
1469 // knownLayouts.beginScope();
1470 // knownOffsets.beginScope();
1471
1472 DeclClass *ret = static_cast< DeclClass *>( Parent::mutate( decl ) );
1473
1474 // knownOffsets.endScope();
1475 // knownLayouts.endScope();
1476 endTypeScope();
1477 return ret;
1478 }
1479
1480 ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) {
1481 return handleDecl( objectDecl, objectDecl->get_type() );
1482 }
1483
1484 DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) {
1485 knownLayouts.beginScope();
1486 knownOffsets.beginScope();
1487
1488 DeclarationWithType * decl = handleDecl( functionDecl, functionDecl->get_functionType() );
1489 knownOffsets.endScope();
1490 knownLayouts.endScope();
1491 return decl;
1492 }
1493
1494 TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) {
1495 return handleDecl( typedefDecl, typedefDecl->get_base() );
1496 }
1497
1498 TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {
1499 addToTyVarMap( typeDecl, scopeTyVars );
1500 return Parent::mutate( typeDecl );
1501 }
1502
1503 Type * PolyGenericCalculator::mutate( PointerType *pointerType ) {
1504 beginTypeScope( pointerType );
1505
1506 Type *ret = Parent::mutate( pointerType );
1507
1508 endTypeScope();
1509 return ret;
1510 }
1511
1512 Type * PolyGenericCalculator::mutate( FunctionType *funcType ) {
1513 beginTypeScope( funcType );
1514
1515 // make sure that any type information passed into the function is accounted for
1516 for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) {
1517 // condition here duplicates that in Pass2::mutate( FunctionType* )
1518 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
1519 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
1520 knownLayouts.insert( mangleType( polyType ) );
1521 }
1522 }
1523
1524 Type *ret = Parent::mutate( funcType );
1525
1526 endTypeScope();
1527 return ret;
1528 }
1529
1530 Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) {
1531 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
1532 if ( findGeneric( objectDecl->get_type() ) ) {
1533 // change initialization of a polymorphic value object to allocate via a VLA
1534 // (alloca was previously used, but can't be safely used in loops)
1535 Type *declType = objectDecl->get_type();
1536 std::string bufName = bufNamer.newName();
1537 ObjectDecl *newBuf = new ObjectDecl( bufName, Type::StorageClasses(), LinkageSpec::C, 0,
1538 new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::Kind::Char), new NameExpr( sizeofName( mangleType(declType) ) ),
1539 true, false, std::list<Attribute*>{ new Attribute( std::string{"aligned"}, std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } ) } ), 0 );
1540 stmtsToAdd.push_back( new DeclStmt( noLabels, newBuf ) );
1541
1542 delete objectDecl->get_init();
1543
1544 objectDecl->set_init( new SingleInit( new NameExpr( bufName ) ) );
1545 }
1546 }
1547 return Parent::mutate( declStmt );
1548 }
1549
1550 /// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
1551 long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
1552 long i = 0;
1553 for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) {
1554 if ( memberDecl->get_name() != (*decl)->get_name() ) continue;
1555
1556 if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
1557 if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty()
1558 || memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
1559 else continue;
1560 } else return i;
1561 }
1562 return -1;
1563 }
1564
1565 /// Returns an index expression into the offset array for a type
1566 Expression *makeOffsetIndex( Type *objectType, long i ) {
1567 std::stringstream offset_namer;
1568 offset_namer << i;
1569 ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );
1570 UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
1571 fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType ) ) ) );
1572 fieldOffset->get_args().push_back( fieldIndex );
1573 return fieldOffset;
1574 }
1575
1576 Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) {
1577 // mutate, exiting early if no longer MemberExpr
1578 Expression *expr = Parent::mutate( memberExpr );
1579 memberExpr = dynamic_cast< MemberExpr* >( expr );
1580 if ( ! memberExpr ) return expr;
1581
1582 // only mutate member expressions for polymorphic types
1583 int tyDepth;
1584 Type *objectType = hasPolyBase( memberExpr->get_aggregate()->get_result(), scopeTyVars, &tyDepth );
1585 if ( ! objectType ) return memberExpr;
1586 findGeneric( objectType ); // ensure layout for this type is available
1587
1588 // replace member expression with dynamically-computed layout expression
1589 Expression *newMemberExpr = 0;
1590 if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
1591 // look up offset index
1592 long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() );
1593 if ( i == -1 ) return memberExpr;
1594
1595 // replace member expression with pointer to base plus offset
1596 UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
1597 Expression * aggr = memberExpr->get_aggregate()->clone();
1598 delete aggr->get_env(); // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
1599 aggr->set_env( nullptr );
1600 fieldLoc->get_args().push_back( aggr );
1601 fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
1602 fieldLoc->set_result( memberExpr->get_result()->clone() );
1603 newMemberExpr = fieldLoc;
1604 } else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
1605 // union members are all at offset zero, so just use the aggregate expr
1606 Expression * aggr = memberExpr->get_aggregate()->clone();
1607 delete aggr->get_env(); // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
1608 aggr->set_env( nullptr );
1609 newMemberExpr = aggr;
1610 newMemberExpr->set_result( memberExpr->get_result()->clone() );
1611 } else return memberExpr;
1612 assert( newMemberExpr );
1613
1614 Type *memberType = memberExpr->get_member()->get_type();
1615 if ( ! isPolyType( memberType, scopeTyVars ) ) {
1616 // Not all members of a polymorphic type are themselves of polymorphic type; in this case the member expression should be wrapped and dereferenced to form an lvalue
1617 CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) );
1618 UntypedExpr *derefExpr = UntypedExpr::createDeref( ptrCastExpr );
1619 newMemberExpr = derefExpr;
1620 }
1621
1622 delete memberExpr;
1623 return newMemberExpr;
1624 }
1625
1626 ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
1627 ObjectDecl *newObj = new ObjectDecl( name, Type::StorageClasses(), LinkageSpec::C, 0, type, init );
1628 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
1629 return newObj;
1630 }
1631
1632 void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
1633 for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
1634 if ( findGeneric( *param ) ) {
1635 // push size/align vars for a generic parameter back
1636 std::string paramName = mangleType( *param );
1637 layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) );
1638 layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) );
1639 } else {
1640 layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
1641 layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
1642 }
1643 }
1644 }
1645
1646 /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
1647 bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
1648 bool hasDynamicLayout = false;
1649
1650 std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
1651 std::list< Expression* >::const_iterator typeParam = typeParams.begin();
1652 for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
1653 // skip non-otype parameters
1654 if ( ! (*baseParam)->isComplete() ) continue;
1655 TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
1656 assert( typeExpr && "all otype parameters should be type expressions" );
1657
1658 Type *type = typeExpr->get_type();
1659 out.push_back( type );
1660 if ( isPolyType( type ) ) hasDynamicLayout = true;
1661 }
1662 assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
1663
1664 return hasDynamicLayout;
1665 }
1666
1667 bool PolyGenericCalculator::findGeneric( Type *ty ) {
1668 ty = replaceTypeInst( ty, env );
1669
1670 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
1671 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
1672 // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
1673 return true;
1674 }
1675 return false;
1676 } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
1677 // check if this type already has a layout generated for it
1678 std::string typeName = mangleType( ty );
1679 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
1680
1681 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
1682 std::list< Type* > otypeParams;
1683 if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
1684
1685 // insert local variables for layout and generate call to layout function
1686 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call
1687 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1688
1689 int n_members = structTy->get_baseStruct()->get_members().size();
1690 if ( n_members == 0 ) {
1691 // all empty structs have the same layout - size 1, align 1
1692 makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
1693 makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
1694 // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
1695 } else {
1696 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
1697 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
1698 ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from_int( n_members ) ), false, false ) );
1699
1700 // generate call to layout function
1701 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( structTy->get_baseStruct() ) ) );
1702 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
1703 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
1704 layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
1705 addOtypeParamsToLayoutCall( layoutCall, otypeParams );
1706
1707 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
1708 }
1709
1710 return true;
1711 } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
1712 // check if this type already has a layout generated for it
1713 std::string typeName = mangleType( ty );
1714 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
1715
1716 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
1717 std::list< Type* > otypeParams;
1718 if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
1719
1720 // insert local variables for layout and generate call to layout function
1721 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call
1722 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1723
1724 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
1725 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
1726
1727 // generate call to layout function
1728 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( unionTy->get_baseUnion() ) ) );
1729 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
1730 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
1731 addOtypeParamsToLayoutCall( layoutCall, otypeParams );
1732
1733 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
1734
1735 return true;
1736 }
1737
1738 return false;
1739 }
1740
1741 Expression *PolyGenericCalculator::mutate( SizeofExpr *sizeofExpr ) {
1742 Type *ty = sizeofExpr->get_type();
1743 if ( findGeneric( ty ) ) {
1744 Expression *ret = new NameExpr( sizeofName( mangleType( ty ) ) );
1745 delete sizeofExpr;
1746 return ret;
1747 }
1748 return sizeofExpr;
1749 }
1750
1751 Expression *PolyGenericCalculator::mutate( AlignofExpr *alignofExpr ) {
1752 Type *ty = alignofExpr->get_type();
1753 if ( findGeneric( ty ) ) {
1754 Expression *ret = new NameExpr( alignofName( mangleType( ty ) ) );
1755 delete alignofExpr;
1756 return ret;
1757 }
1758 return alignofExpr;
1759 }
1760
1761 Expression *PolyGenericCalculator::mutate( OffsetofExpr *offsetofExpr ) {
1762 // mutate, exiting early if no longer OffsetofExpr
1763 Expression *expr = Parent::mutate( offsetofExpr );
1764 offsetofExpr = dynamic_cast< OffsetofExpr* >( expr );
1765 if ( ! offsetofExpr ) return expr;
1766
1767 // only mutate expressions for polymorphic structs/unions
1768 Type *ty = offsetofExpr->get_type();
1769 if ( ! findGeneric( ty ) ) return offsetofExpr;
1770
1771 if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
1772 // replace offsetof expression by index into offset array
1773 long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() );
1774 if ( i == -1 ) return offsetofExpr;
1775
1776 Expression *offsetInd = makeOffsetIndex( ty, i );
1777 delete offsetofExpr;
1778 return offsetInd;
1779 } else if ( dynamic_cast< UnionInstType* >( ty ) ) {
1780 // all union members are at offset zero
1781 delete offsetofExpr;
1782 return new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "0" ) );
1783 } else return offsetofExpr;
1784 }
1785
1786 Expression *PolyGenericCalculator::mutate( OffsetPackExpr *offsetPackExpr ) {
1787 StructInstType *ty = offsetPackExpr->get_type();
1788
1789 Expression *ret = 0;
1790 if ( findGeneric( ty ) ) {
1791 // pull offset back from generated type information
1792 ret = new NameExpr( offsetofName( mangleType( ty ) ) );
1793 } else {
1794 std::string offsetName = offsetofName( mangleType( ty ) );
1795 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
1796 // use the already-generated offsets for this type
1797 ret = new NameExpr( offsetName );
1798 } else {
1799 knownOffsets.insert( offsetName );
1800
1801 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
1802 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1803
1804 // build initializer list for offset array
1805 std::list< Initializer* > inits;
1806 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
1807 DeclarationWithType *memberDecl;
1808 if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
1809 memberDecl = origMember->clone();
1810 } else {
1811 memberDecl = new ObjectDecl( (*member)->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
1812 }
1813 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
1814 }
1815
1816 // build the offset array and replace the pack with a reference to it
1817 ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from_ulong( baseMembers.size() ) ), false, false ),
1818 new ListInit( inits ) );
1819 ret = new VariableExpr( offsetArray );
1820 }
1821 }
1822
1823 delete offsetPackExpr;
1824 return ret;
1825 }
1826
1827 void PolyGenericCalculator::doBeginScope() {
1828 knownLayouts.beginScope();
1829 knownOffsets.beginScope();
1830 }
1831
1832 void PolyGenericCalculator::doEndScope() {
1833 knownLayouts.endScope();
1834 knownOffsets.endScope();
1835 }
1836
1837////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
1838
1839 template< typename DeclClass >
1840 DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
1841 scopeTyVars.beginScope();
1842 makeTyVarMap( type, scopeTyVars );
1843
1844 DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
1845 // ScrubTyVars::scrub( decl, scopeTyVars );
1846 ScrubTyVars::scrubAll( decl );
1847
1848 scopeTyVars.endScope();
1849 return ret;
1850 }
1851
1852 ObjectDecl * Pass3::mutate( ObjectDecl *objectDecl ) {
1853 return handleDecl( objectDecl, objectDecl->get_type() );
1854 }
1855
1856 DeclarationWithType * Pass3::mutate( FunctionDecl *functionDecl ) {
1857 return handleDecl( functionDecl, functionDecl->get_functionType() );
1858 }
1859
1860 TypedefDecl * Pass3::mutate( TypedefDecl *typedefDecl ) {
1861 return handleDecl( typedefDecl, typedefDecl->get_base() );
1862 }
1863
1864 TypeDecl * Pass3::mutate( TypeDecl *typeDecl ) {
1865// Initializer *init = 0;
1866// std::list< Expression *> designators;
1867// addToTyVarMap( typeDecl, scopeTyVars );
1868// if ( typeDecl->get_base() ) {
1869// init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators );
1870// }
1871// return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init );
1872
1873 addToTyVarMap( typeDecl, scopeTyVars );
1874 return Mutator::mutate( typeDecl );
1875 }
1876
1877 Type * Pass3::mutate( PointerType *pointerType ) {
1878 scopeTyVars.beginScope();
1879 makeTyVarMap( pointerType, scopeTyVars );
1880
1881 Type *ret = Mutator::mutate( pointerType );
1882
1883 scopeTyVars.endScope();
1884 return ret;
1885 }
1886
1887 Type * Pass3::mutate( FunctionType *functionType ) {
1888 scopeTyVars.beginScope();
1889 makeTyVarMap( functionType, scopeTyVars );
1890
1891 Type *ret = Mutator::mutate( functionType );
1892
1893 scopeTyVars.endScope();
1894 return ret;
1895 }
1896 } // anonymous namespace
1897} // namespace GenPoly
1898
1899// Local Variables: //
1900// tab-width: 4 //
1901// mode: c++ //
1902// compile-command: "make install" //
1903// End: //
Note: See TracBrowser for help on using the repository browser.