source: src/GenPoly/Box.cc@ 78a0b88

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 78a0b88 was 9b18044, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Handle TraitDecl in Box Pass2

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