source: src/GenPoly/Box.cc @ ac633d0

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since ac633d0 was ac633d0, checked in by Aaron Moss <a3moss@…>, 8 years ago

Strip some dead code from Box.cc

  • Property mode set to 100644
File size: 93.0 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Box.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Feb  5 16:45:07 2016
13// Update Count     : 286
14//
15
16#include <algorithm>
17#include <iterator>
18#include <list>
19#include <map>
20#include <set>
21#include <stack>
22#include <string>
23#include <utility>
24#include <vector>
25#include <cassert>
26
27#include "Box.h"
28#include "DeclMutator.h"
29#include "PolyMutator.h"
30#include "FindFunction.h"
31#include "ScopedMap.h"
32#include "ScrubTyVars.h"
33
34#include "Parser/ParseNode.h"
35
36#include "SynTree/Constant.h"
37#include "SynTree/Declaration.h"
38#include "SynTree/Expression.h"
39#include "SynTree/Initializer.h"
40#include "SynTree/Mutator.h"
41#include "SynTree/Statement.h"
42#include "SynTree/Type.h"
43#include "SynTree/TypeSubstitution.h"
44
45#include "ResolvExpr/TypeEnvironment.h"
46#include "ResolvExpr/TypeMap.h"
47#include "ResolvExpr/typeops.h"
48
49#include "SymTab/Indexer.h"
50#include "SymTab/Mangler.h"
51
52#include "Common/SemanticError.h"
53#include "Common/UniqueName.h"
54#include "Common/utility.h"
55
56#include <ext/functional> // temporary
57
58namespace GenPoly {
59        namespace {
60                const std::list<Label> noLabels;
61
62                FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
63
64                /// Key for a unique concrete type; generic base type paired with type parameter list
65                struct ConcreteType {
66                        ConcreteType() : base(NULL), params() {}
67
68                        ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); }
69
70                        ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }
71
72                        /// Extracts types from a list of TypeExpr*
73                        ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base), params() {
74                                for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {
75                                        params.push_back( (*param)->get_type()->clone() );
76                                }
77                        }
78
79                        ConcreteType& operator= (const ConcreteType& that) {
80                                deleteAll( params );
81                                params.clear();
82
83                                base = that.base;
84                                cloneAll( that.params, params );
85
86                                return *this;
87                        }
88
89                        ~ConcreteType() { deleteAll( params ); }
90
91                        bool operator== (const ConcreteType& that) const {
92                                if ( base != that.base ) return false;
93
94                                SymTab::Indexer dummy;
95                                if ( params.size() != that.params.size() ) return false;
96                                for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
97                                        if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;
98                                }
99                                return true;
100                        }
101
102                        AggregateDecl *base;        ///< Base generic type
103                        std::list< Type* > params;  ///< Instantiation parameters
104                };
105
106                /// Maps a concrete type to the some value, accounting for scope
107                template< typename Value >
108                class InstantiationMap {
109                        /// Information about a specific instantiation of a generic type
110                        struct Instantiation {
111                                ConcreteType key;  ///< Instantiation parameters for this type
112                                Value *value;      ///< Value for this instantiation
113
114                                Instantiation() : key(), value(0) {}
115                                Instantiation(const ConcreteType &_key, Value *_value) : key(_key), value(_value) {}
116                        };
117                        /// Map of generic types to instantiations of them
118                        typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;
119
120                        std::vector< Scope > scopes;  ///< list of scopes, from outermost to innermost
121
122                public:
123                        /// Starts a new scope
124                        void beginScope() {
125                                Scope scope;
126                                scopes.push_back(scope);
127                        }
128
129                        /// Ends a scope
130                        void endScope() {
131                                scopes.pop_back();
132                        }
133
134                        /// Default constructor initializes with one scope
135                        InstantiationMap() { beginScope(); }
136
137                        /// Gets the value for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.
138                        /// Returns NULL on none such.
139                        Value *lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) {
140                                ConcreteType key(generic, params);
141                                // scan scopes from innermost out
142                                for ( typename std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) {
143                                        // skip scope if no instantiations of this generic type
144                                        typename Scope::const_iterator insts = scope->find( generic );
145                                        if ( insts == scope->end() ) continue;
146                                        // look through instantiations for matches to concrete type
147                                        for ( typename std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {
148                                                if ( inst->key == key ) return inst->value;
149                                        }
150                                }
151                                // no matching instantiation found
152                                return 0;
153                        }
154
155                        /// Adds a value for a concrete type to the current scope
156                        void insert( AggregateDecl *generic, const std::list< TypeExpr* > &params, Value *value ) {
157                                ConcreteType key(generic, params);
158                                scopes.back()[generic].push_back( Instantiation( key, value ) );
159                        }
160                };
161
162                /// Adds layout-generation functions to polymorphic types
163                class LayoutFunctionBuilder : public DeclMutator {
164                        unsigned int functionNesting;  // current level of nested functions
165                public:
166                        LayoutFunctionBuilder() : functionNesting( 0 ) {}
167
168                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
169                        virtual Declaration *mutate( StructDecl *structDecl );
170                        virtual Declaration *mutate( UnionDecl *unionDecl );
171                };
172               
173                /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
174                class Pass1 : public PolyMutator {
175                  public:
176                        Pass1();
177                        virtual Expression *mutate( ApplicationExpr *appExpr );
178                        virtual Expression *mutate( AddressExpr *addrExpr );
179                        virtual Expression *mutate( UntypedExpr *expr );
180                        virtual DeclarationWithType* mutate( FunctionDecl *functionDecl );
181                        virtual TypeDecl *mutate( TypeDecl *typeDecl );
182                        virtual Expression *mutate( CommaExpr *commaExpr );
183                        virtual Expression *mutate( ConditionalExpr *condExpr );
184                        virtual Statement * mutate( ReturnStmt *returnStmt );
185                        virtual Type *mutate( PointerType *pointerType );
186                        virtual Type * mutate( FunctionType *functionType );
187
188                        virtual void doBeginScope();
189                        virtual void doEndScope();
190                  private:
191                        /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it
192                        Expression *makeOffsetArray( StructInstType *type );
193                        /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
194                        void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
195                        /// passes extra type parameters into a polymorphic function application
196                        void passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
197                        /// wraps a function application with a new temporary for the out-parameter return value
198                        Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
199                        /// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment
200                        void replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params );
201                        /// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete).
202                        /// If `doClone` is set to false, will not clone interior types
203                        Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true );
204                        /// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value
205                        Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg );
206                        Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
207                        void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
208                        void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
209                        void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
210                        /// Stores assignment operators from assertion list in local map of assignment operations
211                        void findAssignOps( const std::list< TypeDecl *> &forall );
212                        void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
213                        FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
214                        /// Replaces intrinsic operator functions with their arithmetic desugaring
215                        Expression *handleIntrinsics( ApplicationExpr *appExpr );
216                        /// Inserts a new temporary variable into the current scope with an auto-generated name
217                        ObjectDecl *makeTemporary( Type *type );
218
219                        std::map< std::string, DeclarationWithType *> assignOps;
220                        ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;
221                        ScopedMap< std::string, DeclarationWithType* > adapters;
222                        DeclarationWithType *retval;
223                        bool useRetval;
224                        UniqueName tempNamer;
225                };
226
227                /// Moves polymorphic returns in function types to pointer-type parameters, adds type size and assertion parameters to parameter lists as well
228                class Pass2 : public PolyMutator {
229                  public:
230                        template< typename DeclClass >
231                        DeclClass *handleDecl( DeclClass *decl, Type *type );
232                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
233                        virtual ObjectDecl *mutate( ObjectDecl *objectDecl );
234                        virtual TypeDecl *mutate( TypeDecl *typeDecl );
235                        virtual TypedefDecl *mutate( TypedefDecl *typedefDecl );
236                        virtual Type *mutate( PointerType *pointerType );
237                        virtual Type *mutate( FunctionType *funcType );
238                  private:
239                        void addAdapters( FunctionType *functionType );
240
241                        std::map< UniqueId, std::string > adapterName;
242                };
243
244                /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
245                class GenericInstantiator : public DeclMutator {
246                        /// Map of (generic type, parameter list) pairs to concrete type instantiations
247                        InstantiationMap< AggregateDecl > instantiations;
248                        /// Namer for concrete types
249                        UniqueName typeNamer;
250
251                public:
252                        GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
253
254                        virtual Type* mutate( StructInstType *inst );
255                        virtual Type* mutate( UnionInstType *inst );
256
257        //              virtual Expression* mutate( MemberExpr *memberExpr );
258
259                        virtual void doBeginScope();
260                        virtual void doEndScope();
261                private:
262                        /// Wrap instantiation lookup for structs
263                        StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)instantiations.lookup( inst->get_baseStruct(), typeSubs ); }
264                        /// Wrap instantiation lookup for unions
265                        UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)instantiations.lookup( inst->get_baseUnion(), typeSubs ); }
266                        /// Wrap instantiation insertion for structs
267                        void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { instantiations.insert( inst->get_baseStruct(), typeSubs, decl ); }
268                        /// Wrap instantiation insertion for unions
269                        void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }
270                };
271
272                /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference;
273                /// also fixes offsetof expressions.
274                class MemberExprFixer : public PolyMutator {
275                  public:
276                        template< typename DeclClass >
277                        DeclClass *handleDecl( DeclClass *decl, Type *type );
278                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
279                        virtual ObjectDecl *mutate( ObjectDecl *objectDecl );
280                        virtual TypedefDecl *mutate( TypedefDecl *objectDecl );
281                        virtual TypeDecl *mutate( TypeDecl *objectDecl );
282                        virtual Statement *mutate( DeclStmt *declStmt );
283                        virtual Type *mutate( PointerType *pointerType );
284                        virtual Type *mutate( FunctionType *funcType );
285                        virtual Expression *mutate( MemberExpr *memberExpr );
286                        virtual Expression *mutate( OffsetofExpr *offsetofExpr );
287                };
288
289                /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable
290                class Pass3 : public PolyMutator {
291                  public:
292                        template< typename DeclClass >
293                        DeclClass *handleDecl( DeclClass *decl, Type *type );
294                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
295                        virtual ObjectDecl *mutate( ObjectDecl *objectDecl );
296                        virtual TypedefDecl *mutate( TypedefDecl *objectDecl );
297                        virtual TypeDecl *mutate( TypeDecl *objectDecl );
298                        virtual Type *mutate( PointerType *pointerType );
299                        virtual Type *mutate( FunctionType *funcType );
300                  private:
301                };
302
303        } // anonymous namespace
304
305        /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
306        template< typename MutatorType >
307        inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) {
308                bool seenIntrinsic = false;
309                SemanticError errors;
310                for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
311                        try {
312                                if ( *i ) {
313                                        if ( (*i)->get_linkage() == LinkageSpec::Intrinsic ) {
314                                                seenIntrinsic = true;
315                                        } else if ( seenIntrinsic ) {
316                                                seenIntrinsic = false; // break on this line when debugging for end of prelude
317                                        }
318
319                                        *i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) );
320                                        assert( *i );
321                                } // if
322                        } catch( SemanticError &e ) {
323                                errors.append( e );
324                        } // try
325                } // for
326                if ( ! errors.isEmpty() ) {
327                        throw errors;
328                } // if
329        }
330
331        void box( std::list< Declaration *>& translationUnit ) {
332                LayoutFunctionBuilder layoutBuilder;
333                Pass1 pass1;
334                Pass2 pass2;
335                GenericInstantiator instantiator;
336                MemberExprFixer memberFixer;
337                Pass3 pass3;
338               
339                layoutBuilder.mutateDeclarationList( translationUnit );
340                mutateTranslationUnit/*All*/( translationUnit, pass1 );
341                mutateTranslationUnit/*All*/( translationUnit, pass2 );
342                instantiator.mutateDeclarationList( translationUnit );
343                mutateTranslationUnit/*All*/( translationUnit, memberFixer );
344                mutateTranslationUnit/*All*/( translationUnit, pass3 );
345        }
346
347        ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
348
349        DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {
350                functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
351                mutateAll( functionDecl->get_oldDecls(), *this );
352                ++functionNesting;
353                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
354                --functionNesting;
355                return functionDecl;
356        }
357       
358        /// Get a list of type declarations that will affect a layout function
359        std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
360                std::list< TypeDecl * > otypeDecls;
361
362                for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
363                        if ( (*decl)->get_kind() == TypeDecl::Any ) {
364                                otypeDecls.push_back( *decl );
365                        }
366                }
367               
368                return otypeDecls;
369        }
370
371        /// Adds parameters for otype layout to a function type
372        void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
373                BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
374               
375                for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
376                        TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );
377                        layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( &paramType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
378                        layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( &paramType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
379                }
380        }
381
382        /// Builds a layout function declaration
383        FunctionDecl *buildLayoutFunctionDecl( const std::string &typeName, unsigned int functionNesting, FunctionType *layoutFnType ) {
384                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
385                // because each unit generates copies of the default routines for each aggregate.
386                FunctionDecl *layoutDecl = new FunctionDecl(
387                        "__layoutof_" + typeName, functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );
388                layoutDecl->fixUniqueId();
389                return layoutDecl;
390        }
391
392        /// Makes a unary operation
393        Expression *makeOp( const std::string &name, Expression *arg ) {
394                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
395                expr->get_args().push_back( arg );
396                return expr;
397        }
398
399        /// Makes a binary operation
400        Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {
401                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
402                expr->get_args().push_back( lhs );
403                expr->get_args().push_back( rhs );
404                return expr;
405        }
406
407        /// Returns the dereference of a local pointer variable
408        Expression *derefVar( ObjectDecl *var ) {
409                return makeOp( "*?", new VariableExpr( var ) );
410        }
411
412        /// makes an if-statement with a single-expression if-block and no then block
413        Statement *makeCond( Expression *cond, Expression *ifPart ) {
414                return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 );
415        }
416
417        /// makes a statement that assigns rhs to lhs if lhs < rhs
418        Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {
419                return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );
420        }
421
422        /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)
423        Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {
424                // check that the lhs is zeroed out to the level of rhs
425                Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );
426                // if not aligned, increment to alignment
427                Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );
428                return makeCond( ifCond, ifExpr );
429        }
430       
431        /// adds an expression to a compound statement
432        void addExpr( CompoundStmt *stmts, Expression *expr ) {
433                stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );
434        }
435
436        /// adds a statement to a compound statement
437        void addStmt( CompoundStmt *stmts, Statement *stmt ) {
438                stmts->get_kids().push_back( stmt );
439        }
440       
441        Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
442                // do not generate layout function for "empty" tag structs
443                if ( structDecl->get_members().empty() ) return structDecl;
444
445                // get parameters that can change layout, exiting early if none
446                std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
447                if ( otypeParams.empty() ) return structDecl;
448
449                // build layout function signature
450                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
451                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
452                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
453               
454                ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
455                layoutFnType->get_parameters().push_back( sizeParam );
456                ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
457                layoutFnType->get_parameters().push_back( alignParam );
458                ObjectDecl *offsetParam = new ObjectDecl( "__offsetof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
459                layoutFnType->get_parameters().push_back( offsetParam );
460                addOtypeParams( layoutFnType, otypeParams );
461
462                // build function decl
463                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl->get_name(), functionNesting, layoutFnType );
464
465                // calculate struct layout in function body
466
467                // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size
468                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) );
469                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
470                unsigned long n_members = 0;
471                bool firstMember = true;
472                for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) {
473                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
474                        assert( dwt );
475                        Type *memberType = dwt->get_type();
476
477                        if ( firstMember ) {
478                                firstMember = false;
479                        } else {
480                                // make sure all members after the first (automatically aligned at 0) are properly padded for alignment
481                                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
482                        }
483                       
484                        // place current size in the current offset index
485                        addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ),
486                                                                              derefVar( sizeParam ) ) );
487                        ++n_members;
488
489                        // add member size to current size
490                        addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
491                       
492                        // take max of member alignment and global alignment
493                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
494                }
495                // make sure the type is end-padded to a multiple of its alignment
496                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
497
498                addDeclarationAfter( layoutDecl );
499                return structDecl;
500        }
501       
502        Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
503                // do not generate layout function for "empty" tag unions
504                if ( unionDecl->get_members().empty() ) return unionDecl;
505               
506                // get parameters that can change layout, exiting early if none
507                std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
508                if ( otypeParams.empty() ) return unionDecl;
509
510                // build layout function signature
511                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
512                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
513                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
514               
515                ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
516                layoutFnType->get_parameters().push_back( sizeParam );
517                ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
518                layoutFnType->get_parameters().push_back( alignParam );
519                addOtypeParams( layoutFnType, otypeParams );
520
521                // build function decl
522                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl->get_name(), functionNesting, layoutFnType );
523
524                // calculate union layout in function body
525                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
526                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
527                for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {
528                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
529                        assert( dwt );
530                        Type *memberType = dwt->get_type();
531                       
532                        // take max member size and global size
533                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
534                       
535                        // take max of member alignment and global alignment
536                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
537                }
538                // make sure the type is end-padded to a multiple of its alignment
539                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
540
541                addDeclarationAfter( layoutDecl );
542                return unionDecl;
543        }
544       
545        ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
546
547        namespace {
548                std::string makePolyMonoSuffix( FunctionType * function, const TyVarMap &tyVars ) {
549                        std::stringstream name;
550
551                        // NOTE: this function previously used isPolyObj, which failed to produce
552                        // the correct thing in some situations. It's not clear to me why this wasn't working.
553
554                        // if the return type or a parameter type involved polymorphic types, then the adapter will need
555                        // to take those polymorphic types as pointers. Therefore, there can be two different functions
556                        // with the same mangled name, so we need to further mangle the names.
557                        for ( std::list< DeclarationWithType *>::iterator retval = function->get_returnVals().begin(); retval != function->get_returnVals().end(); ++retval ) {
558                                if ( isPolyType( (*retval)->get_type(), tyVars ) ) {
559                                        name << "P";
560                                } else {
561                                        name << "M";
562                                }
563                        }
564                        name << "_";
565                        std::list< DeclarationWithType *> &paramList = function->get_parameters();
566                        for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
567                                if ( isPolyType( (*arg)->get_type(), tyVars ) ) {
568                                        name << "P";
569                                } else {
570                                        name << "M";
571                                }
572                        } // for
573                        return name.str();
574                }
575
576                std::string mangleAdapterName( FunctionType * function, const TyVarMap &tyVars ) {
577                        return SymTab::Mangler::mangle( function ) + makePolyMonoSuffix( function, tyVars );
578                }
579
580                std::string makeAdapterName( const std::string &mangleName ) {
581                        return "_adapter" + mangleName;
582                }
583
584                Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {}
585
586                /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
587                TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) {
588                        if ( decl->get_name() == "?=?" ) {
589                                if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
590                                        if ( funType->get_parameters().size() == 2 ) {
591                                                if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
592                                                        if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
593                                                                if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
594                                                                        if ( refType->get_name() == refType2->get_name() ) {
595                                                                                return refType;
596                                                                        } // if
597                                                                } // if
598                                                        } // if
599                                                } // if
600                                        } // if
601                                } // if
602                        } // if
603                        return 0;
604                }
605               
606                /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
607                /// Only picks assignments where neither parameter is cv-qualified
608                Type *isAssignment( DeclarationWithType *decl ) {
609                        if ( decl->get_name() == "?=?" ) {
610                                if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
611                                        if ( funType->get_parameters().size() == 2 ) {
612                                                Type::Qualifiers defaultQualifiers;
613                                                Type *paramType1 = funType->get_parameters().front()->get_type();
614                                                if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0;
615                                                Type *paramType2 = funType->get_parameters().back()->get_type();
616                                                if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;
617                                               
618                                                if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {
619                                                        Type *baseType1 = pointerType->get_base();
620                                                        if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0;
621                                                        SymTab::Indexer dummy;
622                                                        if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) {
623                                                                return baseType1;
624                                                        } // if
625                                                } // if
626                                        } // if
627                                } // if
628                        } // if
629                        return 0;
630                }
631
632                void Pass1::findAssignOps( const std::list< TypeDecl *> &forall ) {
633                        // what if a nested function uses an assignment operator?
634                        // assignOps.clear();
635                        for ( std::list< TypeDecl *>::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
636                                for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
637                                        std::string typeName;
638                                        if ( TypeInstType *typeInst = isTypeInstAssignment( *assert ) ) {
639                                                assignOps[ typeInst->get_name() ] = *assert;
640                                        } // if
641                                } // for
642                        } // for
643                }
644
645                DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
646                        // if this is a polymorphic assignment function, put it in the map for this scope
647                        if ( Type *assignedType = isAssignment( functionDecl ) ) {
648                                if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) {
649                                        scopedAssignOps.insert( assignedType, functionDecl );
650                                }
651                        }
652
653                        if ( functionDecl->get_statements() ) {         // empty routine body ?
654                                doBeginScope();
655                                TyVarMap oldtyVars = scopeTyVars;
656                                std::map< std::string, DeclarationWithType *> oldassignOps = assignOps;
657                                DeclarationWithType *oldRetval = retval;
658                                bool oldUseRetval = useRetval;
659
660                                // process polymorphic return value
661                                retval = 0;
662                                if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
663                                        retval = functionDecl->get_functionType()->get_returnVals().front();
664
665                                        // give names to unnamed return values
666                                        if ( retval->get_name() == "" ) {
667                                                retval->set_name( "_retparm" );
668                                                retval->set_linkage( LinkageSpec::C );
669                                        } // if
670                                } // if
671
672                                FunctionType *functionType = functionDecl->get_functionType();
673                                makeTyVarMap( functionDecl->get_functionType(), scopeTyVars );
674                                findAssignOps( functionDecl->get_functionType()->get_forall() );
675
676                                std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
677                                std::list< FunctionType *> functions;
678                                for ( std::list< TypeDecl *>::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
679                                        for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
680                                                findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter );
681                                        } // for
682                                } // for
683                                for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
684                                        findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter );
685                                } // for
686
687                                for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
688                                        std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
689                                        if ( adapters.find( mangleName ) == adapters.end() ) {
690                                                std::string adapterName = makeAdapterName( mangleName );
691                                                adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) ) );
692                                        } // if
693                                } // for
694
695                                functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );
696
697                                scopeTyVars = oldtyVars;
698                                assignOps = oldassignOps;
699                                // std::cerr << "end FunctionDecl: ";
700                                // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
701                                //      std::cerr << i->first << " ";
702                                // }
703                                // std::cerr << "\n";
704                                retval = oldRetval;
705                                useRetval = oldUseRetval;
706                                doEndScope();
707                        } // if
708                        return functionDecl;
709                }
710
711                TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) {
712                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
713                        return Mutator::mutate( typeDecl );
714                }
715
716                Expression *Pass1::mutate( CommaExpr *commaExpr ) {
717                        bool oldUseRetval = useRetval;
718                        useRetval = false;
719                        commaExpr->set_arg1( maybeMutate( commaExpr->get_arg1(), *this ) );
720                        useRetval = oldUseRetval;
721                        commaExpr->set_arg2( maybeMutate( commaExpr->get_arg2(), *this ) );
722                        return commaExpr;
723                }
724
725                Expression *Pass1::mutate( ConditionalExpr *condExpr ) {
726                        bool oldUseRetval = useRetval;
727                        useRetval = false;
728                        condExpr->set_arg1( maybeMutate( condExpr->get_arg1(), *this ) );
729                        useRetval = oldUseRetval;
730                        condExpr->set_arg2( maybeMutate( condExpr->get_arg2(), *this ) );
731                        condExpr->set_arg3( maybeMutate( condExpr->get_arg3(), *this ) );
732                        return condExpr;
733
734                }
735
736                Expression *Pass1::makeOffsetArray( StructInstType *ty ) {
737                        std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
738
739                        // make a new temporary array
740                        Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
741                        std::stringstream lenGen;
742                        lenGen << baseMembers.size();
743                        ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) );
744                        ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) );
745
746                        // build initializer list for temporary
747                        std::list< Initializer* > inits;
748                        for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
749                                DeclarationWithType *memberDecl;
750                                if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
751                                        memberDecl = origMember->clone();
752                                } else {
753                                        memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
754                                }
755                                inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
756                        }
757                        arrayTemp->set_init( new ListInit( inits ) );
758
759                        // return variable pointing to temporary
760                        return new VariableExpr( arrayTemp );
761                }
762
763                void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
764                        Type *polyBase = hasPolyBase( parmType, exprTyVars );
765                        if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
766                                std::string sizeName = sizeofName( polyBase );
767                                if ( seenTypes.count( sizeName ) ) return;
768
769                                arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
770                                arg++;
771                                arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
772                                arg++;
773                                if ( dynamic_cast< StructInstType* >( polyBase ) ) {
774                                        if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
775                                                arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
776                                                arg++;
777                                        } else {
778                                                throw SemanticError( "Cannot pass non-struct type for generic struct" );
779                                        }
780                                }
781
782                                seenTypes.insert( sizeName );
783                        }
784                }
785
786                void Pass1::passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
787                        // pass size/align for type variables
788                        for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
789                                ResolvExpr::EqvClass eqvClass;
790                                assert( env );
791                                if ( tyParm->second == TypeDecl::Any ) {
792                                        Type *concrete = env->lookup( tyParm->first );
793                                        if ( concrete ) {
794                                                arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) );
795                                                arg++;
796                                                arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) );
797                                                arg++;
798                                        } else {
799                                                throw SemanticError( "unbound type variable in application ", appExpr );
800                                        } // if
801                                } // if
802                        } // for
803
804                        // add size/align for generic types to parameter list
805                        if ( appExpr->get_function()->get_results().empty() ) return;
806                        FunctionType *funcType = getFunctionType( appExpr->get_function()->get_results().front() );
807                        assert( funcType );
808
809                        std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin();
810                        std::list< Expression* >::const_iterator fnArg = arg;
811                        std::set< std::string > seenTypes; //< names for generic types we've seen
812
813                        // a polymorphic return type may need to be added to the argument list
814                        if ( polyRetType ) {
815                                Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
816                                passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
817                        }
818                       
819                        // add type information args for presently unseen types in parameter list
820                        for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
821                                VariableExpr *fnArgBase = getBaseVar( *fnArg );
822                                if ( ! fnArgBase || fnArgBase->get_results().empty() ) continue;
823                                passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_results().front(), arg, exprTyVars, seenTypes );
824                        }
825                }
826
827                ObjectDecl *Pass1::makeTemporary( Type *type ) {
828                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, type, 0 );
829                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
830                        return newObj;
831                }
832
833                Expression *Pass1::addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ) {
834                        // ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous.
835                        // if ( useRetval ) {
836                        //      assert( retval );
837                        //      arg = appExpr->get_args().insert( arg, new VariableExpr( retval ) );
838                        //      arg++;
839                        // } else {
840
841                        // Create temporary to hold return value of polymorphic function and produce that temporary as a result
842                        // using a comma expression.  Possibly change comma expression into statement expression "{}" for multiple
843                        // return values.
844                        ObjectDecl *newObj = makeTemporary( retType->clone() );
845                        Expression *paramExpr = new VariableExpr( newObj );
846
847                        // If the type of the temporary is not polymorphic, box temporary by taking its address;
848                        // otherwise the temporary is already boxed and can be used directly.
849                        if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) {
850                                paramExpr = new AddressExpr( paramExpr );
851                        } // if
852                        arg = appExpr->get_args().insert( arg, paramExpr ); // add argument to function call
853                        arg++;
854                        // Build a comma expression to call the function and emulate a normal return.
855                        CommaExpr *commaExpr = new CommaExpr( appExpr, new VariableExpr( newObj ) );
856                        commaExpr->set_env( appExpr->get_env() );
857                        appExpr->set_env( 0 );
858                        return commaExpr;
859                        // } // if
860                        // return appExpr;
861                }
862
863                void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) {
864                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
865                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
866                                assert(paramType && "Aggregate parameters should be type expressions");
867                                paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) );
868                        }
869                }
870
871                Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) {
872                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
873                                Type *concrete = env->lookup( typeInst->get_name() );
874                                if ( concrete == 0 ) {
875                                        throw SemanticError( "Unbound type variable " + typeInst->get_name() + " in ", appExpr );
876                                } // if
877                                return concrete;
878                        } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
879                                if ( doClone ) {
880                                        structType = structType->clone();
881                                }
882                                replaceParametersWithConcrete( appExpr, structType->get_parameters() );
883                                return structType;
884                        } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
885                                if ( doClone ) {
886                                        unionType = unionType->clone();
887                                }
888                                replaceParametersWithConcrete( appExpr, unionType->get_parameters() );
889                                return unionType;
890                        }
891                        return type;
892                }
893
894                Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ) {
895                        assert( env );
896                        Type *concrete = replaceWithConcrete( appExpr, polyType );
897                        // add out-parameter for return value   
898                        return addRetParam( appExpr, function, concrete, arg );
899                }
900
901                Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
902                        Expression *ret = appExpr;
903                        if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) {
904                                ret = addRetParam( appExpr, function, function->get_returnVals().front()->get_type(), arg );
905                        } // if
906                        std::string mangleName = mangleAdapterName( function, tyVars );
907                        std::string adapterName = makeAdapterName( mangleName );
908
909                        // cast adaptee to void (*)(), since it may have any type inside a polymorphic function
910                        Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
911                        appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) );
912                        appExpr->set_function( new NameExpr( adapterName ) );
913
914                        return ret;
915                }
916
917                void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
918                        assert( ! arg->get_results().empty() );
919                        if ( isPolyType( param, exprTyVars ) ) {
920                                if ( isPolyType( arg->get_results().front() ) ) {
921                                        // if the argument's type is polymorphic, we don't need to box again!
922                                        return;
923                                } else if ( arg->get_results().front()->get_isLvalue() ) {
924                                        // VariableExpr and MemberExpr are lvalues
925                                        arg = new AddressExpr( arg );
926                                } else {
927                                        // use type computed in unification to declare boxed variables
928                                        Type * newType = param->clone();
929                                        if ( env ) env->apply( newType );
930                                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, newType, 0 );
931                                        newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
932                                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
933                                        UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
934                                        assign->get_args().push_back( new VariableExpr( newObj ) );
935                                        assign->get_args().push_back( arg );
936                                        stmtsToAdd.push_back( new ExprStmt( noLabels, assign ) );
937                                        arg = new AddressExpr( new VariableExpr( newObj ) );
938                                } // if
939                        } // if
940                }
941
942                /// cast parameters to polymorphic functions so that types are replaced with
943                /// void * if they are type parameters in the formal type.
944                /// this gets rid of warnings from gcc.
945                void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
946                        Type * newType = formal->clone();
947                        if ( getFunctionType( newType ) ) {
948                                newType = ScrubTyVars::scrub( newType, tyVars );
949                                actual = new CastExpr( actual, newType );
950                        } // if
951                }
952
953                void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
954                        for ( std::list< DeclarationWithType *>::const_iterator param = function->get_parameters().begin(); param != function->get_parameters().end(); ++param, ++arg ) {
955                                assert( arg != appExpr->get_args().end() );
956                                addCast( *arg, (*param)->get_type(), exprTyVars );
957                                boxParam( (*param)->get_type(), *arg, exprTyVars );
958                        } // for
959                }
960
961                void Pass1::addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
962                        std::list< Expression *>::iterator cur = arg;
963                        for ( std::list< TypeDecl *>::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
964                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
965                                        InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
966                                        assert( inferParam != appExpr->get_inferParams().end() && "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" );
967                                        Expression *newExpr = inferParam->second.expr->clone();
968                                        addCast( newExpr, (*assert)->get_type(), tyVars );
969                                        boxParam( (*assert)->get_type(), newExpr, tyVars );
970                                        appExpr->get_args().insert( cur, newExpr );
971                                } // for
972                        } // for
973                }
974
975                void makeRetParm( FunctionType *funcType ) {
976                        DeclarationWithType *retParm = funcType->get_returnVals().front();
977
978                        // make a new parameter that is a pointer to the type of the old return value
979                        retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
980                        funcType->get_parameters().push_front( retParm );
981
982                        // we don't need the return value any more
983                        funcType->get_returnVals().clear();
984                }
985
986                FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ) {
987                        // actually make the adapter type
988                        FunctionType *adapter = adaptee->clone();
989                        if ( ! adapter->get_returnVals().empty() && isPolyType( adapter->get_returnVals().front()->get_type(), tyVars ) ) {
990                                makeRetParm( adapter );
991                        } // if
992                        adapter->get_parameters().push_front( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 ) );
993                        return adapter;
994                }
995
996                Expression *makeAdapterArg( DeclarationWithType *param, DeclarationWithType *arg, DeclarationWithType *realParam, const TyVarMap &tyVars ) {
997                        assert( param );
998                        assert( arg );
999                        if ( isPolyType( realParam->get_type(), tyVars ) ) {
1000                                if ( ! isPolyType( arg->get_type() ) ) {
1001                                        UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
1002                                        deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
1003                                        deref->get_results().push_back( arg->get_type()->clone() );
1004                                        return deref;
1005                                } // if
1006                        } // if
1007                        return new VariableExpr( param );
1008                }
1009
1010                void addAdapterParams( ApplicationExpr *adapteeApp, std::list< DeclarationWithType *>::iterator arg, std::list< DeclarationWithType *>::iterator param, std::list< DeclarationWithType *>::iterator paramEnd, std::list< DeclarationWithType *>::iterator realParam, const TyVarMap &tyVars ) {
1011                        UniqueName paramNamer( "_p" );
1012                        for ( ; param != paramEnd; ++param, ++arg, ++realParam ) {
1013                                if ( (*param)->get_name() == "" ) {
1014                                        (*param)->set_name( paramNamer.newName() );
1015                                        (*param)->set_linkage( LinkageSpec::C );
1016                                } // if
1017                                adapteeApp->get_args().push_back( makeAdapterArg( *param, *arg, *realParam, tyVars ) );
1018                        } // for
1019                }
1020
1021
1022
1023                FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
1024                        FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
1025                        adapterType = ScrubTyVars::scrub( adapterType, tyVars );
1026                        DeclarationWithType *adapteeDecl = adapterType->get_parameters().front();
1027                        adapteeDecl->set_name( "_adaptee" );
1028                        ApplicationExpr *adapteeApp = new ApplicationExpr( new CastExpr( new VariableExpr( adapteeDecl ), new PointerType( Type::Qualifiers(), realType ) ) );
1029                        Statement *bodyStmt;
1030
1031                        std::list< TypeDecl *>::iterator tyArg = realType->get_forall().begin();
1032                        std::list< TypeDecl *>::iterator tyParam = adapterType->get_forall().begin();
1033                        std::list< TypeDecl *>::iterator realTyParam = adaptee->get_forall().begin();
1034                        for ( ; tyParam != adapterType->get_forall().end(); ++tyArg, ++tyParam, ++realTyParam ) {
1035                                assert( tyArg != realType->get_forall().end() );
1036                                std::list< DeclarationWithType *>::iterator assertArg = (*tyArg)->get_assertions().begin();
1037                                std::list< DeclarationWithType *>::iterator assertParam = (*tyParam)->get_assertions().begin();
1038                                std::list< DeclarationWithType *>::iterator realAssertParam = (*realTyParam)->get_assertions().begin();
1039                                for ( ; assertParam != (*tyParam)->get_assertions().end(); ++assertArg, ++assertParam, ++realAssertParam ) {
1040                                        assert( assertArg != (*tyArg)->get_assertions().end() );
1041                                        adapteeApp->get_args().push_back( makeAdapterArg( *assertParam, *assertArg, *realAssertParam, tyVars ) );
1042                                } // for
1043                        } // for
1044
1045                        std::list< DeclarationWithType *>::iterator arg = realType->get_parameters().begin();
1046                        std::list< DeclarationWithType *>::iterator param = adapterType->get_parameters().begin();
1047                        std::list< DeclarationWithType *>::iterator realParam = adaptee->get_parameters().begin();
1048                        param++;                // skip adaptee parameter
1049                        if ( realType->get_returnVals().empty() ) {
1050                                addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
1051                                bodyStmt = new ExprStmt( noLabels, adapteeApp );
1052                        } else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
1053                                if ( (*param)->get_name() == "" ) {
1054                                        (*param)->set_name( "_ret" );
1055                                        (*param)->set_linkage( LinkageSpec::C );
1056                                } // if
1057                                UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
1058                                UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
1059                                deref->get_args().push_back( new CastExpr( new VariableExpr( *param++ ), new PointerType( Type::Qualifiers(), realType->get_returnVals().front()->get_type()->clone() ) ) );
1060                                assign->get_args().push_back( deref );
1061                                addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
1062                                assign->get_args().push_back( adapteeApp );
1063                                bodyStmt = new ExprStmt( noLabels, assign );
1064                        } else {
1065                                // adapter for a function that returns a monomorphic value
1066                                addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
1067                                bodyStmt = new ReturnStmt( noLabels, adapteeApp );
1068                        } // if
1069                        CompoundStmt *adapterBody = new CompoundStmt( noLabels );
1070                        adapterBody->get_kids().push_back( bodyStmt );
1071                        std::string adapterName = makeAdapterName( mangleName );
1072                        return new FunctionDecl( adapterName, DeclarationNode::NoStorageClass, LinkageSpec::C, adapterType, adapterBody, false, false );
1073                }
1074
1075                void Pass1::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
1076                        // collect a list of function types passed as parameters or implicit parameters (assertions)
1077                        std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
1078                        std::list< FunctionType *> functions;
1079                        for ( std::list< TypeDecl *>::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
1080                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
1081                                        findFunction( (*assert)->get_type(), functions, exprTyVars, needsAdapter );
1082                                } // for
1083                        } // for
1084                        for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
1085                                findFunction( (*arg)->get_type(), functions, exprTyVars, needsAdapter );
1086                        } // for
1087
1088                        // parameter function types for which an appropriate adapter has been generated.  we cannot use the types
1089                        // after applying substitutions, since two different parameter types may be unified to the same type
1090                        std::set< std::string > adaptersDone;
1091
1092                        for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
1093                                FunctionType *originalFunction = (*funType)->clone();
1094                                FunctionType *realFunction = (*funType)->clone();
1095                                std::string mangleName = SymTab::Mangler::mangle( realFunction );
1096
1097                                // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
1098                                // pre-substitution parameter function type.
1099                                if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
1100                                        adaptersDone.insert( adaptersDone.begin(), mangleName );
1101
1102                                        // apply substitution to type variables to figure out what the adapter's type should look like
1103                                        assert( env );
1104                                        env->apply( realFunction );
1105                                        mangleName = SymTab::Mangler::mangle( realFunction );
1106                                        mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
1107
1108                                        typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
1109                                        AdapterIter adapter = adapters.find( mangleName );
1110                                        if ( adapter == adapters.end() ) {
1111                                                // adapter has not been created yet in the current scope, so define it
1112                                                FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars );
1113                                                std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
1114                                                adapter = answer.first;
1115                                                stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
1116                                        } // if
1117                                        assert( adapter != adapters.end() );
1118
1119                                        // add the appropriate adapter as a parameter
1120                                        appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
1121                                } // if
1122                        } // for
1123                } // passAdapters
1124
1125                Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, Type *polyType, bool isIncr ) {
1126                        NameExpr *opExpr;
1127                        if ( isIncr ) {
1128                                opExpr = new NameExpr( "?+=?" );
1129                        } else {
1130                                opExpr = new NameExpr( "?-=?" );
1131                        } // if
1132                        UntypedExpr *addAssign = new UntypedExpr( opExpr );
1133                        if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
1134                                addAssign->get_args().push_back( address->get_arg() );
1135                        } else {
1136                                addAssign->get_args().push_back( appExpr->get_args().front() );
1137                        } // if
1138                        addAssign->get_args().push_back( new NameExpr( sizeofName( polyType ) ) );
1139                        addAssign->get_results().front() = appExpr->get_results().front()->clone();
1140                        if ( appExpr->get_env() ) {
1141                                addAssign->set_env( appExpr->get_env() );
1142                                appExpr->set_env( 0 );
1143                        } // if
1144                        appExpr->get_args().clear();
1145                        delete appExpr;
1146                        return addAssign;
1147                }
1148
1149                Expression *Pass1::handleIntrinsics( ApplicationExpr *appExpr ) {
1150                        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->get_function() ) ) {
1151                                if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
1152                                        if ( varExpr->get_var()->get_name() == "?[?]" ) {
1153                                                assert( ! appExpr->get_results().empty() );
1154                                                assert( appExpr->get_args().size() == 2 );
1155                                                Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), scopeTyVars, env );
1156                                                Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), scopeTyVars, env );
1157                                                assert( ! baseType1 || ! baseType2 ); // the arguments cannot both be polymorphic pointers
1158                                                UntypedExpr *ret = 0;
1159                                                if ( baseType1 || baseType2 ) { // one of the arguments is a polymorphic pointer
1160                                                        ret = new UntypedExpr( new NameExpr( "?+?" ) );
1161                                                } // if
1162                                                if ( baseType1 ) {
1163                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1164                                                        multiply->get_args().push_back( appExpr->get_args().back() );
1165                                                        multiply->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) );
1166                                                        ret->get_args().push_back( appExpr->get_args().front() );
1167                                                        ret->get_args().push_back( multiply );
1168                                                } else if ( baseType2 ) {
1169                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1170                                                        multiply->get_args().push_back( appExpr->get_args().front() );
1171                                                        multiply->get_args().push_back( new NameExpr( sizeofName( baseType2 ) ) );
1172                                                        ret->get_args().push_back( multiply );
1173                                                        ret->get_args().push_back( appExpr->get_args().back() );
1174                                                } // if
1175                                                if ( baseType1 || baseType2 ) {
1176                                                        ret->get_results().push_front( appExpr->get_results().front()->clone() );
1177                                                        if ( appExpr->get_env() ) {
1178                                                                ret->set_env( appExpr->get_env() );
1179                                                                appExpr->set_env( 0 );
1180                                                        } // if
1181                                                        appExpr->get_args().clear();
1182                                                        delete appExpr;
1183                                                        return ret;
1184                                                } // if
1185                                        } else if ( varExpr->get_var()->get_name() == "*?" ) {
1186                                                assert( ! appExpr->get_results().empty() );
1187                                                assert( ! appExpr->get_args().empty() );
1188                                                if ( isPolyType( appExpr->get_results().front(), scopeTyVars, env ) ) {
1189                                                        Expression *ret = appExpr->get_args().front();
1190                                                        delete ret->get_results().front();
1191                                                        ret->get_results().front() = appExpr->get_results().front()->clone();
1192                                                        if ( appExpr->get_env() ) {
1193                                                                ret->set_env( appExpr->get_env() );
1194                                                                appExpr->set_env( 0 );
1195                                                        } // if
1196                                                        appExpr->get_args().clear();
1197                                                        delete appExpr;
1198                                                        return ret;
1199                                                } // if
1200                                        } else if ( varExpr->get_var()->get_name() == "?++" || varExpr->get_var()->get_name() == "?--" ) {
1201                                                assert( ! appExpr->get_results().empty() );
1202                                                assert( appExpr->get_args().size() == 1 );
1203                                                if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) {
1204                                                        Type *tempType = appExpr->get_results().front()->clone();
1205                                                        if ( env ) {
1206                                                                env->apply( tempType );
1207                                                        } // if
1208                                                        ObjectDecl *newObj = makeTemporary( tempType );
1209                                                        VariableExpr *tempExpr = new VariableExpr( newObj );
1210                                                        UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
1211                                                        assignExpr->get_args().push_back( tempExpr->clone() );
1212                                                        if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
1213                                                                assignExpr->get_args().push_back( address->get_arg()->clone() );
1214                                                        } else {
1215                                                                assignExpr->get_args().push_back( appExpr->get_args().front()->clone() );
1216                                                        } // if
1217                                                        CommaExpr *firstComma = new CommaExpr( assignExpr, makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "?++" ) );
1218                                                        return new CommaExpr( firstComma, tempExpr );
1219                                                } // if
1220                                        } else if ( varExpr->get_var()->get_name() == "++?" || varExpr->get_var()->get_name() == "--?" ) {
1221                                                assert( ! appExpr->get_results().empty() );
1222                                                assert( appExpr->get_args().size() == 1 );
1223                                                if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) {
1224                                                        return makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "++?" );
1225                                                } // if
1226                                        } else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
1227                                                assert( ! appExpr->get_results().empty() );
1228                                                assert( appExpr->get_args().size() == 2 );
1229                                                Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), scopeTyVars, env );
1230                                                Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), scopeTyVars, env );
1231                                                if ( baseType1 && baseType2 ) {
1232                                                        UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
1233                                                        divide->get_args().push_back( appExpr );
1234                                                        divide->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) );
1235                                                        divide->get_results().push_front( appExpr->get_results().front()->clone() );
1236                                                        if ( appExpr->get_env() ) {
1237                                                                divide->set_env( appExpr->get_env() );
1238                                                                appExpr->set_env( 0 );
1239                                                        } // if
1240                                                        return divide;
1241                                                } else if ( baseType1 ) {
1242                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1243                                                        multiply->get_args().push_back( appExpr->get_args().back() );
1244                                                        multiply->get_args().push_back( new NameExpr( sizeofName( baseType1 ) ) );
1245                                                        appExpr->get_args().back() = multiply;
1246                                                } else if ( baseType2 ) {
1247                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1248                                                        multiply->get_args().push_back( appExpr->get_args().front() );
1249                                                        multiply->get_args().push_back( new NameExpr( sizeofName( baseType2 ) ) );
1250                                                        appExpr->get_args().front() = multiply;
1251                                                } // if
1252                                        } else if ( varExpr->get_var()->get_name() == "?+=?" || varExpr->get_var()->get_name() == "?-=?" ) {
1253                                                assert( ! appExpr->get_results().empty() );
1254                                                assert( appExpr->get_args().size() == 2 );
1255                                                Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env );
1256                                                if ( baseType ) {
1257                                                        UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
1258                                                        multiply->get_args().push_back( appExpr->get_args().back() );
1259                                                        multiply->get_args().push_back( new NameExpr( sizeofName( baseType ) ) );
1260                                                        appExpr->get_args().back() = multiply;
1261                                                } // if
1262                                        } // if
1263                                        return appExpr;
1264                                } // if
1265                        } // if
1266                        return 0;
1267                }
1268
1269                Expression *Pass1::mutate( ApplicationExpr *appExpr ) {
1270                        // std::cerr << "mutate appExpr: ";
1271                        // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
1272                        //      std::cerr << i->first << " ";
1273                        // }
1274                        // std::cerr << "\n";
1275                        bool oldUseRetval = useRetval;
1276                        useRetval = false;
1277                        appExpr->get_function()->acceptMutator( *this );
1278                        mutateAll( appExpr->get_args(), *this );
1279                        useRetval = oldUseRetval;
1280
1281                        assert( ! appExpr->get_function()->get_results().empty() );
1282                        PointerType *pointer = dynamic_cast< PointerType *>( appExpr->get_function()->get_results().front() );
1283                        assert( pointer );
1284                        FunctionType *function = dynamic_cast< FunctionType *>( pointer->get_base() );
1285                        assert( function );
1286
1287                        if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
1288                                return newExpr;
1289                        } // if
1290
1291                        Expression *ret = appExpr;
1292
1293                        std::list< Expression *>::iterator arg = appExpr->get_args().begin();
1294                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
1295
1296                        TyVarMap exprTyVars;
1297                        makeTyVarMap( function, exprTyVars );
1298                        ReferenceToType *polyRetType = isPolyRet( function );
1299
1300                        if ( polyRetType ) {
1301                                ret = addPolyRetParam( appExpr, function, polyRetType, arg );
1302                        } else if ( needsAdapter( function, scopeTyVars ) ) {
1303                                // std::cerr << "needs adapter: ";
1304                                // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
1305                                //      std::cerr << i->first << " ";
1306                                // }
1307                                // std::cerr << "\n";
1308                                // change the application so it calls the adapter rather than the passed function
1309                                ret = applyAdapter( appExpr, function, arg, scopeTyVars );
1310                        } // if
1311                        arg = appExpr->get_args().begin();
1312
1313                        passTypeVars( appExpr, polyRetType, arg, exprTyVars );
1314                        addInferredParams( appExpr, function, arg, exprTyVars );
1315
1316                        arg = paramBegin;
1317
1318                        boxParams( appExpr, function, arg, exprTyVars );
1319
1320                        passAdapters( appExpr, function, exprTyVars );
1321
1322                        return ret;
1323                }
1324
1325                Expression *Pass1::mutate( UntypedExpr *expr ) {
1326                        if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), scopeTyVars, env ) ) {
1327                                if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
1328                                        if ( name->get_name() == "*?" ) {
1329                                                Expression *ret = expr->get_args().front();
1330                                                expr->get_args().clear();
1331                                                delete expr;
1332                                                return ret->acceptMutator( *this );
1333                                        } // if
1334                                } // if
1335                        } // if
1336                        return PolyMutator::mutate( expr );
1337                }
1338
1339                Expression *Pass1::mutate( AddressExpr *addrExpr ) {
1340                        assert( ! addrExpr->get_arg()->get_results().empty() );
1341
1342                        bool needs = false;
1343                        if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->get_arg() ) ) {
1344                                if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), scopeTyVars, env ) ) {
1345                                        if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
1346                                                if ( name->get_name() == "*?" ) {
1347                                                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
1348                                                                assert( ! appExpr->get_function()->get_results().empty() );
1349                                                                PointerType *pointer = dynamic_cast< PointerType *>( appExpr->get_function()->get_results().front() );
1350                                                                assert( pointer );
1351                                                                FunctionType *function = dynamic_cast< FunctionType *>( pointer->get_base() );
1352                                                                assert( function );
1353                                                                needs = needsAdapter( function, scopeTyVars );
1354                                                        } // if
1355                                                } // if
1356                                        } // if
1357                                } // if
1358                        } // if
1359                        addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
1360                        if ( isPolyType( addrExpr->get_arg()->get_results().front(), scopeTyVars, env ) || needs ) {
1361                                Expression *ret = addrExpr->get_arg();
1362                                delete ret->get_results().front();
1363                                ret->get_results().front() = addrExpr->get_results().front()->clone();
1364                                addrExpr->set_arg( 0 );
1365                                delete addrExpr;
1366                                return ret;
1367                        } else {
1368                                return addrExpr;
1369                        } // if
1370                }
1371
1372                /// Wraps a function declaration in a new pointer-to-function variable expression
1373                VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) {
1374                        // line below cloned from FixFunction.cc
1375                        ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
1376                                                                  new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
1377                        functionObj->set_mangleName( functionDecl->get_mangleName() );
1378                        return new VariableExpr( functionObj );
1379                }
1380               
1381                Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
1382                        if ( retval && returnStmt->get_expr() ) {
1383                                assert( ! returnStmt->get_expr()->get_results().empty() );
1384                                // ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous.
1385                                // if ( returnStmt->get_expr()->get_results().front()->get_isLvalue() ) {
1386                                // by this point, a cast expr on a polymorphic return value is redundant
1387                                while ( CastExpr *castExpr = dynamic_cast< CastExpr *>( returnStmt->get_expr() ) ) {
1388                                        returnStmt->set_expr( castExpr->get_arg() );
1389                                        returnStmt->get_expr()->set_env( castExpr->get_env() );
1390                                        castExpr->set_env( 0 );
1391                                        castExpr->set_arg( 0 );
1392                                        delete castExpr;
1393                                } //while
1394
1395                                // find assignment operator for (polymorphic) return type
1396                                ApplicationExpr *assignExpr = 0;
1397                                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
1398                                        // find assignment operator for type variable
1399                                        std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
1400                                        if ( assignIter == assignOps.end() ) {
1401                                                throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
1402                                        } // if
1403                                        assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
1404                                } else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
1405                                        // find assignment operator for generic type
1406                                        DeclarationWithType *functionDecl = scopedAssignOps.find( refType );
1407                                        if ( ! functionDecl ) {
1408                                                throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
1409                                        }
1410
1411                                        // wrap it up in an application expression
1412                                        assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) );
1413                                        assignExpr->set_env( env->clone() );
1414
1415                                        // find each of its needed secondary assignment operators
1416                                        std::list< Expression* > &tyParams = refType->get_parameters();
1417                                        std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall();
1418                                        std::list< Expression* >::const_iterator tyIt = tyParams.begin();
1419                                        std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
1420                                        for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
1421                                                if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype)
1422
1423                                                std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
1424                                                assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
1425                                                DeclarationWithType *actualDecl = asserts.front();
1426                                                TypeInstType *actualType = isTypeInstAssignment( actualDecl );
1427                                                assert( actualType && "First assertion of type with assertions should be assignment operator" );
1428                                                TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
1429                                                assert( formalTypeExpr && "type parameters must be type expressions" );
1430                                                Type *formalType = formalTypeExpr->get_type();
1431                                                assignExpr->get_env()->add( actualType->get_name(), formalType );
1432                                               
1433                                                DeclarationWithType *assertAssign = 0;
1434                                                if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
1435                                                        std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
1436                                                        if ( assertAssignIt == assignOps.end() ) {
1437                                                                throw SemanticError( "No assignment operation found for ", formalTypeInstType );
1438                                                        }
1439                                                        assertAssign = assertAssignIt->second;
1440                                                } else {
1441                                                        assertAssign = scopedAssignOps.find( formalType );
1442                                                        if ( ! assertAssign ) {
1443                                                                throw SemanticError( "No assignment operation found for ", formalType );
1444                                                        }
1445                                                }
1446                                               
1447
1448                                                assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
1449                                                        = ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
1450                                        }
1451                                }
1452                                assert( assignExpr );
1453
1454                                // replace return statement with appropriate assignment to out parameter
1455                                Expression *retParm = new NameExpr( retval->get_name() );
1456                                retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
1457                                assignExpr->get_args().push_back( retParm );
1458                                assignExpr->get_args().push_back( returnStmt->get_expr() );
1459                                stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( assignExpr ) ) );
1460                                // } else {
1461                                //      useRetval = true;
1462                                //      stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( returnStmt->get_expr() ) ) );
1463                                //      useRetval = false;
1464                                // } // if
1465                                returnStmt->set_expr( 0 );
1466                        } else {
1467                                returnStmt->set_expr( mutateExpression( returnStmt->get_expr() ) );
1468                        } // if
1469                        return returnStmt;
1470                }
1471
1472                Type * Pass1::mutate( PointerType *pointerType ) {
1473                        TyVarMap oldtyVars = scopeTyVars;
1474                        makeTyVarMap( pointerType, scopeTyVars );
1475
1476                        Type *ret = Mutator::mutate( pointerType );
1477
1478                        scopeTyVars = oldtyVars;
1479                        return ret;
1480                }
1481
1482                Type * Pass1::mutate( FunctionType *functionType ) {
1483                        TyVarMap oldtyVars = scopeTyVars;
1484                        makeTyVarMap( functionType, scopeTyVars );
1485
1486                        Type *ret = Mutator::mutate( functionType );
1487
1488                        scopeTyVars = oldtyVars;
1489                        return ret;
1490                }
1491
1492                void Pass1::doBeginScope() {
1493                        adapters.beginScope();
1494                        scopedAssignOps.beginScope();
1495                }
1496
1497                void Pass1::doEndScope() {
1498                        adapters.endScope();
1499                        scopedAssignOps.endScope();
1500                }
1501
1502////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
1503
1504                void Pass2::addAdapters( FunctionType *functionType ) {
1505                        std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
1506                        std::list< FunctionType *> functions;
1507                        for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
1508                                Type *orig = (*arg)->get_type();
1509                                findAndReplaceFunction( orig, functions, scopeTyVars, needsAdapter );
1510                                (*arg)->set_type( orig );
1511                        }
1512                        std::set< std::string > adaptersDone;
1513                        for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
1514                                std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
1515                                if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
1516                                        std::string adapterName = makeAdapterName( mangleName );
1517                                        paramList.push_front( new ObjectDecl( adapterName, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) );
1518                                        adaptersDone.insert( adaptersDone.begin(), mangleName );
1519                                }
1520                        }
1521//  deleteAll( functions );
1522                }
1523
1524                template< typename DeclClass >
1525                DeclClass * Pass2::handleDecl( DeclClass *decl, Type *type ) {
1526                        DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
1527
1528                        return ret;
1529                }
1530
1531                DeclarationWithType * Pass2::mutate( FunctionDecl *functionDecl ) {
1532                        return handleDecl( functionDecl, functionDecl->get_functionType() );
1533                }
1534
1535                ObjectDecl * Pass2::mutate( ObjectDecl *objectDecl ) {
1536                        return handleDecl( objectDecl, objectDecl->get_type() );
1537                }
1538
1539                TypeDecl * Pass2::mutate( TypeDecl *typeDecl ) {
1540                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
1541                        if ( typeDecl->get_base() ) {
1542                                return handleDecl( typeDecl, typeDecl->get_base() );
1543                        } else {
1544                                return Mutator::mutate( typeDecl );
1545                        }
1546                }
1547
1548                TypedefDecl * Pass2::mutate( TypedefDecl *typedefDecl ) {
1549                        return handleDecl( typedefDecl, typedefDecl->get_base() );
1550                }
1551
1552                Type * Pass2::mutate( PointerType *pointerType ) {
1553                        TyVarMap oldtyVars = scopeTyVars;
1554                        makeTyVarMap( pointerType, scopeTyVars );
1555
1556                        Type *ret = Mutator::mutate( pointerType );
1557
1558                        scopeTyVars = oldtyVars;
1559                        return ret;
1560                }
1561
1562                Type *Pass2::mutate( FunctionType *funcType ) {
1563                        TyVarMap oldtyVars = scopeTyVars;
1564                        makeTyVarMap( funcType, scopeTyVars );
1565
1566                        // move polymorphic return type to parameter list
1567                        if ( isPolyRet( funcType ) ) {
1568                                DeclarationWithType *ret = funcType->get_returnVals().front();
1569                                ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
1570                                funcType->get_parameters().push_front( ret );
1571                                funcType->get_returnVals().pop_front();
1572                        }
1573
1574                        // add size/align and assertions for type parameters to parameter list
1575                        std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin();
1576                        std::list< DeclarationWithType *> inferredParams;
1577                        ObjectDecl newObj( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 );
1578                        ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0,
1579                                           new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
1580                        for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
1581                                ObjectDecl *sizeParm, *alignParm;
1582                                // add all size and alignment parameters to parameter list
1583                                if ( (*tyParm)->get_kind() == TypeDecl::Any ) {
1584                                        TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm );
1585
1586                                        sizeParm = newObj.clone();
1587                                        sizeParm->set_name( sizeofName( &parmType ) );
1588                                        last = funcType->get_parameters().insert( last, sizeParm );
1589                                        ++last;
1590
1591                                        alignParm = newObj.clone();
1592                                        alignParm->set_name( alignofName( &parmType ) );
1593                                        last = funcType->get_parameters().insert( last, alignParm );
1594                                        ++last;
1595                                }
1596                                // move all assertions into parameter list
1597                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
1598//      *assert = (*assert)->acceptMutator( *this );
1599                                        inferredParams.push_back( *assert );
1600                                }
1601                                (*tyParm)->get_assertions().clear();
1602                        }
1603
1604                        // add size/align for generic parameter types to parameter list
1605                        std::set< std::string > seenTypes; // sizeofName for generic types we've seen
1606                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
1607                                Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars );
1608                                if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
1609                                        std::string sizeName = sizeofName( polyBase );
1610                                        if ( seenTypes.count( sizeName ) ) continue;
1611
1612                                        ObjectDecl *sizeParm, *alignParm, *offsetParm;
1613                                        sizeParm = newObj.clone();
1614                                        sizeParm->set_name( sizeName );
1615                                        last = funcType->get_parameters().insert( last, sizeParm );
1616                                        ++last;
1617
1618                                        alignParm = newObj.clone();
1619                                        alignParm->set_name( alignofName( polyBase ) );
1620                                        last = funcType->get_parameters().insert( last, alignParm );
1621                                        ++last;
1622
1623                                        if ( dynamic_cast< StructInstType* >( polyBase ) ) {
1624                                                offsetParm = newPtr.clone();
1625                                                offsetParm->set_name( offsetofName( polyBase ) );
1626                                                last = funcType->get_parameters().insert( last, offsetParm );
1627                                                ++last;
1628                                        }
1629
1630                                        seenTypes.insert( sizeName );
1631                                }
1632                        }
1633
1634                        // splice assertion parameters into parameter list
1635                        funcType->get_parameters().splice( last, inferredParams );
1636                        addAdapters( funcType );
1637                        mutateAll( funcType->get_returnVals(), *this );
1638                        mutateAll( funcType->get_parameters(), *this );
1639
1640                        scopeTyVars = oldtyVars;
1641                        return funcType;
1642                }
1643
1644//////////////////////////////////////// GenericInstantiator //////////////////////////////////////////////////
1645
1646                /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
1647                bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
1648                        bool allConcrete = true;  // will finish the substitution list even if they're not all concrete
1649
1650                        // substitute concrete types for given parameters, and incomplete types for placeholders
1651                        std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
1652                        std::list< Expression* >::const_iterator param = params.begin();
1653                        for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {
1654        //                      switch ( (*baseParam)->get_kind() ) {
1655        //                      case TypeDecl::Any: {   // any type is a valid substitution here; complete types can be used to instantiate generics
1656                                        TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
1657                                        assert(paramType && "Aggregate parameters should be type expressions");
1658                                        out.push_back( paramType->clone() );
1659                                        // check that the substituted type isn't a type variable itself
1660                                        if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) {
1661                                                allConcrete = false;
1662                                        }
1663        //                              break;
1664        //                      }
1665        //                      case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
1666        //                              out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
1667        //                              break;
1668        //                      case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
1669        //                              out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
1670        //                              break;
1671        //                      }
1672                        }
1673
1674                        // if any parameters left over, not done
1675                        if ( baseParam != baseParams.end() ) return false;
1676        //              // if not enough parameters given, substitute remaining incomplete types for placeholders
1677        //              for ( ; baseParam != baseParams.end(); ++baseParam ) {
1678        //                      switch ( (*baseParam)->get_kind() ) {
1679        //                      case TypeDecl::Any:    // no more substitutions here, fail early
1680        //                              return false;
1681        //                      case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
1682        //                              out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
1683        //                              break;
1684        //                      case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
1685        //                              out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
1686        //                              break;
1687        //                      }
1688        //              }
1689
1690                        return allConcrete;
1691                }
1692
1693                /// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out
1694                void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs,
1695                                                                std::list< Declaration* >& out ) {
1696                        // substitute types into new members
1697                        TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
1698                        for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {
1699                                Declaration *newMember = (*member)->clone();
1700                                subs.apply(newMember);
1701                                out.push_back( newMember );
1702                        }
1703                }
1704
1705                Type* GenericInstantiator::mutate( StructInstType *inst ) {
1706                        // mutate subtypes
1707                        Type *mutated = Mutator::mutate( inst );
1708                        inst = dynamic_cast< StructInstType* >( mutated );
1709                        if ( ! inst ) return mutated;
1710
1711                        // exit early if no need for further mutation
1712                        if ( inst->get_parameters().empty() ) return inst;
1713                        assert( inst->get_baseParameters() && "Base struct has parameters" );
1714
1715                        // check if type can be concretely instantiated; put substitutions into typeSubs
1716                        std::list< TypeExpr* > typeSubs;
1717                        if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
1718                                deleteAll( typeSubs );
1719                                return inst;
1720                        }
1721
1722                        // make concrete instantiation of generic type
1723                        StructDecl *concDecl = lookup( inst, typeSubs );
1724                        if ( ! concDecl ) {
1725                                // set concDecl to new type, insert type declaration into statements to add
1726                                concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
1727                                substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs,        concDecl->get_members() );
1728                                DeclMutator::addDeclaration( concDecl );
1729                                insert( inst, typeSubs, concDecl );
1730                        }
1731                        StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
1732                        newInst->set_baseStruct( concDecl );
1733
1734                        deleteAll( typeSubs );
1735                        delete inst;
1736                        return newInst;
1737                }
1738
1739                Type* GenericInstantiator::mutate( UnionInstType *inst ) {
1740                        // mutate subtypes
1741                        Type *mutated = Mutator::mutate( inst );
1742                        inst = dynamic_cast< UnionInstType* >( mutated );
1743                        if ( ! inst ) return mutated;
1744
1745                        // exit early if no need for further mutation
1746                        if ( inst->get_parameters().empty() ) return inst;
1747                        assert( inst->get_baseParameters() && "Base union has parameters" );
1748
1749                        // check if type can be concretely instantiated; put substitutions into typeSubs
1750                        std::list< TypeExpr* > typeSubs;
1751                        if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
1752                                deleteAll( typeSubs );
1753                                return inst;
1754                        }
1755
1756                        // make concrete instantiation of generic type
1757                        UnionDecl *concDecl = lookup( inst, typeSubs );
1758                        if ( ! concDecl ) {
1759                                // set concDecl to new type, insert type declaration into statements to add
1760                                concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
1761                                substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
1762                                DeclMutator::addDeclaration( concDecl );
1763                                insert( inst, typeSubs, concDecl );
1764                        }
1765                        UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
1766                        newInst->set_baseUnion( concDecl );
1767
1768                        deleteAll( typeSubs );
1769                        delete inst;
1770                        return newInst;
1771                }
1772
1773        //      /// Gets the base struct or union declaration for a member expression; NULL if not applicable
1774        //      AggregateDecl* getMemberBaseDecl( MemberExpr *memberExpr ) {
1775        //              // get variable for member aggregate
1776        //              VariableExpr *varExpr = dynamic_cast< VariableExpr* >( memberExpr->get_aggregate() );
1777        //              if ( ! varExpr ) return NULL;
1778        //
1779        //              // get object for variable
1780        //              ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
1781        //              if ( ! objectDecl ) return NULL;
1782        //
1783        //              // get base declaration from object type
1784        //              Type *objectType = objectDecl->get_type();
1785        //              StructInstType *structType = dynamic_cast< StructInstType* >( objectType );
1786        //              if ( structType ) return structType->get_baseStruct();
1787        //              UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType );
1788        //              if ( unionType ) return unionType->get_baseUnion();
1789        //
1790        //              return NULL;
1791        //      }
1792        //
1793        //      /// Finds the declaration with the given name, returning decls.end() if none such
1794        //      std::list< Declaration* >::const_iterator findDeclNamed( const std::list< Declaration* > &decls, const std::string &name ) {
1795        //              for( std::list< Declaration* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
1796        //                      if ( (*decl)->get_name() == name ) return decl;
1797        //              }
1798        //              return decls.end();
1799        //      }
1800        //
1801        //      Expression* Instantiate::mutate( MemberExpr *memberExpr ) {
1802        //              // mutate, exiting early if no longer MemberExpr
1803        //              Expression *expr = Mutator::mutate( memberExpr );
1804        //              memberExpr = dynamic_cast< MemberExpr* >( expr );
1805        //              if ( ! memberExpr ) return expr;
1806        //
1807        //              // get declaration of member and base declaration of member, exiting early if not found
1808        //              AggregateDecl *memberBase = getMemberBaseDecl( memberExpr );
1809        //              if ( ! memberBase ) return memberExpr;
1810        //              DeclarationWithType *memberDecl = memberExpr->get_member();
1811        //              std::list< Declaration* >::const_iterator baseIt = findDeclNamed( memberBase->get_members(), memberDecl->get_name() );
1812        //              if ( baseIt == memberBase->get_members().end() ) return memberExpr;
1813        //              DeclarationWithType *baseDecl = dynamic_cast< DeclarationWithType* >( *baseIt );
1814        //              if ( ! baseDecl ) return memberExpr;
1815        //
1816        //              // check if stated type of the member is not the type of the member's declaration; if so, need a cast
1817        //              // this *SHOULD* be safe, I don't think anything but the void-replacements I put in for dtypes would make it past the typechecker
1818        //              SymTab::Indexer dummy;
1819        //              if ( ResolvExpr::typesCompatible( memberDecl->get_type(), baseDecl->get_type(), dummy ) ) return memberExpr;
1820        //              else return new CastExpr( memberExpr, memberDecl->get_type() );
1821        //      }
1822
1823                void GenericInstantiator::doBeginScope() {
1824                        DeclMutator::doBeginScope();
1825                        instantiations.beginScope();
1826                }
1827
1828                void GenericInstantiator::doEndScope() {
1829                        DeclMutator::doEndScope();
1830                        instantiations.endScope();
1831                }
1832
1833////////////////////////////////////////// MemberExprFixer ////////////////////////////////////////////////////
1834
1835                template< typename DeclClass >
1836                DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) {
1837                        TyVarMap oldtyVars = scopeTyVars;
1838                        makeTyVarMap( type, scopeTyVars );
1839
1840                        DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
1841
1842                        scopeTyVars = oldtyVars;
1843                        return ret;
1844                }
1845
1846                ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {
1847                        return handleDecl( objectDecl, objectDecl->get_type() );
1848                }
1849
1850                DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {
1851                        return handleDecl( functionDecl, functionDecl->get_functionType() );
1852                }
1853
1854                TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {
1855                        return handleDecl( typedefDecl, typedefDecl->get_base() );
1856                }
1857
1858                TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {
1859                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
1860                        return Mutator::mutate( typeDecl );
1861                }
1862
1863                Type * MemberExprFixer::mutate( PointerType *pointerType ) {
1864                        TyVarMap oldtyVars = scopeTyVars;
1865                        makeTyVarMap( pointerType, scopeTyVars );
1866
1867                        Type *ret = Mutator::mutate( pointerType );
1868
1869                        scopeTyVars = oldtyVars;
1870                        return ret;
1871                }
1872
1873                Type * MemberExprFixer::mutate( FunctionType *functionType ) {
1874                        TyVarMap oldtyVars = scopeTyVars;
1875                        makeTyVarMap( functionType, scopeTyVars );
1876
1877                        Type *ret = Mutator::mutate( functionType );
1878
1879                        scopeTyVars = oldtyVars;
1880                        return ret;
1881                }
1882
1883                Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) {
1884                        if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
1885                                if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {
1886                                        // change initialization of a polymorphic value object
1887                                        // to allocate storage with alloca
1888                                        Type *declType = objectDecl->get_type();
1889                                        UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
1890                                        alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) );
1891
1892                                        delete objectDecl->get_init();
1893
1894                                        std::list<Expression*> designators;
1895                                        objectDecl->set_init( new SingleInit( alloc, designators ) );
1896                                }
1897                        }
1898                        return Mutator::mutate( declStmt );
1899                }
1900
1901                /// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
1902                long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
1903                        long i = 0;
1904                        for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) {
1905                                if ( memberDecl->get_name() != (*decl)->get_name() ) continue;
1906
1907                                if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
1908                                        if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty()
1909                                             || memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
1910                                        else continue;
1911                                } else return i;
1912                        }
1913                        return -1;
1914                }
1915
1916                /// Returns an index expression into the offset array for a type
1917                Expression *makeOffsetIndex( Type *objectType, long i ) {
1918                        std::stringstream offset_namer;
1919                        offset_namer << i;
1920                        ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );
1921                        UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
1922                        fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) );
1923                        fieldOffset->get_args().push_back( fieldIndex );
1924                        return fieldOffset;
1925                }
1926
1927                /// Returns an expression dereferenced n times
1928                Expression *makeDerefdVar( Expression *derefdVar, long n ) {
1929                        for ( int i = 1; i < n; ++i ) {
1930                                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
1931                                derefExpr->get_args().push_back( derefdVar );
1932                                derefdVar = derefExpr;
1933                        }
1934                        return derefdVar;
1935                }
1936               
1937                Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
1938                        // mutate, exiting early if no longer MemberExpr
1939                        Expression *expr = Mutator::mutate( memberExpr );
1940                        memberExpr = dynamic_cast< MemberExpr* >( expr );
1941                        if ( ! memberExpr ) return expr;
1942
1943                        // get declaration for base struct, exiting early if not found
1944                        int varDepth;
1945                        VariableExpr *varExpr = getBaseVar( memberExpr->get_aggregate(), &varDepth );
1946                        if ( ! varExpr ) return memberExpr;
1947                        ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
1948                        if ( ! objectDecl ) return memberExpr;
1949
1950                        // only mutate member expressions for polymorphic types
1951                        int tyDepth;
1952                        Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
1953                        if ( ! objectType ) return memberExpr;
1954
1955                        Expression *newMemberExpr = 0;
1956                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
1957                                // look up offset index
1958                                long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() );
1959                                if ( i == -1 ) return memberExpr;
1960
1961                                // replace member expression with pointer to base plus offset
1962                                UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
1963                                fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) );
1964                                fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
1965                                newMemberExpr = fieldLoc;
1966                        } else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
1967                                // union members are all at offset zero, so build appropriately-dereferenced variable
1968                                newMemberExpr = makeDerefdVar( varExpr->clone(), varDepth );
1969                        } else return memberExpr;
1970                        assert( newMemberExpr );
1971
1972                        Type *memberType = memberExpr->get_member()->get_type();
1973                        if ( ! isPolyType( memberType, scopeTyVars ) ) {
1974                                // 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
1975                                CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) );
1976                                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
1977                                derefExpr->get_args().push_back( ptrCastExpr );
1978                                newMemberExpr = derefExpr;
1979                        }
1980
1981                        delete memberExpr;
1982                        return newMemberExpr;
1983                }
1984
1985                Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) {
1986                        // mutate, exiting early if no longer OffsetofExpr
1987                        Expression *expr = Mutator::mutate( offsetofExpr );
1988                        offsetofExpr = dynamic_cast< OffsetofExpr* >( expr );
1989                        if ( ! offsetofExpr ) return expr;
1990
1991                        // only mutate expressions for polymorphic structs/unions
1992                        Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars );
1993                        if ( ! ty ) return offsetofExpr;
1994
1995                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
1996                                // replace offsetof expression by index into offset array
1997                                long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() );
1998                                if ( i == -1 ) return offsetofExpr;
1999
2000                                Expression *offsetInd = makeOffsetIndex( ty, i );
2001                                delete offsetofExpr;
2002                                return offsetInd;
2003                        } else if ( dynamic_cast< UnionInstType* >( ty ) ) {
2004                                // all union members are at offset zero
2005                                delete offsetofExpr;
2006                                return new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::string("0") ) );
2007                        } else return offsetofExpr;
2008                }
2009
2010////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
2011
2012                template< typename DeclClass >
2013                DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
2014                        TyVarMap oldtyVars = scopeTyVars;
2015                        makeTyVarMap( type, scopeTyVars );
2016
2017                        DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
2018                        ScrubTyVars::scrub( decl, scopeTyVars );
2019
2020                        scopeTyVars = oldtyVars;
2021                        return ret;
2022                }
2023
2024                ObjectDecl * Pass3::mutate( ObjectDecl *objectDecl ) {
2025                        return handleDecl( objectDecl, objectDecl->get_type() );
2026                }
2027
2028                DeclarationWithType * Pass3::mutate( FunctionDecl *functionDecl ) {
2029                        return handleDecl( functionDecl, functionDecl->get_functionType() );
2030                }
2031
2032                TypedefDecl * Pass3::mutate( TypedefDecl *typedefDecl ) {
2033                        return handleDecl( typedefDecl, typedefDecl->get_base() );
2034                }
2035
2036                TypeDecl * Pass3::mutate( TypeDecl *typeDecl ) {
2037//   Initializer *init = 0;
2038//   std::list< Expression *> designators;
2039//   scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
2040//   if ( typeDecl->get_base() ) {
2041//     init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators );
2042//   }
2043//   return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init );
2044
2045                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
2046                        return Mutator::mutate( typeDecl );
2047                }
2048
2049                Type * Pass3::mutate( PointerType *pointerType ) {
2050                        TyVarMap oldtyVars = scopeTyVars;
2051                        makeTyVarMap( pointerType, scopeTyVars );
2052
2053                        Type *ret = Mutator::mutate( pointerType );
2054
2055                        scopeTyVars = oldtyVars;
2056                        return ret;
2057                }
2058
2059                Type * Pass3::mutate( FunctionType *functionType ) {
2060                        TyVarMap oldtyVars = scopeTyVars;
2061                        makeTyVarMap( functionType, scopeTyVars );
2062
2063                        Type *ret = Mutator::mutate( functionType );
2064
2065                        scopeTyVars = oldtyVars;
2066                        return ret;
2067                }
2068        } // anonymous namespace
2069} // namespace GenPoly
2070
2071// Local Variables: //
2072// tab-width: 4 //
2073// mode: c++ //
2074// compile-command: "make install" //
2075// End: //
Note: See TracBrowser for help on using the repository browser.