source: src/GenPoly/Box.cc@ 92b3de1

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 92b3de1 was b4bfa0a, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Convert LayoutFunctionBuilder to PassVisitor

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