source: src/GenPoly/Box.cc @ 4da152a

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

Cleaning old box pass for easier translation. Adding a bunch of const qualifiers. Hopefully this will remove some ambiguity about where changes happen, but const is dropped quickly in the old ast.

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