source: src/GenPoly/Box.cc@ 1ed958c3

new-env with_gc
Last change on this file since 1ed958c3 was 1cdfa82, checked in by Aaron Moss <a3moss@…>, 7 years ago

Merge remote-tracking branch 'origin/master' into with_gc

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