source: src/GenPoly/Box.cc@ 907eccb

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 907eccb was b940dc71, checked in by Rob Schluntz <rschlunt@…>, 9 years ago

replace type variables in InstantiateGeneric, fix call passTypeVars so that the correct type is passed

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