source: src/GenPoly/Box.cc@ 1afda5a2

ADT ast-experimental
Last change on this file since 1afda5a2 was d18540f, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Cleaning old box pass for easier translation. Cleaning unused code out of Pass3, it was tracking information it never used.

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