source: src/GenPoly/Box.cc@ 6d267ca

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 6d267ca was bff227f, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Refactor operator predicates into OperatorTable.cc

  • 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 "CodeGen/OperatorTable.h"
59
60#include "InitTweak/InitTweak.h"
61
62#include <ext/functional> // temporary
63
64namespace GenPoly {
65 namespace {
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, 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, 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 );
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::from_ulong( 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::from_ulong( 0 ) ) ) );
389 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant::from_ulong( 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::from_ulong( 1 ) ) ) );
446 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant::from_ulong( 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 // std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl;
509 doBeginScope();
510 scopeTyVars.beginScope();
511
512 DeclarationWithType *oldRetval = retval;
513
514 // process polymorphic return value
515 retval = nullptr;
516 if ( isDynRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() != LinkageSpec::C ) {
517 retval = functionDecl->get_functionType()->get_returnVals().front();
518
519 // give names to unnamed return values
520 if ( retval->get_name() == "" ) {
521 retval->set_name( "_retparm" );
522 retval->set_linkage( LinkageSpec::C );
523 } // if
524 } // if
525
526 FunctionType *functionType = functionDecl->get_functionType();
527 makeTyVarMap( functionDecl->get_functionType(), scopeTyVars );
528
529 std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
530 std::list< FunctionType *> functions;
531 for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
532 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
533 findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter );
534 } // for
535 } // for
536 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
537 findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter );
538 } // for
539
540 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
541 std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
542 if ( adapters.find( mangleName ) == adapters.end() ) {
543 std::string adapterName = makeAdapterName( mangleName );
544 adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), nullptr ) ) );
545 } // if
546 } // for
547
548 functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );
549
550 scopeTyVars.endScope();
551 retval = oldRetval;
552 doEndScope();
553 // std::cerr << "end function: " << functionDecl->get_mangleName() << std::endl;
554 } // if
555 return functionDecl;
556 }
557
558 TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) {
559 addToTyVarMap( typeDecl, scopeTyVars );
560 return Mutator::mutate( typeDecl );
561 }
562
563 Expression *Pass1::mutate( CommaExpr *commaExpr ) {
564 // Attempting to find application expressions that were mutated by the copy constructor passes
565 // to use an explicit return variable, so that the variable can be reused as a parameter to the
566 // call rather than creating a new temp variable. Previously this step was an optimization, but
567 // with the introduction of tuples and UniqueExprs, it is necessary to ensure that they use the same variable.
568 // Essentially, looking for pattern: (x=f(...), x)
569 // To compound the issue, the right side can be *x, etc. because of lvalue-returning functions
570 if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) {
571 if ( CodeGen::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
572 assert( assign->get_args().size() == 2 );
573 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) {
574 // first argument is assignable, so it must be an lvalue, so it should be legal to take its address.
575 retVals[appExpr] = assign->get_args().front();
576 }
577 }
578 }
579
580 commaExpr->set_arg1( maybeMutate( commaExpr->get_arg1(), *this ) );
581 commaExpr->set_arg2( maybeMutate( commaExpr->get_arg2(), *this ) );
582 return commaExpr;
583 }
584
585 Expression *Pass1::mutate( ConditionalExpr *condExpr ) {
586 condExpr->set_arg1( maybeMutate( condExpr->get_arg1(), *this ) );
587 condExpr->set_arg2( maybeMutate( condExpr->get_arg2(), *this ) );
588 condExpr->set_arg3( maybeMutate( condExpr->get_arg3(), *this ) );
589 return condExpr;
590
591 }
592
593 void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
594 Type *polyType = isPolyType( parmType, exprTyVars );
595 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
596 std::string typeName = mangleType( polyType );
597 if ( seenTypes.count( typeName ) ) return;
598
599 arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
600 arg++;
601 arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
602 arg++;
603 if ( dynamic_cast< StructInstType* >( polyType ) ) {
604 if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
605 // zero-length arrays are forbidden by C, so don't pass offset for empty struct
606 if ( ! argBaseStructType->get_baseStruct()->get_members().empty() ) {
607 arg = appExpr->get_args().insert( arg, new OffsetPackExpr( argBaseStructType->clone() ) );
608 arg++;
609 }
610 } else {
611 throw SemanticError( "Cannot pass non-struct type for generic struct: ", argBaseType );
612 }
613 }
614
615 seenTypes.insert( typeName );
616 }
617 }
618
619 void Pass1::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
620 // pass size/align for type variables
621 for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
622 ResolvExpr::EqvClass eqvClass;
623 assert( env );
624 if ( tyParm->second.isComplete ) {
625 Type *concrete = env->lookup( tyParm->first );
626 if ( concrete ) {
627 arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) );
628 arg++;
629 arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) );
630 arg++;
631 } else {
632 // xxx - should this be an assertion?
633 std::string x = env ? toString( *env ) : "missing env";
634 throw SemanticError( x + "\n" + "unbound type variable: " + tyParm->first + " in application ", appExpr );
635 } // if
636 } // if
637 } // for
638
639 // add size/align for generic types to parameter list
640 if ( ! appExpr->get_function()->has_result() ) return;
641 FunctionType *funcType = getFunctionType( appExpr->get_function()->get_result() );
642 assert( funcType );
643
644 std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin();
645 std::list< Expression* >::const_iterator fnArg = arg;
646 std::set< std::string > seenTypes; ///< names for generic types we've seen
647
648 // a polymorphic return type may need to be added to the argument list
649 if ( polyRetType ) {
650 Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
651 passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
652 ++fnArg; // skip the return parameter in the argument list
653 }
654
655 // add type information args for presently unseen types in parameter list
656 for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
657 if ( ! (*fnArg)->get_result() ) continue;
658 Type * argType = (*fnArg)->get_result();
659 passArgTypeVars( appExpr, (*fnParm)->get_type(), argType, arg, exprTyVars, seenTypes );
660 }
661 }
662
663 ObjectDecl *Pass1::makeTemporary( Type *type ) {
664 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 );
665 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
666 return newObj;
667 }
668
669 Expression *Pass1::addRetParam( ApplicationExpr *appExpr, Type *retType, std::list< Expression *>::iterator &arg ) {
670 // Create temporary to hold return value of polymorphic function and produce that temporary as a result
671 // using a comma expression.
672 assert( retType );
673
674 Expression * paramExpr = nullptr;
675 // try to use existing return value parameter if it exists, otherwise create a new temporary
676 if ( retVals.count( appExpr ) ) {
677 paramExpr = retVals[appExpr]->clone();
678 } else {
679 ObjectDecl *newObj = makeTemporary( retType->clone() );
680 paramExpr = new VariableExpr( newObj );
681 }
682 Expression * retExpr = paramExpr->clone();
683
684 // If the type of the temporary is not polymorphic, box temporary by taking its address;
685 // otherwise the temporary is already boxed and can be used directly.
686 if ( ! isPolyType( paramExpr->get_result(), scopeTyVars, env ) ) {
687 paramExpr = new AddressExpr( paramExpr );
688 } // if
689 arg = appExpr->get_args().insert( arg, paramExpr ); // add argument to function call
690 arg++;
691 // Build a comma expression to call the function and emulate a normal return.
692 CommaExpr *commaExpr = new CommaExpr( appExpr, retExpr );
693 commaExpr->set_env( appExpr->get_env() );
694 appExpr->set_env( 0 );
695 return commaExpr;
696 }
697
698 void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) {
699 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
700 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
701 assertf(paramType, "Aggregate parameters should be type expressions");
702 paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) );
703 }
704 }
705
706 Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) {
707 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
708 Type *concrete = env->lookup( typeInst->get_name() );
709 if ( concrete == 0 ) {
710 return typeInst;
711 // xxx - should this be an assertion?
712// std::string x = env ? toString( *env ) : "missing env";
713// throw SemanticError( x + "\n" + "Unbound type variable " + typeInst->get_name() + " in ", appExpr );
714 } // if
715 return concrete;
716 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
717 if ( doClone ) {
718 structType = structType->clone();
719 }
720 replaceParametersWithConcrete( appExpr, structType->get_parameters() );
721 return structType;
722 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
723 if ( doClone ) {
724 unionType = unionType->clone();
725 }
726 replaceParametersWithConcrete( appExpr, unionType->get_parameters() );
727 return unionType;
728 }
729 return type;
730 }
731
732 Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, Type *dynType, std::list< Expression *>::iterator &arg ) {
733 assert( env );
734 Type *concrete = replaceWithConcrete( appExpr, dynType );
735 // add out-parameter for return value
736 return addRetParam( appExpr, concrete, arg );
737 }
738
739 Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
740 Expression *ret = appExpr;
741// if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) {
742 if ( isDynRet( function, tyVars ) ) {
743 ret = addRetParam( appExpr, function->get_returnVals().front()->get_type(), arg );
744 } // if
745 std::string mangleName = mangleAdapterName( function, tyVars );
746 std::string adapterName = makeAdapterName( mangleName );
747
748 // cast adaptee to void (*)(), since it may have any type inside a polymorphic function
749 Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
750 appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) );
751 appExpr->set_function( new NameExpr( adapterName ) ); // xxx - result is never set on NameExpr
752
753 return ret;
754 }
755
756 void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
757 assert( arg->has_result() );
758 if ( isPolyType( param, exprTyVars ) ) {
759 if ( isPolyType( arg->get_result() ) ) {
760 // if the argument's type is polymorphic, we don't need to box again!
761 return;
762 } else if ( arg->get_result()->get_lvalue() ) { // xxx - is this still right??
763 // xxx - dynamic_cast<ReferenceType *>( arg->get_result() )??
764 // VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue)
765 // xxx - need to test that this code is still reachable
766 if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) {
767 commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) );
768 } else {
769 arg = new AddressExpr( arg );
770 }
771 if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
772 // silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
773 arg = new CastExpr( arg, param->clone() );
774 }
775 } else {
776 // use type computed in unification to declare boxed variables
777 Type * newType = param->clone();
778 if ( env ) env->apply( newType );
779 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, newType, 0 );
780 newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
781 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
782 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
783 assign->get_args().push_back( new VariableExpr( newObj ) );
784 assign->get_args().push_back( arg );
785 stmtsToAdd.push_back( new ExprStmt( noLabels, assign ) );
786 arg = new AddressExpr( new VariableExpr( newObj ) );
787 } // if
788 } // if
789 }
790
791 /// cast parameters to polymorphic functions so that types are replaced with
792 /// void * if they are type parameters in the formal type.
793 /// this gets rid of warnings from gcc.
794 void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
795 if ( getFunctionType( formal ) ) {
796 Type * newType = formal->clone();
797 newType = ScrubTyVars::scrub( newType, tyVars );
798 actual = new CastExpr( actual, newType );
799 } // if
800 }
801
802 void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
803 for ( std::list< DeclarationWithType *>::const_iterator param = function->get_parameters().begin(); param != function->get_parameters().end(); ++param, ++arg ) {
804 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() );
805 addCast( *arg, (*param)->get_type(), exprTyVars );
806 boxParam( (*param)->get_type(), *arg, exprTyVars );
807 } // for
808 }
809
810 void Pass1::addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
811 std::list< Expression *>::iterator cur = arg;
812 for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
813 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
814 InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
815 if ( inferParam == appExpr->get_inferParams().end() ) {
816 std::cerr << "looking for assertion: " << (*assert) << std::endl << appExpr << std::endl;
817 }
818 assertf( inferParam != appExpr->get_inferParams().end(), "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" );
819 Expression *newExpr = inferParam->second.expr->clone();
820 addCast( newExpr, (*assert)->get_type(), tyVars );
821 boxParam( (*assert)->get_type(), newExpr, tyVars );
822 appExpr->get_args().insert( cur, newExpr );
823 } // for
824 } // for
825 }
826
827 void makeRetParm( FunctionType *funcType ) {
828 DeclarationWithType *retParm = funcType->get_returnVals().front();
829
830 // make a new parameter that is a pointer to the type of the old return value
831 retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
832 funcType->get_parameters().push_front( retParm );
833
834 // we don't need the return value any more
835 funcType->get_returnVals().clear();
836 }
837
838 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ) {
839 // actually make the adapter type
840 FunctionType *adapter = adaptee->clone();
841// if ( ! adapter->get_returnVals().empty() && isPolyType( adapter->get_returnVals().front()->get_type(), tyVars ) ) {
842 if ( isDynRet( adapter, tyVars ) ) {
843 makeRetParm( adapter );
844 } // if
845 adapter->get_parameters().push_front( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ) );
846 return adapter;
847 }
848
849 Expression *makeAdapterArg( DeclarationWithType *param, DeclarationWithType *arg, DeclarationWithType *realParam, const TyVarMap &tyVars ) {
850 assert( param );
851 assert( arg );
852 if ( isPolyType( realParam->get_type(), tyVars ) ) {
853 if ( ! isPolyType( arg->get_type() ) ) {
854 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
855 deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
856 deref->set_result( arg->get_type()->clone() );
857 return deref;
858 } // if
859 } // if
860 return new VariableExpr( param );
861 }
862
863 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 ) {
864 UniqueName paramNamer( "_p" );
865 for ( ; param != paramEnd; ++param, ++arg, ++realParam ) {
866 if ( (*param)->get_name() == "" ) {
867 (*param)->set_name( paramNamer.newName() );
868 (*param)->set_linkage( LinkageSpec::C );
869 } // if
870 adapteeApp->get_args().push_back( makeAdapterArg( *param, *arg, *realParam, tyVars ) );
871 } // for
872 }
873
874 FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
875 FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
876 adapterType = ScrubTyVars::scrub( adapterType, tyVars );
877 DeclarationWithType *adapteeDecl = adapterType->get_parameters().front();
878 adapteeDecl->set_name( "_adaptee" );
879 ApplicationExpr *adapteeApp = new ApplicationExpr( new CastExpr( new VariableExpr( adapteeDecl ), new PointerType( Type::Qualifiers(), realType ) ) );
880 Statement *bodyStmt;
881
882 Type::ForallList::iterator tyArg = realType->get_forall().begin();
883 Type::ForallList::iterator tyParam = adapterType->get_forall().begin();
884 Type::ForallList::iterator realTyParam = adaptee->get_forall().begin();
885 for ( ; tyParam != adapterType->get_forall().end(); ++tyArg, ++tyParam, ++realTyParam ) {
886 assert( tyArg != realType->get_forall().end() );
887 std::list< DeclarationWithType *>::iterator assertArg = (*tyArg)->get_assertions().begin();
888 std::list< DeclarationWithType *>::iterator assertParam = (*tyParam)->get_assertions().begin();
889 std::list< DeclarationWithType *>::iterator realAssertParam = (*realTyParam)->get_assertions().begin();
890 for ( ; assertParam != (*tyParam)->get_assertions().end(); ++assertArg, ++assertParam, ++realAssertParam ) {
891 assert( assertArg != (*tyArg)->get_assertions().end() );
892 adapteeApp->get_args().push_back( makeAdapterArg( *assertParam, *assertArg, *realAssertParam, tyVars ) );
893 } // for
894 } // for
895
896 std::list< DeclarationWithType *>::iterator arg = realType->get_parameters().begin();
897 std::list< DeclarationWithType *>::iterator param = adapterType->get_parameters().begin();
898 std::list< DeclarationWithType *>::iterator realParam = adaptee->get_parameters().begin();
899 param++; // skip adaptee parameter in the adapter type
900 if ( realType->get_returnVals().empty() ) {
901 // void return
902 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
903 bodyStmt = new ExprStmt( noLabels, adapteeApp );
904// } else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
905 } else if ( isDynType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
906 // return type T
907 if ( (*param)->get_name() == "" ) {
908 (*param)->set_name( "_ret" );
909 (*param)->set_linkage( LinkageSpec::C );
910 } // if
911 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
912 UntypedExpr *deref = UntypedExpr::createDeref( new CastExpr( new VariableExpr( *param++ ), new PointerType( Type::Qualifiers(), realType->get_returnVals().front()->get_type()->clone() ) ) );
913 assign->get_args().push_back( deref );
914 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
915 assign->get_args().push_back( adapteeApp );
916 bodyStmt = new ExprStmt( noLabels, assign );
917 } else {
918 // adapter for a function that returns a monomorphic value
919 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
920 bodyStmt = new ReturnStmt( noLabels, adapteeApp );
921 } // if
922 CompoundStmt *adapterBody = new CompoundStmt( noLabels );
923 adapterBody->get_kids().push_back( bodyStmt );
924 std::string adapterName = makeAdapterName( mangleName );
925 return new FunctionDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, adapterType, adapterBody );
926 }
927
928 void Pass1::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
929 // collect a list of function types passed as parameters or implicit parameters (assertions)
930 std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
931 std::list< FunctionType *> functions;
932 for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
933 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
934 findFunction( (*assert)->get_type(), functions, exprTyVars, needsAdapter );
935 } // for
936 } // for
937 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
938 findFunction( (*arg)->get_type(), functions, exprTyVars, needsAdapter );
939 } // for
940
941 // parameter function types for which an appropriate adapter has been generated. we cannot use the types
942 // after applying substitutions, since two different parameter types may be unified to the same type
943 std::set< std::string > adaptersDone;
944
945 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
946 FunctionType *originalFunction = (*funType)->clone();
947 FunctionType *realFunction = (*funType)->clone();
948 std::string mangleName = SymTab::Mangler::mangle( realFunction );
949
950 // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
951 // pre-substitution parameter function type.
952 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
953 adaptersDone.insert( adaptersDone.begin(), mangleName );
954
955 // apply substitution to type variables to figure out what the adapter's type should look like
956 assert( env );
957 env->apply( realFunction );
958 mangleName = SymTab::Mangler::mangle( realFunction );
959 mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
960
961 typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
962 AdapterIter adapter = adapters.find( mangleName );
963 if ( adapter == adapters.end() ) {
964 // adapter has not been created yet in the current scope, so define it
965 FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars );
966 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
967 adapter = answer.first;
968 stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
969 } // if
970 assert( adapter != adapters.end() );
971
972 // add the appropriate adapter as a parameter
973 appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
974 } // if
975 } // for
976 } // passAdapters
977
978 Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, Type *polyType, bool isIncr ) {
979 NameExpr *opExpr;
980 if ( isIncr ) {
981 opExpr = new NameExpr( "?+=?" );
982 } else {
983 opExpr = new NameExpr( "?-=?" );
984 } // if
985 UntypedExpr *addAssign = new UntypedExpr( opExpr );
986 if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
987 addAssign->get_args().push_back( address->get_arg() );
988 } else {
989 addAssign->get_args().push_back( appExpr->get_args().front() );
990 } // if
991 addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) );
992 addAssign->set_result( appExpr->get_result()->clone() );
993 if ( appExpr->get_env() ) {
994 addAssign->set_env( appExpr->get_env() );
995 appExpr->set_env( 0 );
996 } // if
997 appExpr->get_args().clear();
998 delete appExpr;
999 return addAssign;
1000 }
1001
1002 Expression *Pass1::handleIntrinsics( ApplicationExpr *appExpr ) {
1003 if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->get_function() ) ) {
1004 if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
1005 if ( varExpr->get_var()->get_name() == "?[?]" ) {
1006 assert( appExpr->has_result() );
1007 assert( appExpr->get_args().size() == 2 );
1008 Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
1009 Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_result(), scopeTyVars, env );
1010 assert( ! baseType1 || ! baseType2 ); // the arguments cannot both be polymorphic pointers
1011 UntypedExpr *ret = 0;
1012 if ( baseType1 || baseType2 ) { // one of the arguments is a polymorphic pointer
1013 ret = new UntypedExpr( new NameExpr( "?+?" ) );
1014 } // if
1015 if ( baseType1 ) {
1016 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1017 multiply->get_args().push_back( appExpr->get_args().back() );
1018 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
1019 ret->get_args().push_back( appExpr->get_args().front() );
1020 ret->get_args().push_back( multiply );
1021 } else if ( baseType2 ) {
1022 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1023 multiply->get_args().push_back( appExpr->get_args().front() );
1024 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
1025 ret->get_args().push_back( multiply );
1026 ret->get_args().push_back( appExpr->get_args().back() );
1027 } // if
1028 if ( baseType1 || baseType2 ) {
1029 ret->set_result( appExpr->get_result()->clone() );
1030 if ( appExpr->get_env() ) {
1031 ret->set_env( appExpr->get_env() );
1032 appExpr->set_env( 0 );
1033 } // if
1034 appExpr->get_args().clear();
1035 delete appExpr;
1036 return ret;
1037 } // if
1038 } else if ( varExpr->get_var()->get_name() == "*?" ) {
1039 assert( appExpr->has_result() );
1040 assert( ! appExpr->get_args().empty() );
1041 if ( isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) { // dereference returns a reference type
1042 // remove dereference from polymorphic types since they are boxed.
1043 Expression *ret = appExpr->get_args().front();
1044 // fix expr type to remove reference
1045 delete ret->get_result();
1046 Type * baseType = InitTweak::getPointerBase( appExpr->get_result() );
1047 assert( baseType );
1048 ret->set_result( baseType->clone() );
1049 if ( appExpr->get_env() ) {
1050 ret->set_env( appExpr->get_env() );
1051 appExpr->set_env( 0 );
1052 } // if
1053 appExpr->get_args().clear();
1054 delete appExpr;
1055 return ret;
1056 } // if
1057 } else if ( varExpr->get_var()->get_name() == "?++" || varExpr->get_var()->get_name() == "?--" ) {
1058 assert( appExpr->has_result() );
1059 assert( appExpr->get_args().size() == 1 );
1060 if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
1061 Type *tempType = appExpr->get_result()->clone();
1062 if ( env ) {
1063 env->apply( tempType );
1064 } // if
1065 ObjectDecl *newObj = makeTemporary( tempType );
1066 VariableExpr *tempExpr = new VariableExpr( newObj );
1067 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
1068 assignExpr->get_args().push_back( tempExpr->clone() );
1069 if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
1070 assignExpr->get_args().push_back( address->get_arg()->clone() );
1071 } else {
1072 assignExpr->get_args().push_back( appExpr->get_args().front()->clone() );
1073 } // if
1074 CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "?++" ) );
1075 return new CommaExpr( firstComma, tempExpr );
1076 } // if
1077 } else if ( varExpr->get_var()->get_name() == "++?" || varExpr->get_var()->get_name() == "--?" ) {
1078 assert( appExpr->has_result() );
1079 assert( appExpr->get_args().size() == 1 );
1080 if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
1081 return makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "++?" );
1082 } // if
1083 } else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
1084 assert( appExpr->has_result() );
1085 assert( appExpr->get_args().size() == 2 );
1086 Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
1087 Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_result(), scopeTyVars, env );
1088 if ( baseType1 && baseType2 ) {
1089 UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
1090 divide->get_args().push_back( appExpr );
1091 divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
1092 divide->set_result( appExpr->get_result()->clone() );
1093 if ( appExpr->get_env() ) {
1094 divide->set_env( appExpr->get_env() );
1095 appExpr->set_env( 0 );
1096 } // if
1097 return divide;
1098 } else if ( baseType1 ) {
1099 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1100 multiply->get_args().push_back( appExpr->get_args().back() );
1101 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
1102 appExpr->get_args().back() = multiply;
1103 } else if ( baseType2 ) {
1104 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1105 multiply->get_args().push_back( appExpr->get_args().front() );
1106 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
1107 appExpr->get_args().front() = multiply;
1108 } // if
1109 } else if ( varExpr->get_var()->get_name() == "?+=?" || varExpr->get_var()->get_name() == "?-=?" ) {
1110 assert( appExpr->has_result() );
1111 assert( appExpr->get_args().size() == 2 );
1112 Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env );
1113 if ( baseType ) {
1114 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1115 multiply->get_args().push_back( appExpr->get_args().back() );
1116 multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) );
1117 appExpr->get_args().back() = multiply;
1118 } // if
1119 } // if
1120 return appExpr;
1121 } // if
1122 } // if
1123 return 0;
1124 }
1125
1126 Expression *Pass1::mutate( ApplicationExpr *appExpr ) {
1127 // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
1128 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
1129 // std::cerr << i->first << " ";
1130 // }
1131 // std::cerr << "\n";
1132 appExpr->get_function()->acceptMutator( *this );
1133 mutateAll( appExpr->get_args(), *this );
1134
1135 assert( appExpr->get_function()->has_result() );
1136 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
1137 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
1138
1139 if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
1140 return newExpr;
1141 } // if
1142
1143 Expression *ret = appExpr;
1144
1145 std::list< Expression *>::iterator arg = appExpr->get_args().begin();
1146 std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
1147
1148 TyVarMap exprTyVars( TypeDecl::Data{} );
1149 makeTyVarMap( function, exprTyVars ); // xxx - should this take into account the variables already bound in scopeTyVars (i.e. remove them from exprTyVars?)
1150 ReferenceToType *dynRetType = isDynRet( function, exprTyVars );
1151
1152 // std::cerr << function << std::endl;
1153 // std::cerr << "scopeTyVars: ";
1154 // printTyVarMap( std::cerr, scopeTyVars );
1155 // std::cerr << "exprTyVars: ";
1156 // printTyVarMap( std::cerr, exprTyVars );
1157 // std::cerr << "env: " << *env << std::endl;
1158 // std::cerr << needsAdapter( function, scopeTyVars ) << ! needsAdapter( function, exprTyVars) << std::endl;
1159
1160 // 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
1161 // passTypeVars needs to know the program-text return type (i.e. the distinction between _conc_T30 and T3(int))
1162 // concRetType may not be a good name in one or both of these places. A more appropriate name change is welcome.
1163 if ( dynRetType ) {
1164 // std::cerr << "dynRetType: " << dynRetType << std::endl;
1165 Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();
1166 ret = addDynRetParam( appExpr, concRetType, arg ); // xxx - used to use dynRetType instead of concRetType
1167 } else if ( needsAdapter( function, scopeTyVars ) && ! needsAdapter( function, exprTyVars) ) { // xxx - exprTyVars is used above...?
1168 // 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.
1169
1170 // std::cerr << "needs adapter: ";
1171 // printTyVarMap( std::cerr, scopeTyVars );
1172 // std::cerr << *env << std::endl;
1173 // change the application so it calls the adapter rather than the passed function
1174 ret = applyAdapter( appExpr, function, arg, scopeTyVars );
1175 } // if
1176 arg = appExpr->get_args().begin();
1177
1178 Type *concRetType = replaceWithConcrete( appExpr, dynRetType );
1179 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)
1180 addInferredParams( appExpr, function, arg, exprTyVars );
1181
1182 arg = paramBegin;
1183
1184 boxParams( appExpr, function, arg, exprTyVars );
1185 passAdapters( appExpr, function, exprTyVars );
1186
1187 return ret;
1188 }
1189
1190 Expression *Pass1::mutate( UntypedExpr *expr ) {
1191 if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
1192 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
1193 if ( name->get_name() == "*?" ) {
1194 Expression *ret = expr->get_args().front();
1195 expr->get_args().clear();
1196 delete expr;
1197 return ret->acceptMutator( *this );
1198 } // if
1199 } // if
1200 } // if
1201 return PolyMutator::mutate( expr );
1202 }
1203
1204 Expression *Pass1::mutate( AddressExpr *addrExpr ) {
1205 assert( addrExpr->get_arg()->has_result() && ! addrExpr->get_arg()->get_result()->isVoid() );
1206
1207 bool needs = false;
1208 if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->get_arg() ) ) {
1209 if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
1210 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
1211 if ( name->get_name() == "*?" ) {
1212 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
1213 assert( appExpr->get_function()->has_result() );
1214 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
1215 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
1216 needs = needsAdapter( function, scopeTyVars );
1217 } // if
1218 } // if
1219 } // if
1220 } // if
1221 } // if
1222 // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
1223 // out of the if condition.
1224 bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env );
1225 addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
1226 if ( polytype || needs ) {
1227 Expression *ret = addrExpr->get_arg();
1228 delete ret->get_result();
1229 ret->set_result( addrExpr->get_result()->clone() );
1230 addrExpr->set_arg( 0 );
1231 delete addrExpr;
1232 return ret;
1233 } else {
1234 return addrExpr;
1235 } // if
1236 }
1237
1238 Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
1239 if ( retval && returnStmt->get_expr() ) {
1240 assert( returnStmt->get_expr()->has_result() && ! returnStmt->get_expr()->get_result()->isVoid() );
1241 delete returnStmt->get_expr();
1242 returnStmt->set_expr( 0 );
1243 } else {
1244 returnStmt->set_expr( mutateExpression( returnStmt->get_expr() ) );
1245 } // if
1246 return returnStmt;
1247 }
1248
1249 Type * Pass1::mutate( PointerType *pointerType ) {
1250 scopeTyVars.beginScope();
1251 makeTyVarMap( pointerType, scopeTyVars );
1252
1253 Type *ret = Mutator::mutate( pointerType );
1254
1255 scopeTyVars.endScope();
1256 return ret;
1257 }
1258
1259 Type * Pass1::mutate( FunctionType *functionType ) {
1260 scopeTyVars.beginScope();
1261 makeTyVarMap( functionType, scopeTyVars );
1262
1263 Type *ret = Mutator::mutate( functionType );
1264
1265 scopeTyVars.endScope();
1266 return ret;
1267 }
1268
1269 void Pass1::doBeginScope() {
1270 adapters.beginScope();
1271 }
1272
1273 void Pass1::doEndScope() {
1274 adapters.endScope();
1275 }
1276
1277////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
1278
1279 void Pass2::addAdapters( FunctionType *functionType ) {
1280 std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
1281 std::list< FunctionType *> functions;
1282 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
1283 Type *orig = (*arg)->get_type();
1284 findAndReplaceFunction( orig, functions, scopeTyVars, needsAdapter );
1285 (*arg)->set_type( orig );
1286 }
1287 std::set< std::string > adaptersDone;
1288 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
1289 std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
1290 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
1291 std::string adapterName = makeAdapterName( mangleName );
1292 paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) );
1293 adaptersDone.insert( adaptersDone.begin(), mangleName );
1294 }
1295 }
1296// deleteAll( functions );
1297 }
1298
1299 template< typename DeclClass >
1300 DeclClass * Pass2::handleDecl( DeclClass *decl ) {
1301 DeclClass *ret = static_cast< DeclClass *>( Parent::mutate( decl ) );
1302
1303 return ret;
1304 }
1305
1306 /// determines if `pref` is a prefix of `str`
1307 bool isPrefix( const std::string & str, const std::string & pref ) {
1308 if ( pref.size() > str.size() ) return false;
1309 auto its = std::mismatch( pref.begin(), pref.end(), str.begin() );
1310 return its.first == pref.end();
1311 }
1312
1313 DeclarationWithType * Pass2::mutate( FunctionDecl *functionDecl ) {
1314 functionDecl = safe_dynamic_cast< FunctionDecl * > ( handleDecl( functionDecl ) );
1315 FunctionType * ftype = functionDecl->get_functionType();
1316 if ( ! ftype->get_returnVals().empty() && functionDecl->get_statements() ) {
1317 if ( ! isPrefix( functionDecl->get_name(), "_thunk" ) && ! isPrefix( functionDecl->get_name(), "_adapter" ) ) { // xxx - remove check for prefix once thunks properly use ctor/dtors
1318 assert( ftype->get_returnVals().size() == 1 );
1319 DeclarationWithType * retval = ftype->get_returnVals().front();
1320 if ( retval->get_name() == "" ) {
1321 retval->set_name( "_retval" );
1322 }
1323 functionDecl->get_statements()->get_kids().push_front( new DeclStmt( noLabels, retval ) );
1324 DeclarationWithType * newRet = retval->clone(); // for ownership purposes
1325 ftype->get_returnVals().front() = newRet;
1326 }
1327 }
1328 // errors should have been caught by this point, remove initializers from parameters to allow correct codegen of default arguments
1329 for ( Declaration * param : functionDecl->get_functionType()->get_parameters() ) {
1330 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( param ) ) {
1331 delete obj->get_init();
1332 obj->set_init( nullptr );
1333 }
1334 }
1335 return functionDecl;
1336 }
1337
1338 ObjectDecl * Pass2::mutate( ObjectDecl *objectDecl ) {
1339 return handleDecl( objectDecl );
1340 }
1341
1342 template< typename AggDecl >
1343 AggDecl * Pass2::handleAggDecl( AggDecl * aggDecl ) {
1344 // prevent tyVars from leaking into containing scope
1345 scopeTyVars.beginScope();
1346 Parent::mutate( aggDecl );
1347 scopeTyVars.endScope();
1348 return aggDecl;
1349 }
1350
1351 StructDecl * Pass2::mutate( StructDecl *aggDecl ) {
1352 return handleAggDecl( aggDecl );
1353 }
1354
1355 UnionDecl * Pass2::mutate( UnionDecl *aggDecl ) {
1356 return handleAggDecl( aggDecl );
1357 }
1358
1359 TypeDecl * Pass2::mutate( TypeDecl *typeDecl ) {
1360 addToTyVarMap( typeDecl, scopeTyVars );
1361 if ( typeDecl->get_base() ) {
1362 return handleDecl( typeDecl );
1363 } else {
1364 return Parent::mutate( typeDecl );
1365 }
1366 }
1367
1368 TypedefDecl * Pass2::mutate( TypedefDecl *typedefDecl ) {
1369 return handleDecl( typedefDecl );
1370 }
1371
1372 Type * Pass2::mutate( PointerType *pointerType ) {
1373 scopeTyVars.beginScope();
1374 makeTyVarMap( pointerType, scopeTyVars );
1375
1376 Type *ret = Parent::mutate( pointerType );
1377
1378 scopeTyVars.endScope();
1379 return ret;
1380 }
1381
1382 Type *Pass2::mutate( FunctionType *funcType ) {
1383 scopeTyVars.beginScope();
1384 makeTyVarMap( funcType, scopeTyVars );
1385
1386 // move polymorphic return type to parameter list
1387 if ( isDynRet( funcType ) ) {
1388 ObjectDecl *ret = safe_dynamic_cast< ObjectDecl* >( funcType->get_returnVals().front() );
1389 ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
1390 funcType->get_parameters().push_front( ret );
1391 funcType->get_returnVals().pop_front();
1392 ret->set_init( nullptr ); // xxx - memory leak?
1393 }
1394
1395 // add size/align and assertions for type parameters to parameter list
1396 std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
1397 std::list< DeclarationWithType *> inferredParams;
1398 ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 );
1399 ObjectDecl newPtr( "", Type::StorageClasses(), LinkageSpec::C, 0,
1400 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
1401 for ( Type::ForallList::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
1402 ObjectDecl *sizeParm, *alignParm;
1403 // add all size and alignment parameters to parameter list
1404 if ( (*tyParm)->isComplete() ) {
1405 TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm );
1406 std::string parmName = mangleType( &parmType );
1407
1408 sizeParm = newObj.clone();
1409 sizeParm->set_name( sizeofName( parmName ) );
1410 last = funcType->get_parameters().insert( last, sizeParm );
1411 ++last;
1412
1413 alignParm = newObj.clone();
1414 alignParm->set_name( alignofName( parmName ) );
1415 last = funcType->get_parameters().insert( last, alignParm );
1416 ++last;
1417 }
1418 // move all assertions into parameter list
1419 for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
1420// *assert = (*assert)->acceptMutator( *this );
1421 inferredParams.push_back( *assert );
1422 }
1423 (*tyParm)->get_assertions().clear();
1424 }
1425
1426 // add size/align for generic parameter types to parameter list
1427 std::set< std::string > seenTypes; // sizeofName for generic types we've seen
1428 for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
1429 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
1430 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
1431 std::string typeName = mangleType( polyType );
1432 if ( seenTypes.count( typeName ) ) continue;
1433
1434 ObjectDecl *sizeParm, *alignParm, *offsetParm;
1435 sizeParm = newObj.clone();
1436 sizeParm->set_name( sizeofName( typeName ) );
1437 last = funcType->get_parameters().insert( last, sizeParm );
1438 ++last;
1439
1440 alignParm = newObj.clone();
1441 alignParm->set_name( alignofName( typeName ) );
1442 last = funcType->get_parameters().insert( last, alignParm );
1443 ++last;
1444
1445 if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyType ) ) {
1446 // NOTE zero-length arrays are illegal in C, so empty structs have no offset array
1447 if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) {
1448 offsetParm = newPtr.clone();
1449 offsetParm->set_name( offsetofName( typeName ) );
1450 last = funcType->get_parameters().insert( last, offsetParm );
1451 ++last;
1452 }
1453 }
1454
1455 seenTypes.insert( typeName );
1456 }
1457 }
1458
1459 // splice assertion parameters into parameter list
1460 funcType->get_parameters().splice( last, inferredParams );
1461 addAdapters( funcType );
1462 mutateAll( funcType->get_returnVals(), *this );
1463 mutateAll( funcType->get_parameters(), *this );
1464
1465 scopeTyVars.endScope();
1466 return funcType;
1467 }
1468
1469////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////////////////////////
1470
1471 PolyGenericCalculator::PolyGenericCalculator()
1472 : Parent(), knownLayouts(), knownOffsets(), bufNamer( "_buf" ) {}
1473
1474 void PolyGenericCalculator::beginTypeScope( Type *ty ) {
1475 scopeTyVars.beginScope();
1476 makeTyVarMap( ty, scopeTyVars );
1477 }
1478
1479 void PolyGenericCalculator::endTypeScope() {
1480 scopeTyVars.endScope();
1481 }
1482
1483 template< typename DeclClass >
1484 DeclClass * PolyGenericCalculator::handleDecl( DeclClass *decl, Type *type ) {
1485 beginTypeScope( type );
1486 // knownLayouts.beginScope();
1487 // knownOffsets.beginScope();
1488
1489 DeclClass *ret = static_cast< DeclClass *>( Parent::mutate( decl ) );
1490
1491 // knownOffsets.endScope();
1492 // knownLayouts.endScope();
1493 endTypeScope();
1494 return ret;
1495 }
1496
1497 ObjectDecl * PolyGenericCalculator::mutate( ObjectDecl *objectDecl ) {
1498 return handleDecl( objectDecl, objectDecl->get_type() );
1499 }
1500
1501 DeclarationWithType * PolyGenericCalculator::mutate( FunctionDecl *functionDecl ) {
1502 knownLayouts.beginScope();
1503 knownOffsets.beginScope();
1504
1505 DeclarationWithType * decl = handleDecl( functionDecl, functionDecl->get_functionType() );
1506 knownOffsets.endScope();
1507 knownLayouts.endScope();
1508 return decl;
1509 }
1510
1511 TypedefDecl * PolyGenericCalculator::mutate( TypedefDecl *typedefDecl ) {
1512 return handleDecl( typedefDecl, typedefDecl->get_base() );
1513 }
1514
1515 TypeDecl * PolyGenericCalculator::mutate( TypeDecl *typeDecl ) {
1516 addToTyVarMap( typeDecl, scopeTyVars );
1517 return Parent::mutate( typeDecl );
1518 }
1519
1520 Type * PolyGenericCalculator::mutate( PointerType *pointerType ) {
1521 beginTypeScope( pointerType );
1522
1523 Type *ret = Parent::mutate( pointerType );
1524
1525 endTypeScope();
1526 return ret;
1527 }
1528
1529 Type * PolyGenericCalculator::mutate( FunctionType *funcType ) {
1530 beginTypeScope( funcType );
1531
1532 // make sure that any type information passed into the function is accounted for
1533 for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) {
1534 // condition here duplicates that in Pass2::mutate( FunctionType* )
1535 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
1536 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
1537 knownLayouts.insert( mangleType( polyType ) );
1538 }
1539 }
1540
1541 Type *ret = Parent::mutate( funcType );
1542
1543 endTypeScope();
1544 return ret;
1545 }
1546
1547 Statement *PolyGenericCalculator::mutate( DeclStmt *declStmt ) {
1548 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
1549 if ( findGeneric( objectDecl->get_type() ) ) {
1550 // change initialization of a polymorphic value object to allocate via a VLA
1551 // (alloca was previously used, but can't be safely used in loops)
1552 Type *declType = objectDecl->get_type();
1553 std::string bufName = bufNamer.newName();
1554 ObjectDecl *newBuf = new ObjectDecl( bufName, Type::StorageClasses(), LinkageSpec::C, 0,
1555 new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::Kind::Char), new NameExpr( sizeofName( mangleType(declType) ) ),
1556 true, false, std::list<Attribute*>{ new Attribute( std::string{"aligned"}, std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } ) } ), 0 );
1557 stmtsToAdd.push_back( new DeclStmt( noLabels, newBuf ) );
1558
1559 delete objectDecl->get_init();
1560
1561 objectDecl->set_init( new SingleInit( new NameExpr( bufName ) ) );
1562 }
1563 }
1564 return Parent::mutate( declStmt );
1565 }
1566
1567 /// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
1568 long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
1569 long i = 0;
1570 for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) {
1571 if ( memberDecl->get_name() != (*decl)->get_name() ) continue;
1572
1573 if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
1574 if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty()
1575 || memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
1576 else continue;
1577 } else return i;
1578 }
1579 return -1;
1580 }
1581
1582 /// Returns an index expression into the offset array for a type
1583 Expression *makeOffsetIndex( Type *objectType, long i ) {
1584 ConstantExpr *fieldIndex = new ConstantExpr( Constant::from_ulong( i ) );
1585 UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
1586 fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType ) ) ) );
1587 fieldOffset->get_args().push_back( fieldIndex );
1588 return fieldOffset;
1589 }
1590
1591 Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) {
1592 // mutate, exiting early if no longer MemberExpr
1593 Expression *expr = Parent::mutate( memberExpr );
1594 memberExpr = dynamic_cast< MemberExpr* >( expr );
1595 if ( ! memberExpr ) return expr;
1596
1597 // only mutate member expressions for polymorphic types
1598 int tyDepth;
1599 Type *objectType = hasPolyBase( memberExpr->get_aggregate()->get_result(), scopeTyVars, &tyDepth );
1600 if ( ! objectType ) return memberExpr;
1601 findGeneric( objectType ); // ensure layout for this type is available
1602
1603 // replace member expression with dynamically-computed layout expression
1604 Expression *newMemberExpr = 0;
1605 if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
1606 // look up offset index
1607 long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() );
1608 if ( i == -1 ) return memberExpr;
1609
1610 // replace member expression with pointer to base plus offset
1611 UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
1612 Expression * aggr = memberExpr->get_aggregate()->clone();
1613 delete aggr->get_env(); // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
1614 aggr->set_env( nullptr );
1615 fieldLoc->get_args().push_back( aggr );
1616 fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
1617 fieldLoc->set_result( memberExpr->get_result()->clone() );
1618 newMemberExpr = fieldLoc;
1619 } else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
1620 // union members are all at offset zero, so just use the aggregate expr
1621 Expression * aggr = memberExpr->get_aggregate()->clone();
1622 delete aggr->get_env(); // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
1623 aggr->set_env( nullptr );
1624 newMemberExpr = aggr;
1625 newMemberExpr->set_result( memberExpr->get_result()->clone() );
1626 } else return memberExpr;
1627 assert( newMemberExpr );
1628
1629 Type *memberType = memberExpr->get_member()->get_type();
1630 if ( ! isPolyType( memberType, scopeTyVars ) ) {
1631 // 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
1632 CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) );
1633 UntypedExpr *derefExpr = UntypedExpr::createDeref( ptrCastExpr );
1634 newMemberExpr = derefExpr;
1635 }
1636
1637 delete memberExpr;
1638 return newMemberExpr;
1639 }
1640
1641 ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
1642 ObjectDecl *newObj = new ObjectDecl( name, Type::StorageClasses(), LinkageSpec::C, 0, type, init );
1643 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
1644 return newObj;
1645 }
1646
1647 void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
1648 for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
1649 if ( findGeneric( *param ) ) {
1650 // push size/align vars for a generic parameter back
1651 std::string paramName = mangleType( *param );
1652 layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) );
1653 layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) );
1654 } else {
1655 layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
1656 layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
1657 }
1658 }
1659 }
1660
1661 /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
1662 bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
1663 bool hasDynamicLayout = false;
1664
1665 std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
1666 std::list< Expression* >::const_iterator typeParam = typeParams.begin();
1667 for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
1668 // skip non-otype parameters
1669 if ( ! (*baseParam)->isComplete() ) continue;
1670 TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
1671 assert( typeExpr && "all otype parameters should be type expressions" );
1672
1673 Type *type = typeExpr->get_type();
1674 out.push_back( type );
1675 if ( isPolyType( type ) ) hasDynamicLayout = true;
1676 }
1677 assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
1678
1679 return hasDynamicLayout;
1680 }
1681
1682 bool PolyGenericCalculator::findGeneric( Type *ty ) {
1683 ty = replaceTypeInst( ty, env );
1684
1685 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
1686 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
1687 // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
1688 return true;
1689 }
1690 return false;
1691 } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
1692 // check if this type already has a layout generated for it
1693 std::string typeName = mangleType( ty );
1694 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
1695
1696 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
1697 std::list< Type* > otypeParams;
1698 if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
1699
1700 // insert local variables for layout and generate call to layout function
1701 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call
1702 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1703
1704 int n_members = structTy->get_baseStruct()->get_members().size();
1705 if ( n_members == 0 ) {
1706 // all empty structs have the same layout - size 1, align 1
1707 makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
1708 makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
1709 // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
1710 } else {
1711 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
1712 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
1713 ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from_int( n_members ) ), false, false ) );
1714
1715 // generate call to layout function
1716 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( structTy->get_baseStruct() ) ) );
1717 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
1718 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
1719 layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
1720 addOtypeParamsToLayoutCall( layoutCall, otypeParams );
1721
1722 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
1723 }
1724
1725 return true;
1726 } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
1727 // check if this type already has a layout generated for it
1728 std::string typeName = mangleType( ty );
1729 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
1730
1731 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
1732 std::list< Type* > otypeParams;
1733 if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
1734
1735 // insert local variables for layout and generate call to layout function
1736 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call
1737 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1738
1739 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
1740 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
1741
1742 // generate call to layout function
1743 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( unionTy->get_baseUnion() ) ) );
1744 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
1745 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
1746 addOtypeParamsToLayoutCall( layoutCall, otypeParams );
1747
1748 stmtsToAdd.push_back( new ExprStmt( noLabels, layoutCall ) );
1749
1750 return true;
1751 }
1752
1753 return false;
1754 }
1755
1756 Expression *PolyGenericCalculator::mutate( SizeofExpr *sizeofExpr ) {
1757 Type *ty = sizeofExpr->get_type();
1758 if ( findGeneric( ty ) ) {
1759 Expression *ret = new NameExpr( sizeofName( mangleType( ty ) ) );
1760 delete sizeofExpr;
1761 return ret;
1762 }
1763 return sizeofExpr;
1764 }
1765
1766 Expression *PolyGenericCalculator::mutate( AlignofExpr *alignofExpr ) {
1767 Type *ty = alignofExpr->get_type();
1768 if ( findGeneric( ty ) ) {
1769 Expression *ret = new NameExpr( alignofName( mangleType( ty ) ) );
1770 delete alignofExpr;
1771 return ret;
1772 }
1773 return alignofExpr;
1774 }
1775
1776 Expression *PolyGenericCalculator::mutate( OffsetofExpr *offsetofExpr ) {
1777 // mutate, exiting early if no longer OffsetofExpr
1778 Expression *expr = Parent::mutate( offsetofExpr );
1779 offsetofExpr = dynamic_cast< OffsetofExpr* >( expr );
1780 if ( ! offsetofExpr ) return expr;
1781
1782 // only mutate expressions for polymorphic structs/unions
1783 Type *ty = offsetofExpr->get_type();
1784 if ( ! findGeneric( ty ) ) return offsetofExpr;
1785
1786 if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
1787 // replace offsetof expression by index into offset array
1788 long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() );
1789 if ( i == -1 ) return offsetofExpr;
1790
1791 Expression *offsetInd = makeOffsetIndex( ty, i );
1792 delete offsetofExpr;
1793 return offsetInd;
1794 } else if ( dynamic_cast< UnionInstType* >( ty ) ) {
1795 // all union members are at offset zero
1796 delete offsetofExpr;
1797 return new ConstantExpr( Constant::from_ulong( 0 ) );
1798 } else return offsetofExpr;
1799 }
1800
1801 Expression *PolyGenericCalculator::mutate( OffsetPackExpr *offsetPackExpr ) {
1802 StructInstType *ty = offsetPackExpr->get_type();
1803
1804 Expression *ret = 0;
1805 if ( findGeneric( ty ) ) {
1806 // pull offset back from generated type information
1807 ret = new NameExpr( offsetofName( mangleType( ty ) ) );
1808 } else {
1809 std::string offsetName = offsetofName( mangleType( ty ) );
1810 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
1811 // use the already-generated offsets for this type
1812 ret = new NameExpr( offsetName );
1813 } else {
1814 knownOffsets.insert( offsetName );
1815
1816 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
1817 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1818
1819 // build initializer list for offset array
1820 std::list< Initializer* > inits;
1821 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
1822 if ( DeclarationWithType *memberDecl = dynamic_cast< DeclarationWithType* >( *member ) ) {
1823 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
1824 } else {
1825 assertf( false, "Requesting offset of Non-DWT member: %s", toString( *member ).c_str() );
1826 }
1827 }
1828
1829 // build the offset array and replace the pack with a reference to it
1830 ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from_ulong( baseMembers.size() ) ), false, false ),
1831 new ListInit( inits ) );
1832 ret = new VariableExpr( offsetArray );
1833 }
1834 }
1835
1836 delete offsetPackExpr;
1837 return ret;
1838 }
1839
1840 void PolyGenericCalculator::doBeginScope() {
1841 knownLayouts.beginScope();
1842 knownOffsets.beginScope();
1843 }
1844
1845 void PolyGenericCalculator::doEndScope() {
1846 knownLayouts.endScope();
1847 knownOffsets.endScope();
1848 }
1849
1850////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
1851
1852 template< typename DeclClass >
1853 DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
1854 scopeTyVars.beginScope();
1855 makeTyVarMap( type, scopeTyVars );
1856
1857 DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
1858 // ScrubTyVars::scrub( decl, scopeTyVars );
1859 ScrubTyVars::scrubAll( decl );
1860
1861 scopeTyVars.endScope();
1862 return ret;
1863 }
1864
1865 ObjectDecl * Pass3::mutate( ObjectDecl *objectDecl ) {
1866 return handleDecl( objectDecl, objectDecl->get_type() );
1867 }
1868
1869 DeclarationWithType * Pass3::mutate( FunctionDecl *functionDecl ) {
1870 return handleDecl( functionDecl, functionDecl->get_functionType() );
1871 }
1872
1873 TypedefDecl * Pass3::mutate( TypedefDecl *typedefDecl ) {
1874 return handleDecl( typedefDecl, typedefDecl->get_base() );
1875 }
1876
1877 TypeDecl * Pass3::mutate( TypeDecl *typeDecl ) {
1878// Initializer *init = 0;
1879// std::list< Expression *> designators;
1880// addToTyVarMap( typeDecl, scopeTyVars );
1881// if ( typeDecl->get_base() ) {
1882// init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators );
1883// }
1884// return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init );
1885
1886 addToTyVarMap( typeDecl, scopeTyVars );
1887 return Mutator::mutate( typeDecl );
1888 }
1889
1890 Type * Pass3::mutate( PointerType *pointerType ) {
1891 scopeTyVars.beginScope();
1892 makeTyVarMap( pointerType, scopeTyVars );
1893
1894 Type *ret = Mutator::mutate( pointerType );
1895
1896 scopeTyVars.endScope();
1897 return ret;
1898 }
1899
1900 Type * Pass3::mutate( FunctionType *functionType ) {
1901 scopeTyVars.beginScope();
1902 makeTyVarMap( functionType, scopeTyVars );
1903
1904 Type *ret = Mutator::mutate( functionType );
1905
1906 scopeTyVars.endScope();
1907 return ret;
1908 }
1909 } // anonymous namespace
1910} // namespace GenPoly
1911
1912// Local Variables: //
1913// tab-width: 4 //
1914// mode: c++ //
1915// compile-command: "make install" //
1916// End: //
Note: See TracBrowser for help on using the repository browser.