source: src/GenPoly/Box.cc @ 44547b0

ADTast-experimental
Last change on this file since 44547b0 was a805100, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Cleaning old box pass for easier translation. Refactor to remove unneeded parameters. In the future someone may have to put them back, but that flexibility is not being used now.

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