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

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 1d5deea was 07de76b, checked in by Peter A. Buhr <pabuhr@…>, 6 years ago

remove file TypeVar.h* and put TypeVar::Kind into TypeDecl, move LinkageSpec.* from directory Parse to SynTree

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