source: src/GenPoly/Box.cc@ b3212de

ADT ast-experimental stuck-waitfor-destruct
Last change on this file since b3212de was b3212de, checked in by Andrew Beach <ajbeach@…>, 4 years ago

Cleaning old box pass for easier translation. Scattered simplifications, note the moved boxParam method has one new line in it near the beginning.

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