source: src/GenPoly/Box.cc@ 184557e

new-env
Last change on this file since 184557e was 982f95d, checked in by Aaron Moss <a3moss@…>, 7 years ago

Start of new environment implementation; terribly broken

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