source: src/GenPoly/Box.cc@ d1685588

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 d1685588 was 795d450, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Correct the expression type after boxing intrinsic dereference to the argument base type

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