source: src/GenPoly/Box.cc@ 17e5e2b

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 17e5e2b was 5802a4f, checked in by Rob Schluntz <rschlunt@…>, 9 years ago

remove assignment to polymorphic return values in Box

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