source: src/GenPoly/Box.cc@ a805100

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

Cleaning old box pass for easier translation. Refactor to remove unneeded parameters. In the future someone may have to put them back, but that flexibility is not being used now.

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