source: src/GenPoly/Box.cc@ 7a2057a

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

Cleaning old box pass for easier translation. Changed over for loops, with extra const. Also an extra comment in another file I found.

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