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