source: src/GenPoly/Box.cc@ 994028dc

ADT ast-experimental
Last change on this file since 994028dc was 994028dc, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Cleaning old box pass for easier translation. Clean-up more loops.

  • Property mode set to 100644
File size: 87.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 : 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 void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
679 assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
680 if ( ! needsBoxing( param, arg->result, exprTyVars, env ) ) return;
681
682 if ( arg->get_lvalue() ) {
683 // argument expression may be CFA lvalue, but not C lvalue -- apply generalizedLvalue transformations.
684 // if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( arg ) ) {
685 // if ( dynamic_cast<ArrayType *>( varExpr->var->get_type() ) ){
686 // // temporary hack - don't box arrays, because &arr is not the same as &arr[0]
687 // return;
688 // }
689 // }
690 arg = generalizedLvalue( new AddressExpr( arg ) );
691 if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
692 // silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
693 arg = new CastExpr( arg, param->clone() );
694 }
695 } else {
696 // use type computed in unification to declare boxed variables
697 Type * newType = param->clone();
698 if ( env ) env->apply( newType );
699 ObjectDecl *newObj = ObjectDecl::newObject( tempNamer.newName(), newType, nullptr );
700 newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
701 stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
702 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
703 assign->get_args().push_back( new VariableExpr( newObj ) );
704 assign->get_args().push_back( arg );
705 stmtsToAddBefore.push_back( new ExprStmt( assign ) );
706 arg = new AddressExpr( new VariableExpr( newObj ) );
707 } // if
708 }
709
710 // find instances of polymorphic type parameters
711 struct PolyFinder {
712 const TyVarMap * tyVars = nullptr;
713 bool found = false;
714
715 void previsit( TypeInstType * t ) {
716 if ( isPolyType( t, *tyVars ) ) {
717 found = true;
718 }
719 }
720 };
721
722 // true if there is an instance of a polymorphic type parameter in t
723 bool hasPolymorphism( Type * t, const TyVarMap &tyVars ) {
724 PassVisitor<PolyFinder> finder;
725 finder.pass.tyVars = &tyVars;
726 maybeAccept( t, finder );
727 return finder.pass.found;
728 }
729
730 /// cast parameters to polymorphic functions so that types are replaced with
731 /// void * if they are type parameters in the formal type.
732 /// this gets rid of warnings from gcc.
733 void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
734 // type contains polymorphism, but isn't exactly a polytype, in which case it
735 // has some real actual type (e.g. unsigned int) and casting to void * is wrong
736 if ( hasPolymorphism( formal, tyVars ) && ! isPolyType( formal, tyVars ) ) {
737 Type * newType = formal->clone();
738 newType = ScrubTyVars::scrub( newType, tyVars );
739 actual = new CastExpr( actual, newType );
740 } // if
741 }
742
743 void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
744 for ( DeclarationWithType * param : function->parameters ) {
745 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() );
746 addCast( *arg, param->get_type(), exprTyVars );
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 addCast( newExpr, assert->get_type(), tyVars );
760 boxParam( assert->get_type(), newExpr, tyVars );
761 appExpr->get_args().insert( cur, newExpr );
762 } // for
763 } // for
764 }
765
766 void makeRetParm( FunctionType *funcType ) {
767 DeclarationWithType *retParm = funcType->returnVals.front();
768
769 // make a new parameter that is a pointer to the type of the old return value
770 retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
771 funcType->get_parameters().push_front( retParm );
772
773 // we don't need the return value any more
774 funcType->get_returnVals().clear();
775 }
776
777 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ) {
778 // actually make the adapter type
779 FunctionType *adapter = adaptee->clone();
780 if ( isDynRet( adapter, tyVars ) ) {
781 makeRetParm( adapter );
782 } // if
783 adapter->get_parameters().push_front( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ) );
784 return adapter;
785 }
786
787 Expression *makeAdapterArg( DeclarationWithType *param, DeclarationWithType *arg, DeclarationWithType *realParam, const TyVarMap &tyVars ) {
788 assert( param );
789 assert( arg );
790 if ( isPolyType( realParam->get_type(), tyVars ) ) {
791 if ( ! isPolyType( arg->get_type() ) ) {
792 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
793 deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
794 deref->result = arg->get_type()->clone();
795 return deref;
796 } // if
797 } // if
798 return new VariableExpr( param );
799 }
800
801 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 ) {
802 UniqueName paramNamer( "_p" );
803 for ( ; param != paramEnd; ++param, ++arg, ++realParam ) {
804 if ( (*param)->get_name() == "" ) {
805 (*param)->set_name( paramNamer.newName() );
806 (*param)->set_linkage( LinkageSpec::C );
807 } // if
808 adapteeApp->get_args().push_back( makeAdapterArg( *param, *arg, *realParam, tyVars ) );
809 } // for
810 }
811
812 FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
813 FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
814 adapterType = ScrubTyVars::scrub( adapterType, tyVars );
815 DeclarationWithType *adapteeDecl = adapterType->get_parameters().front();
816 adapteeDecl->set_name( "_adaptee" );
817 // do not carry over attributes to real type parameters/return values
818 for ( DeclarationWithType * dwt : realType->parameters ) {
819 deleteAll( dwt->get_type()->attributes );
820 dwt->get_type()->attributes.clear();
821 }
822 for ( DeclarationWithType * dwt : realType->returnVals ) {
823 deleteAll( dwt->get_type()->attributes );
824 dwt->get_type()->attributes.clear();
825 }
826 ApplicationExpr *adapteeApp = new ApplicationExpr( new CastExpr( new VariableExpr( adapteeDecl ), new PointerType( Type::Qualifiers(), realType ) ) );
827 Statement *bodyStmt;
828
829 Type::ForallList::iterator tyArg = realType->get_forall().begin();
830 Type::ForallList::iterator tyParam = adapterType->get_forall().begin();
831 Type::ForallList::iterator realTyParam = adaptee->get_forall().begin();
832 for ( ; tyParam != adapterType->get_forall().end(); ++tyArg, ++tyParam, ++realTyParam ) {
833 assert( tyArg != realType->get_forall().end() );
834 std::list< DeclarationWithType *>::iterator assertArg = (*tyArg)->get_assertions().begin();
835 std::list< DeclarationWithType *>::iterator assertParam = (*tyParam)->get_assertions().begin();
836 std::list< DeclarationWithType *>::iterator realAssertParam = (*realTyParam)->get_assertions().begin();
837 for ( ; assertParam != (*tyParam)->get_assertions().end(); ++assertArg, ++assertParam, ++realAssertParam ) {
838 assert( assertArg != (*tyArg)->get_assertions().end() );
839 adapteeApp->get_args().push_back( makeAdapterArg( *assertParam, *assertArg, *realAssertParam, tyVars ) );
840 } // for
841 } // for
842
843 std::list< DeclarationWithType *>::iterator arg = realType->get_parameters().begin();
844 std::list< DeclarationWithType *>::iterator param = adapterType->get_parameters().begin();
845 std::list< DeclarationWithType *>::iterator realParam = adaptee->get_parameters().begin();
846 param++; // skip adaptee parameter in the adapter type
847 if ( realType->get_returnVals().empty() ) {
848 // void return
849 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
850 bodyStmt = new ExprStmt( adapteeApp );
851 } else if ( isDynType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
852 // return type T
853 if ( (*param)->get_name() == "" ) {
854 (*param)->set_name( "_ret" );
855 (*param)->set_linkage( LinkageSpec::C );
856 } // if
857 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
858 UntypedExpr *deref = UntypedExpr::createDeref( new CastExpr( new VariableExpr( *param++ ), new PointerType( Type::Qualifiers(), realType->get_returnVals().front()->get_type()->clone() ) ) );
859 assign->get_args().push_back( deref );
860 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
861 assign->get_args().push_back( adapteeApp );
862 bodyStmt = new ExprStmt( assign );
863 } else {
864 // adapter for a function that returns a monomorphic value
865 addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
866 bodyStmt = new ReturnStmt( adapteeApp );
867 } // if
868 CompoundStmt *adapterBody = new CompoundStmt();
869 adapterBody->get_kids().push_back( bodyStmt );
870 std::string adapterName = makeAdapterName( mangleName );
871 return new FunctionDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, adapterType, adapterBody );
872 }
873
874 void Pass1::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
875 // collect a list of function types passed as parameters or implicit parameters (assertions)
876 std::list< FunctionType*> functions;
877 for ( TypeDecl * const tyVar : functionType->get_forall() ) {
878 for ( DeclarationWithType * const assert : tyVar->get_assertions() ) {
879 findFunction( assert->get_type(), functions, exprTyVars, needsAdapter );
880 } // for
881 } // for
882 for ( DeclarationWithType * const arg : functionType->get_parameters() ) {
883 findFunction( arg->get_type(), functions, exprTyVars, needsAdapter );
884 } // for
885
886 // parameter function types for which an appropriate adapter has been generated. we cannot use the types
887 // after applying substitutions, since two different parameter types may be unified to the same type
888 std::set< std::string > adaptersDone;
889
890 for ( FunctionType * const funType : functions ) {
891 FunctionType *originalFunction = funType->clone();
892 FunctionType *realFunction = funType->clone();
893 std::string mangleName = SymTab::Mangler::mangle( realFunction );
894
895 // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
896 // pre-substitution parameter function type.
897 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
898 adaptersDone.insert( adaptersDone.begin(), mangleName );
899
900 // apply substitution to type variables to figure out what the adapter's type should look like
901 assert( env );
902 env->apply( realFunction );
903 mangleName = SymTab::Mangler::mangle( realFunction );
904 mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
905
906 typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
907 AdapterIter adapter = adapters.find( mangleName );
908 if ( adapter == adapters.end() ) {
909 // adapter has not been created yet in the current scope, so define it
910 FunctionDecl *newAdapter = makeAdapter( funType, realFunction, mangleName, exprTyVars );
911 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
912 adapter = answer.first;
913 stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
914 } // if
915 assert( adapter != adapters.end() );
916
917 // add the appropriate adapter as a parameter
918 appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
919 } // if
920 } // for
921 } // passAdapters
922
923 Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, Type *polyType, bool isIncr ) {
924 NameExpr *opExpr;
925 if ( isIncr ) {
926 opExpr = new NameExpr( "?+=?" );
927 } else {
928 opExpr = new NameExpr( "?-=?" );
929 } // if
930 UntypedExpr *addAssign = new UntypedExpr( opExpr );
931 if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
932 addAssign->get_args().push_back( address->get_arg() );
933 } else {
934 addAssign->get_args().push_back( appExpr->get_args().front() );
935 } // if
936 addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) );
937 addAssign->set_result( appExpr->get_result()->clone() );
938 if ( appExpr->get_env() ) {
939 addAssign->set_env( appExpr->get_env() );
940 appExpr->set_env( 0 );
941 } // if
942 appExpr->get_args().clear();
943 delete appExpr;
944 return addAssign;
945 }
946
947 Expression *Pass1::handleIntrinsics( ApplicationExpr *appExpr ) {
948 if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->function ) ) {
949 if ( varExpr->var->linkage == LinkageSpec::Intrinsic ) {
950 if ( varExpr->var->name == "?[?]" ) {
951 assert( appExpr->result );
952 assert( appExpr->get_args().size() == 2 );
953 Type *baseType1 = isPolyPtr( appExpr->args.front()->result, scopeTyVars, env );
954 Type *baseType2 = isPolyPtr( appExpr->args.back()->result, scopeTyVars, env );
955 assert( ! baseType1 || ! baseType2 ); // the arguments cannot both be polymorphic pointers
956 UntypedExpr *ret = 0;
957 if ( baseType1 || baseType2 ) { // one of the arguments is a polymorphic pointer
958 ret = new UntypedExpr( new NameExpr( "?+?" ) );
959 } // if
960 if ( baseType1 ) {
961 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
962 multiply->get_args().push_back( appExpr->get_args().back() );
963 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
964 ret->get_args().push_back( appExpr->get_args().front() );
965 ret->get_args().push_back( multiply );
966 } else if ( baseType2 ) {
967 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
968 multiply->get_args().push_back( appExpr->get_args().front() );
969 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
970 ret->get_args().push_back( multiply );
971 ret->get_args().push_back( appExpr->get_args().back() );
972 } // if
973 if ( baseType1 || baseType2 ) {
974 delete ret->get_result();
975 ret->set_result( appExpr->get_result()->clone() );
976 if ( appExpr->get_env() ) {
977 ret->set_env( appExpr->get_env() );
978 appExpr->set_env( 0 );
979 } // if
980 appExpr->get_args().clear();
981 delete appExpr;
982 return ret;
983 } // if
984 } else if ( varExpr->get_var()->get_name() == "*?" ) {
985 assert( appExpr->result );
986 assert( ! appExpr->get_args().empty() );
987 if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) {
988 // remove dereference from polymorphic types since they are boxed.
989 Expression *ret = appExpr->get_args().front();
990 // fix expr type to remove pointer
991 delete ret->get_result();
992 ret->set_result( appExpr->get_result()->clone() );
993 if ( appExpr->get_env() ) {
994 ret->set_env( appExpr->get_env() );
995 appExpr->set_env( 0 );
996 } // if
997 appExpr->get_args().clear();
998 delete appExpr;
999 return ret;
1000 } // if
1001 } else if ( varExpr->get_var()->get_name() == "?++" || varExpr->get_var()->get_name() == "?--" ) {
1002 assert( appExpr->result );
1003 assert( appExpr->get_args().size() == 1 );
1004 if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
1005 Type *tempType = appExpr->get_result()->clone();
1006 if ( env ) {
1007 env->apply( tempType );
1008 } // if
1009 ObjectDecl *newObj = makeTemporary( tempType );
1010 VariableExpr *tempExpr = new VariableExpr( newObj );
1011 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
1012 assignExpr->get_args().push_back( tempExpr->clone() );
1013 if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
1014 assignExpr->get_args().push_back( address->get_arg()->clone() );
1015 } else {
1016 assignExpr->get_args().push_back( appExpr->get_args().front()->clone() );
1017 } // if
1018 CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "?++" ) );
1019 return new CommaExpr( firstComma, tempExpr );
1020 } // if
1021 } else if ( varExpr->get_var()->get_name() == "++?" || varExpr->get_var()->get_name() == "--?" ) {
1022 assert( appExpr->result );
1023 assert( appExpr->get_args().size() == 1 );
1024 if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
1025 return makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "++?" );
1026 } // if
1027 } else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
1028 assert( appExpr->result );
1029 assert( appExpr->get_args().size() == 2 );
1030 Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
1031 Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_result(), scopeTyVars, env );
1032 if ( baseType1 && baseType2 ) {
1033 UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
1034 divide->get_args().push_back( appExpr );
1035 divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
1036 divide->set_result( appExpr->get_result()->clone() );
1037 if ( appExpr->get_env() ) {
1038 divide->set_env( appExpr->get_env() );
1039 appExpr->set_env( 0 );
1040 } // if
1041 return divide;
1042 } else if ( baseType1 ) {
1043 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1044 multiply->get_args().push_back( appExpr->get_args().back() );
1045 multiply->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
1046 appExpr->get_args().back() = multiply;
1047 } else if ( baseType2 ) {
1048 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1049 multiply->get_args().push_back( appExpr->get_args().front() );
1050 multiply->get_args().push_back( new SizeofExpr( baseType2->clone() ) );
1051 appExpr->get_args().front() = multiply;
1052 } // if
1053 } else if ( varExpr->get_var()->get_name() == "?+=?" || varExpr->get_var()->get_name() == "?-=?" ) {
1054 assert( appExpr->result );
1055 assert( appExpr->get_args().size() == 2 );
1056 Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env );
1057 if ( baseType ) {
1058 UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1059 multiply->get_args().push_back( appExpr->get_args().back() );
1060 multiply->get_args().push_back( new SizeofExpr( baseType->clone() ) );
1061 appExpr->get_args().back() = multiply;
1062 } // if
1063 } // if
1064 return appExpr;
1065 } // if
1066 } // if
1067 return 0;
1068 }
1069
1070 Expression *Pass1::postmutate( ApplicationExpr *appExpr ) {
1071 // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
1072 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
1073 // std::cerr << i->first << " ";
1074 // }
1075 // std::cerr << "\n";
1076
1077 assert( appExpr->function->result );
1078 FunctionType * function = getFunctionType( appExpr->function->result );
1079 assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
1080
1081 if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
1082 return newExpr;
1083 } // if
1084
1085 Expression *ret = appExpr;
1086
1087 std::list< Expression *>::iterator arg = appExpr->get_args().begin();
1088 std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
1089
1090 TyVarMap exprTyVars( TypeDecl::Data{} );
1091 makeTyVarMap( function, exprTyVars ); // xxx - should this take into account the variables already bound in scopeTyVars (i.e. remove them from exprTyVars?)
1092 ReferenceToType *dynRetType = isDynRet( function, exprTyVars );
1093
1094 // std::cerr << function << std::endl;
1095 // std::cerr << "scopeTyVars: ";
1096 // printTyVarMap( std::cerr, scopeTyVars );
1097 // std::cerr << "exprTyVars: ";
1098 // printTyVarMap( std::cerr, exprTyVars );
1099 // std::cerr << "env: " << *env << std::endl;
1100 // std::cerr << needsAdapter( function, scopeTyVars ) << ! needsAdapter( function, exprTyVars) << std::endl;
1101
1102 // 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
1103 // passTypeVars needs to know the program-text return type (i.e. the distinction between _conc_T30 and T3(int))
1104 // concRetType may not be a good name in one or both of these places. A more appropriate name change is welcome.
1105 if ( dynRetType ) {
1106 // std::cerr << "dynRetType: " << dynRetType << std::endl;
1107 Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();
1108 ret = addDynRetParam( appExpr, concRetType, arg ); // xxx - used to use dynRetType instead of concRetType
1109 } else if ( needsAdapter( function, scopeTyVars ) && ! needsAdapter( function, exprTyVars) ) { // xxx - exprTyVars is used above...?
1110 // 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.
1111
1112 // std::cerr << "needs adapter: ";
1113 // printTyVarMap( std::cerr, scopeTyVars );
1114 // std::cerr << *env << std::endl;
1115 // change the application so it calls the adapter rather than the passed function
1116 ret = applyAdapter( appExpr, function, arg, scopeTyVars );
1117 } // if
1118 arg = appExpr->get_args().begin();
1119
1120 Type *concRetType = replaceWithConcrete( appExpr, dynRetType );
1121 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)
1122 addInferredParams( appExpr, function, arg, exprTyVars );
1123
1124 arg = paramBegin;
1125
1126 boxParams( appExpr, function, arg, exprTyVars );
1127 passAdapters( appExpr, function, exprTyVars );
1128
1129 return ret;
1130 }
1131
1132 Expression * Pass1::postmutate( UntypedExpr *expr ) {
1133 if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
1134 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
1135 if ( name->name == "*?" ) {
1136 Expression *ret = expr->args.front();
1137 expr->args.clear();
1138 delete expr;
1139 return ret;
1140 } // if
1141 } // if
1142 } // if
1143 return expr;
1144 }
1145
1146 void Pass1::premutate( AddressExpr * ) { visit_children = false; }
1147 Expression * Pass1::postmutate( AddressExpr * addrExpr ) {
1148 assert( addrExpr->arg->result && ! addrExpr->arg->result->isVoid() );
1149
1150 bool needs = false;
1151 if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->arg ) ) {
1152 if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
1153 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
1154 if ( name->name == "*?" ) {
1155 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->args.front() ) ) {
1156 assert( appExpr->function->result );
1157 FunctionType *function = getFunctionType( appExpr->function->result );
1158 assert( function );
1159 needs = needsAdapter( function, scopeTyVars );
1160 } // if
1161 } // if
1162 } // if
1163 } // if
1164 } // if
1165 // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
1166 // out of the if condition.
1167 addrExpr->arg = addrExpr->arg->acceptMutator( *visitor );
1168 // ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment
1169 bool polytype = isPolyType( addrExpr->arg->result, scopeTyVars, env );
1170 if ( polytype || needs ) {
1171 Expression *ret = addrExpr->arg;
1172 delete ret->result;
1173 ret->result = addrExpr->result->clone();
1174 addrExpr->arg = nullptr;
1175 delete addrExpr;
1176 return ret;
1177 } else {
1178 return addrExpr;
1179 } // if
1180 }
1181
1182 void Pass1::premutate( ReturnStmt *returnStmt ) {
1183 if ( retval && returnStmt->expr ) {
1184 assert( returnStmt->expr->result && ! returnStmt->expr->result->isVoid() );
1185 delete returnStmt->expr;
1186 returnStmt->expr = nullptr;
1187 } // if
1188 }
1189
1190 void Pass1::premutate( PointerType *pointerType ) {
1191 GuardScope( scopeTyVars );
1192 makeTyVarMap( pointerType, scopeTyVars );
1193 }
1194
1195 void Pass1::premutate( FunctionType *functionType ) {
1196 GuardScope( scopeTyVars );
1197 makeTyVarMap( functionType, scopeTyVars );
1198 }
1199
1200 void Pass1::beginScope() {
1201 adapters.beginScope();
1202 }
1203
1204 void Pass1::endScope() {
1205 adapters.endScope();
1206 }
1207
1208////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
1209
1210 void Pass2::addAdapters( FunctionType *functionType ) {
1211 std::list< DeclarationWithType *> &paramList = functionType->parameters;
1212 std::list< FunctionType *> functions;
1213 for ( DeclarationWithType * const arg : functionType->parameters ) {
1214 Type *orig = arg->get_type();
1215 findAndReplaceFunction( orig, functions, scopeTyVars, needsAdapter );
1216 arg->set_type( orig );
1217 }
1218 std::set< std::string > adaptersDone;
1219 for ( FunctionType * const funType : functions ) {
1220 std::string mangleName = mangleAdapterName( funType, scopeTyVars );
1221 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
1222 std::string adapterName = makeAdapterName( mangleName );
1223 // adapter may not be used in body, pass along with unused attribute.
1224 paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), 0, { new Attribute( "unused" ) } ) );
1225 adaptersDone.insert( adaptersDone.begin(), mangleName );
1226 }
1227 }
1228// deleteAll( functions );
1229 }
1230
1231 DeclarationWithType * Pass2::postmutate( FunctionDecl *functionDecl ) {
1232 FunctionType * ftype = functionDecl->type;
1233 if ( ! ftype->returnVals.empty() && functionDecl->statements ) {
1234 // intrinsic functions won't be using the _retval so no need to generate it.
1235 if ( functionDecl->linkage != LinkageSpec::Intrinsic && !isPrefix( functionDecl->name, "_thunk" ) && ! isPrefix( functionDecl->name, "_adapter" ) ) { // xxx - remove check for prefix once thunks properly use ctor/dtors
1236 assert( ftype->returnVals.size() == 1 );
1237 DeclarationWithType * retval = ftype->returnVals.front();
1238 if ( retval->name == "" ) {
1239 retval->name = "_retval";
1240 }
1241 functionDecl->statements->kids.push_front( new DeclStmt( retval ) );
1242 DeclarationWithType * newRet = retval->clone(); // for ownership purposes
1243 ftype->returnVals.front() = newRet;
1244 }
1245 }
1246 // errors should have been caught by this point, remove initializers from parameters to allow correct codegen of default arguments
1247 for ( Declaration * param : functionDecl->type->parameters ) {
1248 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( param ) ) {
1249 delete obj->init;
1250 obj->init = nullptr;
1251 }
1252 }
1253 return functionDecl;
1254 }
1255
1256 void Pass2::premutate( StructDecl * ) {
1257 // prevent tyVars from leaking into containing scope
1258 GuardScope( scopeTyVars );
1259 }
1260
1261 void Pass2::premutate( UnionDecl * ) {
1262 // prevent tyVars from leaking into containing scope
1263 GuardScope( scopeTyVars );
1264 }
1265
1266 void Pass2::premutate( TraitDecl * ) {
1267 // prevent tyVars from leaking into containing scope
1268 GuardScope( scopeTyVars );
1269 }
1270
1271 void Pass2::premutate( TypeDecl *typeDecl ) {
1272 addToTyVarMap( typeDecl, scopeTyVars );
1273 }
1274
1275 void Pass2::premutate( PointerType *pointerType ) {
1276 GuardScope( scopeTyVars );
1277 makeTyVarMap( pointerType, scopeTyVars );
1278 }
1279
1280 void Pass2::premutate( FunctionType *funcType ) {
1281 GuardScope( scopeTyVars );
1282 makeTyVarMap( funcType, scopeTyVars );
1283
1284 // move polymorphic return type to parameter list
1285 if ( isDynRet( funcType ) ) {
1286 ObjectDecl *ret = strict_dynamic_cast< ObjectDecl* >( funcType->get_returnVals().front() );
1287 ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
1288 funcType->get_parameters().push_front( ret );
1289 funcType->get_returnVals().pop_front();
1290 ret->set_init( nullptr ); // xxx - memory leak?
1291 }
1292
1293 // add size/align and assertions for type parameters to parameter list
1294 std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
1295 std::list< DeclarationWithType *> inferredParams;
1296 // size/align/offset parameters may not be used in body, pass along with unused attribute.
1297 ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0,
1298 { new Attribute( "unused" ) } );
1299 ObjectDecl newPtr( "", Type::StorageClasses(), LinkageSpec::C, 0,
1300 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
1301 for ( TypeDecl * const tyParam : funcType->get_forall() ) {
1302 ObjectDecl *sizeParm, *alignParm;
1303 // add all size and alignment parameters to parameter list
1304 if ( tyParam->isComplete() ) {
1305 TypeInstType parmType( Type::Qualifiers(), tyParam->get_name(), tyParam );
1306 std::string parmName = mangleType( &parmType );
1307
1308 sizeParm = newObj.clone();
1309 sizeParm->set_name( sizeofName( parmName ) );
1310 last = funcType->get_parameters().insert( last, sizeParm );
1311 ++last;
1312
1313 alignParm = newObj.clone();
1314 alignParm->set_name( alignofName( parmName ) );
1315 last = funcType->get_parameters().insert( last, alignParm );
1316 ++last;
1317 }
1318 // move all assertions into parameter list
1319 for ( DeclarationWithType * const assert : tyParam->get_assertions() ) {
1320 // assertion parameters may not be used in body, pass along with unused attribute.
1321 assert->get_attributes().push_back( new Attribute( "unused" ) );
1322 inferredParams.push_back( assert );
1323 }
1324 tyParam->get_assertions().clear();
1325 }
1326
1327 // add size/align for generic parameter types to parameter list
1328 std::set< std::string > seenTypes; // sizeofName for generic types we've seen
1329 for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) {
1330 Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars );
1331 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
1332 std::string typeName = mangleType( polyType );
1333 if ( seenTypes.count( typeName ) ) continue;
1334
1335 ObjectDecl *sizeParm, *alignParm, *offsetParm;
1336 sizeParm = newObj.clone();
1337 sizeParm->set_name( sizeofName( typeName ) );
1338 last = funcType->get_parameters().insert( last, sizeParm );
1339 ++last;
1340
1341 alignParm = newObj.clone();
1342 alignParm->set_name( alignofName( typeName ) );
1343 last = funcType->get_parameters().insert( last, alignParm );
1344 ++last;
1345
1346 if ( StructInstType *polyBaseStruct = dynamic_cast< StructInstType* >( polyType ) ) {
1347 // NOTE zero-length arrays are illegal in C, so empty structs have no offset array
1348 if ( ! polyBaseStruct->get_baseStruct()->get_members().empty() ) {
1349 offsetParm = newPtr.clone();
1350 offsetParm->set_name( offsetofName( typeName ) );
1351 last = funcType->get_parameters().insert( last, offsetParm );
1352 ++last;
1353 }
1354 }
1355 seenTypes.insert( typeName );
1356 }
1357 }
1358
1359 // splice assertion parameters into parameter list
1360 funcType->get_parameters().splice( last, inferredParams );
1361 addAdapters( funcType );
1362 }
1363
1364////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////////////////////////
1365
1366 PolyGenericCalculator::PolyGenericCalculator()
1367 : knownLayouts(), knownOffsets(), bufNamer( "_buf" ) {}
1368
1369 void PolyGenericCalculator::beginTypeScope( Type *ty ) {
1370 GuardScope( scopeTyVars );
1371 makeTyVarMap( ty, scopeTyVars );
1372 }
1373
1374 void PolyGenericCalculator::beginGenericScope() {
1375 GuardScope( *this );
1376 // We expect the first function type see to be the type relating to this scope
1377 // but any further type is probably some unrelated function pointer
1378 // keep track of which is the first
1379 GuardValue( expect_func_type );
1380 expect_func_type = true;
1381 }
1382
1383 void PolyGenericCalculator::premutate( ObjectDecl *objectDecl ) {
1384 beginTypeScope( objectDecl->get_type() );
1385 }
1386
1387 void PolyGenericCalculator::premutate( FunctionDecl *functionDecl ) {
1388 beginGenericScope();
1389
1390 beginTypeScope( functionDecl->get_functionType() );
1391 }
1392
1393 void PolyGenericCalculator::premutate( TypedefDecl *typedefDecl ) {
1394 assert(false);
1395 beginTypeScope( typedefDecl->get_base() );
1396 }
1397
1398 void PolyGenericCalculator::premutate( TypeDecl * typeDecl ) {
1399 addToTyVarMap( typeDecl, scopeTyVars );
1400 }
1401
1402 Declaration * PolyGenericCalculator::postmutate( TypeDecl *typeDecl ) {
1403 if ( Type * base = typeDecl->base ) {
1404 // add size/align variables for opaque type declarations
1405 TypeInstType inst( Type::Qualifiers(), typeDecl->name, typeDecl );
1406 std::string typeName = mangleType( &inst );
1407 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1408
1409 ObjectDecl * sizeDecl = ObjectDecl::newObject( sizeofName( typeName ), layoutType, new SingleInit( new SizeofExpr( base->clone() ) ) );
1410 ObjectDecl * alignDecl = ObjectDecl::newObject( alignofName( typeName ), layoutType->clone(), new SingleInit( new AlignofExpr( base->clone() ) ) );
1411
1412 // ensure that the initializing sizeof/alignof exprs are properly mutated
1413 sizeDecl->acceptMutator( *visitor );
1414 alignDecl->acceptMutator( *visitor );
1415
1416 // can't use makeVar, because it inserts into stmtsToAdd and TypeDecls can occur at global scope
1417 declsToAddAfter.push_back( alignDecl );
1418 // replace with sizeDecl
1419 return sizeDecl;
1420 }
1421 return typeDecl;
1422 }
1423
1424 void PolyGenericCalculator::premutate( PointerType *pointerType ) {
1425 beginTypeScope( pointerType );
1426 }
1427
1428 void PolyGenericCalculator::premutate( FunctionType *funcType ) {
1429 beginTypeScope( funcType );
1430
1431 GuardValue( expect_func_type );
1432
1433 if(!expect_func_type) {
1434 GuardAction( [this]() {
1435 knownLayouts.endScope();
1436 knownOffsets.endScope();
1437 });
1438 // If this is the first function type we see
1439 // Then it's the type of the declaration and we care about it
1440 knownLayouts.beginScope();
1441 knownOffsets.beginScope();
1442 }
1443
1444 // The other functions type we will see in this scope are probably functions parameters
1445 // they don't help us with the layout and offsets so don't mark them as known in this scope
1446 expect_func_type = false;
1447
1448 // make sure that any type information passed into the function is accounted for
1449 for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) {
1450 // condition here duplicates that in Pass2::mutate( FunctionType* )
1451 Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars );
1452 if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
1453 knownLayouts.insert( mangleType( polyType ) );
1454 }
1455 }
1456 }
1457
1458 /// converts polymorphic type T into a suitable monomorphic representation, currently: __attribute__((aligned(8)) char[size_T]
1459 Type * polyToMonoType( Type * declType ) {
1460 Type * charType = new BasicType( Type::Qualifiers(), BasicType::Kind::Char);
1461 Expression * size = new NameExpr( sizeofName( mangleType(declType) ) );
1462 Attribute * aligned = new Attribute( "aligned", std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } );
1463 return new ArrayType( Type::Qualifiers(), charType, size,
1464 true, false, std::list<Attribute *>{ aligned } );
1465 }
1466
1467 void PolyGenericCalculator::mutateMembers( AggregateDecl * aggrDecl ) {
1468 std::set< std::string > genericParams;
1469 for ( TypeDecl * td : aggrDecl->parameters ) {
1470 genericParams.insert( td->name );
1471 }
1472 for ( Declaration * decl : aggrDecl->members ) {
1473 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( decl ) ) {
1474 Type * ty = replaceTypeInst( field->type, env );
1475 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
1476 // do not try to monomorphize generic parameters
1477 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() && ! genericParams.count( typeInst->name ) ) {
1478 // polymorphic aggregate members should be converted into monomorphic members.
1479 // Using char[size_T] here respects the expected sizing rules of an aggregate type.
1480 Type * newType = polyToMonoType( field->type );
1481 delete field->type;
1482 field->type = newType;
1483 }
1484 }
1485 }
1486 }
1487 }
1488
1489 void PolyGenericCalculator::premutate( StructDecl * structDecl ) {
1490 mutateMembers( structDecl );
1491 }
1492
1493 void PolyGenericCalculator::premutate( UnionDecl * unionDecl ) {
1494 mutateMembers( unionDecl );
1495 }
1496
1497 void PolyGenericCalculator::premutate( DeclStmt *declStmt ) {
1498 if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
1499 if ( findGeneric( objectDecl->get_type() ) ) {
1500 // change initialization of a polymorphic value object to allocate via a VLA
1501 // (alloca was previously used, but can't be safely used in loops)
1502 ObjectDecl *newBuf = ObjectDecl::newObject( bufNamer.newName(), polyToMonoType( objectDecl->type ), nullptr );
1503 stmtsToAddBefore.push_back( new DeclStmt( newBuf ) );
1504
1505 // if the object has a cleanup attribute, the cleanup should be on the buffer, not the pointer
1506 auto matchAndMove = [newBuf](Attribute * attr){
1507 if(attr->name == "cleanup") {
1508 newBuf->attributes.push_back(attr);
1509 return true;
1510 }
1511 return false;
1512 };
1513
1514 objectDecl->attributes.remove_if(matchAndMove);
1515
1516 delete objectDecl->get_init();
1517 objectDecl->set_init( new SingleInit( new VariableExpr( newBuf ) ) );
1518 }
1519 }
1520 }
1521
1522 /// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
1523 long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
1524 for ( auto pair : enumerate( baseDecls ) ) {
1525 Declaration * decl = pair.val;
1526 size_t i = pair.idx;
1527 if ( memberDecl->get_name() != decl->get_name() )
1528 continue;
1529
1530 if ( memberDecl->get_name().empty() ) {
1531 // plan-9 field: match on unique_id
1532 if ( memberDecl->get_uniqueId() == decl->get_uniqueId() )
1533 return i;
1534 else
1535 continue;
1536 }
1537
1538 DeclarationWithType *declWithType = strict_dynamic_cast< DeclarationWithType* >( decl );
1539
1540 if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty() ) {
1541 // tuple-element field: expect neither had mangled name; accept match on simple name (like field_2) only
1542 assert( memberDecl->get_mangleName().empty() && declWithType->get_mangleName().empty() );
1543 return i;
1544 }
1545
1546 // ordinary field: use full name to accommodate overloading
1547 if ( memberDecl->get_mangleName() == declWithType->get_mangleName() )
1548 return i;
1549 else
1550 continue;
1551 }
1552 return -1;
1553 }
1554
1555 /// Returns an index expression into the offset array for a type
1556 Expression *makeOffsetIndex( Type *objectType, long i ) {
1557 ConstantExpr *fieldIndex = new ConstantExpr( Constant::from_ulong( i ) );
1558 UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
1559 fieldOffset->get_args().push_back( new NameExpr( offsetofName( mangleType( objectType ) ) ) );
1560 fieldOffset->get_args().push_back( fieldIndex );
1561 return fieldOffset;
1562 }
1563
1564 Expression *PolyGenericCalculator::postmutate( MemberExpr *memberExpr ) {
1565 // only mutate member expressions for polymorphic types
1566 int tyDepth;
1567 Type *objectType = hasPolyBase( memberExpr->aggregate->result, scopeTyVars, &tyDepth );
1568 if ( ! objectType ) return memberExpr;
1569 findGeneric( objectType ); // ensure layout for this type is available
1570
1571 // replace member expression with dynamically-computed layout expression
1572 Expression *newMemberExpr = nullptr;
1573 if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
1574 // look up offset index
1575 long i = findMember( memberExpr->member, structType->baseStruct->members );
1576 if ( i == -1 ) return memberExpr;
1577
1578 // replace member expression with pointer to base plus offset
1579 UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
1580 Expression * aggr = memberExpr->aggregate->clone();
1581 delete aggr->env; // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
1582 aggr->env = nullptr;
1583 fieldLoc->get_args().push_back( aggr );
1584 fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
1585 fieldLoc->set_result( memberExpr->result->clone() );
1586 newMemberExpr = fieldLoc;
1587 } else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
1588 // union members are all at offset zero, so just use the aggregate expr
1589 Expression * aggr = memberExpr->aggregate->clone();
1590 delete aggr->env; // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
1591 aggr->env= nullptr;
1592 newMemberExpr = aggr;
1593 newMemberExpr->result = memberExpr->result->clone();
1594 } else return memberExpr;
1595 assert( newMemberExpr );
1596
1597 // 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.
1598 // forall(otype T) struct Box { T x; }
1599 // forall(otype T) f() {
1600 // Box(T *) b; b.x;
1601 // }
1602 // 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.
1603 Type *memberType = memberExpr->member->get_type()->clone();
1604 TypeSubstitution sub = objectType->genericSubstitution();
1605 sub.apply( memberType );
1606 if ( ! isPolyType( memberType, scopeTyVars ) ) {
1607 // 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
1608 CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) );
1609 UntypedExpr *derefExpr = UntypedExpr::createDeref( ptrCastExpr );
1610 newMemberExpr = derefExpr;
1611 }
1612
1613 delete memberType;
1614 delete memberExpr;
1615 return newMemberExpr;
1616 }
1617
1618 void PolyGenericCalculator::premutate( AddressExpr * addrExpr ) {
1619 GuardValue( addrMember );
1620 // is the argument a MemberExpr before mutating?
1621 addrMember = dynamic_cast< MemberExpr * >( addrExpr->arg );
1622 }
1623
1624 Expression * PolyGenericCalculator::postmutate( AddressExpr * addrExpr ) {
1625 if ( addrMember && addrMember != addrExpr->arg ) {
1626 // arg was a MemberExpr and has been mutated
1627 if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( addrExpr->arg ) ) {
1628 if ( InitTweak::getFunctionName( untyped ) == "?+?" ) {
1629 // MemberExpr was converted to pointer+offset, and it is not valid C to take the address of an addition, so strip the address-of
1630 // TODO: should addrExpr->arg->result be changed to addrExpr->result?
1631 Expression * ret = addrExpr->arg;
1632 addrExpr->arg = nullptr;
1633 std::swap( addrExpr->env, ret->env );
1634 delete addrExpr;
1635 return ret;
1636 }
1637 }
1638 }
1639 return addrExpr;
1640 }
1641
1642 ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
1643 ObjectDecl *newObj = new ObjectDecl( name, Type::StorageClasses(), LinkageSpec::C, nullptr, type, init );
1644 stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
1645 return newObj;
1646 }
1647
1648 void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
1649 for ( Type * const param : otypeParams ) {
1650 if ( findGeneric( param ) ) {
1651 // push size/align vars for a generic parameter back
1652 std::string paramName = mangleType( param );
1653 layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) );
1654 layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) );
1655 } else {
1656 layoutCall->get_args().push_back( new SizeofExpr( param->clone() ) );
1657 layoutCall->get_args().push_back( new AlignofExpr( param->clone() ) );
1658 }
1659 }
1660 }
1661
1662 /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
1663 bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
1664 bool hasDynamicLayout = false;
1665
1666 std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
1667 std::list< Expression* >::const_iterator typeParam = typeParams.begin();
1668 for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
1669 // skip non-otype parameters
1670 if ( ! (*baseParam)->isComplete() ) continue;
1671 TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
1672 assert( typeExpr && "all otype parameters should be type expressions" );
1673
1674 Type *type = typeExpr->get_type();
1675 out.push_back( type );
1676 if ( isPolyType( type ) ) hasDynamicLayout = true;
1677 }
1678 assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
1679
1680 return hasDynamicLayout;
1681 }
1682
1683 bool PolyGenericCalculator::findGeneric( Type *ty ) {
1684 ty = replaceTypeInst( ty, env );
1685
1686 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
1687 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
1688 // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
1689 return true;
1690 }
1691 return false;
1692 } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
1693 // check if this type already has a layout generated for it
1694 std::string typeName = mangleType( ty );
1695 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
1696
1697 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
1698 std::list< Type* > otypeParams;
1699 if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
1700
1701 // insert local variables for layout and generate call to layout function
1702 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call
1703 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1704
1705 int n_members = structTy->get_baseStruct()->get_members().size();
1706 if ( n_members == 0 ) {
1707 // all empty structs have the same layout - size 1, align 1
1708 makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
1709 makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from_ulong( (unsigned long)1 ) ) ) );
1710 // NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
1711 } else {
1712 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
1713 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
1714 ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from_int( n_members ) ), false, false ) );
1715
1716 // generate call to layout function
1717 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( structTy->get_baseStruct() ) ) );
1718 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
1719 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
1720 layoutCall->get_args().push_back( new VariableExpr( offsetVar ) );
1721 addOtypeParamsToLayoutCall( layoutCall, otypeParams );
1722
1723 stmtsToAddBefore.push_back( new ExprStmt( layoutCall ) );
1724 }
1725
1726 // std::cout << "TRUE 2" << std::endl;
1727
1728 return true;
1729 } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
1730 // check if this type already has a layout generated for it
1731 std::string typeName = mangleType( ty );
1732 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
1733
1734 // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
1735 std::list< Type* > otypeParams;
1736 if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
1737
1738 // insert local variables for layout and generate call to layout function
1739 knownLayouts.insert( typeName ); // done early so as not to interfere with the later addition of parameters to the layout call
1740 Type *layoutType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1741
1742 ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
1743 ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
1744
1745 // generate call to layout function
1746 UntypedExpr *layoutCall = new UntypedExpr( new NameExpr( layoutofName( unionTy->get_baseUnion() ) ) );
1747 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( sizeVar ) ) );
1748 layoutCall->get_args().push_back( new AddressExpr( new VariableExpr( alignVar ) ) );
1749 addOtypeParamsToLayoutCall( layoutCall, otypeParams );
1750
1751 stmtsToAddBefore.push_back( new ExprStmt( layoutCall ) );
1752
1753 return true;
1754 }
1755
1756 return false;
1757 }
1758
1759 Expression * PolyGenericCalculator::genSizeof( Type* ty ) {
1760 if ( ArrayType * aty = dynamic_cast<ArrayType *>(ty) ) {
1761 // generate calculated size for possibly generic array
1762 Expression * sizeofBase = genSizeof( aty->get_base() );
1763 if ( ! sizeofBase ) return nullptr;
1764 Expression * dim = aty->get_dimension();
1765 aty->set_dimension( nullptr );
1766 return makeOp( "?*?", sizeofBase, dim );
1767 } else if ( findGeneric( ty ) ) {
1768 // generate calculated size for generic type
1769 return new NameExpr( sizeofName( mangleType( ty ) ) );
1770 } else return nullptr;
1771 }
1772
1773 Expression *PolyGenericCalculator::postmutate( SizeofExpr *sizeofExpr ) {
1774 Type *ty = sizeofExpr->get_isType() ?
1775 sizeofExpr->get_type() : sizeofExpr->get_expr()->get_result();
1776
1777 Expression * gen = genSizeof( ty );
1778 if ( gen ) {
1779 delete sizeofExpr;
1780 return gen;
1781 } else return sizeofExpr;
1782 }
1783
1784 Expression *PolyGenericCalculator::postmutate( AlignofExpr *alignofExpr ) {
1785 Type *ty = alignofExpr->get_isType() ? alignofExpr->get_type() : alignofExpr->get_expr()->get_result();
1786 if ( findGeneric( ty ) ) {
1787 Expression *ret = new NameExpr( alignofName( mangleType( ty ) ) );
1788 delete alignofExpr;
1789 return ret;
1790 }
1791 return alignofExpr;
1792 }
1793
1794 Expression *PolyGenericCalculator::postmutate( OffsetofExpr *offsetofExpr ) {
1795 // only mutate expressions for polymorphic structs/unions
1796 Type *ty = offsetofExpr->get_type();
1797 if ( ! findGeneric( ty ) ) return offsetofExpr;
1798
1799 if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
1800 // replace offsetof expression by index into offset array
1801 long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() );
1802 if ( i == -1 ) return offsetofExpr;
1803
1804 Expression *offsetInd = makeOffsetIndex( ty, i );
1805 delete offsetofExpr;
1806 return offsetInd;
1807 } else if ( dynamic_cast< UnionInstType* >( ty ) ) {
1808 // all union members are at offset zero
1809 delete offsetofExpr;
1810 return new ConstantExpr( Constant::from_ulong( 0 ) );
1811 } else return offsetofExpr;
1812 }
1813
1814 Expression *PolyGenericCalculator::postmutate( OffsetPackExpr *offsetPackExpr ) {
1815 StructInstType *ty = offsetPackExpr->get_type();
1816
1817 Expression *ret = 0;
1818 if ( findGeneric( ty ) ) {
1819 // pull offset back from generated type information
1820 ret = new NameExpr( offsetofName( mangleType( ty ) ) );
1821 } else {
1822 std::string offsetName = offsetofName( mangleType( ty ) );
1823 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
1824 // use the already-generated offsets for this type
1825 ret = new NameExpr( offsetName );
1826 } else {
1827 knownOffsets.insert( offsetName );
1828
1829 std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
1830 Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
1831
1832 // build initializer list for offset array
1833 std::list< Initializer* > inits;
1834 for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
1835 if ( DeclarationWithType *memberDecl = dynamic_cast< DeclarationWithType* >( *member ) ) {
1836 inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
1837 } else {
1838 assertf( false, "Requesting offset of Non-DWT member: %s", toString( *member ).c_str() );
1839 }
1840 }
1841
1842 // build the offset array and replace the pack with a reference to it
1843 ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from_ulong( baseMembers.size() ) ), false, false ),
1844 new ListInit( inits ) );
1845 ret = new VariableExpr( offsetArray );
1846 }
1847 }
1848
1849 delete offsetPackExpr;
1850 return ret;
1851 }
1852
1853 void PolyGenericCalculator::beginScope() {
1854 knownLayouts.beginScope();
1855 knownOffsets.beginScope();
1856 }
1857
1858 void PolyGenericCalculator::endScope() {
1859 knownLayouts.endScope();
1860 knownOffsets.endScope();
1861 }
1862
1863////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
1864
1865 template< typename DeclClass >
1866 void Pass3::handleDecl( DeclClass * decl, Type * type ) {
1867 GuardScope( scopeTyVars );
1868 makeTyVarMap( type, scopeTyVars );
1869 ScrubTyVars::scrubAll( decl );
1870 }
1871
1872 void Pass3::premutate( ObjectDecl * objectDecl ) {
1873 handleDecl( objectDecl, objectDecl->type );
1874 }
1875
1876 void Pass3::premutate( FunctionDecl * functionDecl ) {
1877 handleDecl( functionDecl, functionDecl->type );
1878 }
1879
1880 void Pass3::premutate( TypedefDecl * typedefDecl ) {
1881 handleDecl( typedefDecl, typedefDecl->base );
1882 }
1883
1884 /// Strips the members from a generic aggregate
1885 void stripGenericMembers(AggregateDecl * decl) {
1886 if ( ! decl->parameters.empty() ) decl->members.clear();
1887 }
1888
1889 void Pass3::premutate( StructDecl * structDecl ) {
1890 stripGenericMembers( structDecl );
1891 }
1892
1893 void Pass3::premutate( UnionDecl * unionDecl ) {
1894 stripGenericMembers( unionDecl );
1895 }
1896
1897 void Pass3::premutate( TypeDecl * typeDecl ) {
1898 addToTyVarMap( typeDecl, scopeTyVars );
1899 }
1900
1901 void Pass3::premutate( PointerType * pointerType ) {
1902 GuardScope( scopeTyVars );
1903 makeTyVarMap( pointerType, scopeTyVars );
1904 }
1905
1906 void Pass3::premutate( FunctionType * functionType ) {
1907 GuardScope( scopeTyVars );
1908 makeTyVarMap( functionType, scopeTyVars );
1909 }
1910 } // anonymous namespace
1911} // namespace GenPoly
1912
1913// Local Variables: //
1914// tab-width: 4 //
1915// mode: c++ //
1916// compile-command: "make install" //
1917// End: //
1918
Note: See TracBrowser for help on using the repository browser.