Changes in / [e50d9cb8:0bdfcc3]
- Files:
-
- 5 deleted
- 12 edited
-
libcfa/src/Makefile.am (modified) (1 diff)
-
libcfa/src/bits/defs.hfa (modified) (1 diff)
-
libcfa/src/concurrency/invoke.h (modified) (3 diffs)
-
libcfa/src/concurrency/kernel.hfa (modified) (1 diff)
-
libcfa/src/concurrency/kernel/startup.cfa (modified) (4 diffs)
-
libcfa/src/concurrency/once.hfa (deleted)
-
libcfa/src/concurrency/thread.cfa (modified) (1 diff)
-
libcfa/src/containers/lockfree.hfa (modified) (5 diffs)
-
src/AST/Pass.impl.hpp (modified) (2 diffs)
-
src/Common/PassVisitor.impl.h (modified) (2 diffs)
-
src/GenPoly/Box.cc (modified) (17 diffs)
-
src/GenPoly/GenPoly.cc (modified) (2 diffs)
-
src/GenPoly/InstantiateGenericNew.cpp (modified) (2 diffs)
-
tests/.expect/loop-inc.txt (deleted)
-
tests/concurrent/.expect/once.txt (deleted)
-
tests/concurrent/once.cfa (deleted)
-
tests/loop-inc.cfa (deleted)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/Makefile.am
re50d9cb8 r0bdfcc3 111 111 concurrency/invoke.h \ 112 112 concurrency/future.hfa \ 113 concurrency/once.hfa \114 113 concurrency/kernel/fwd.hfa \ 115 114 concurrency/mutex_stmt.hfa -
libcfa/src/bits/defs.hfa
re50d9cb8 r0bdfcc3 31 31 #define __cfa_anonymous_object(x) inline struct x 32 32 #define __cfa_dlink1(x) dlink(x) 33 #define __cfa_dlink2(x, name) inline struct name { inline dlink(x); }34 33 #else 35 34 #define __cfa_anonymous_object(x) struct x __cfa_anonymous_object 36 35 #define __cfa_dlink1(x) struct { struct x * next; struct x * back; } 37 #define __cfa_dlink2(x, name) struct { struct x * next; struct x * back; } __dlink ## name38 36 #endif 39 37 -
libcfa/src/concurrency/invoke.h
re50d9cb8 r0bdfcc3 195 195 struct __monitor_group_t monitors; 196 196 197 // intrusive link fields, used for locks, monitors and any user defined data structure 198 // default link fields for dlist 197 // used to put threads on dlist data structure 199 198 __cfa_dlink1(thread$) user_link; 200 199 201 // secondary intrusive link fields, used for global cluster list 202 // default link fields for dlist 203 __cfa_dlink2(thread$, cltr_link); 200 struct { 201 struct thread$ * next; 202 struct thread$ * prev; 203 } node; 204 204 205 205 // used to store state between clh lock/unlock … … 230 230 #ifdef __cforall 231 231 extern "Cforall" { 232 static inline thread$ * volatile & ?`next ( thread$ * this ) {233 return this->user_link.next;234 }235 232 236 233 static inline thread$ *& get_next( thread$ & this ) __attribute__((const)) { 237 234 return this.user_link.next; 235 } 236 237 static inline [thread$ *&, thread$ *& ] __get( thread$ & this ) __attribute__((const)) { 238 return this.node.[next, prev]; 238 239 } 239 240 … … 243 244 return result; 244 245 } 245 246 P9_EMBEDDED(thread$, thread$.cltr_link)247 P9_EMBEDDED(thread$.cltr_link, dlink(thread$))248 246 249 247 static inline void ?{}(__monitor_group_t & this) { -
libcfa/src/concurrency/kernel.hfa
re50d9cb8 r0bdfcc3 256 256 // List of threads 257 257 __spinlock_t thread_list_lock; 258 dlist(struct thread$, thread$.cltr_link) threads;258 __dllist_t(struct thread$) threads; 259 259 unsigned int nthreads; 260 260 -
libcfa/src/concurrency/kernel/startup.cfa
re50d9cb8 r0bdfcc3 535 535 #endif 536 536 537 node.next = 0p; 538 node.prev = 0p; 537 539 doregister(curr_cluster, this); 538 540 … … 657 659 #endif 658 660 659 threads{ };661 threads{ __get }; 660 662 661 663 io.arbiter = create(); … … 737 739 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2); 738 740 cltr->nthreads += 1; 739 insert_first(cltr->threads, thrd);741 push_front(cltr->threads, thrd); 740 742 unlock (cltr->thread_list_lock); 741 743 } … … 743 745 void unregister( cluster * cltr, thread$ & thrd ) { 744 746 lock (cltr->thread_list_lock __cfaabi_dbg_ctx2); 745 { 746 tytagref( dlink(thread$), dlink(thread$) ) ?`inner( thread$ & this ) = void; 747 with( DLINK_VIA( thread$, thread$.cltr_link ) ) 748 remove( thrd ); 749 cltr->nthreads -= 1; 750 } 747 remove(cltr->threads, thrd ); 748 cltr->nthreads -= 1; 751 749 unlock(cltr->thread_list_lock); 752 750 } -
libcfa/src/concurrency/thread.cfa
re50d9cb8 r0bdfcc3 54 54 #endif 55 55 56 node.next = 0p; 57 node.prev = 0p; 58 56 59 clh_node = malloc( ); 57 60 *clh_node = false; -
libcfa/src/containers/lockfree.hfa
re50d9cb8 r0bdfcc3 142 142 143 143 static inline void ?{}(poison_list(T) & this) { this.head = 0p; } 144 static inline bool is_poisoned( const poison_list(T) & this ) { return 1p == this.head; }145 144 146 145 static inline forall(| { T * volatile & ?`next ( T * ); }) … … 148 147 // Adds an element to the list 149 148 // Multi-Thread Safe, Lock-Free 150 boolpush(poison_list(T) & this, T * elem) __attribute__((artificial));151 boolpush(poison_list(T) & this, T * elem) {149 T * push(poison_list(T) & this, T * elem) __attribute__((artificial)); 150 T * push(poison_list(T) & this, T * elem) { 152 151 /* paranoid */ verify(0p == (elem`next)); 153 152 __atomic_store_n( &elem`next, (T*)1p, __ATOMIC_RELAXED ); … … 157 156 for() { 158 157 // check if it's poisoned 159 if(expected == 1p) return false;158 if(expected == 1p) return 0p; 160 159 161 160 // try to CAS the elem in … … 163 162 // We managed to exchange in, we are done 164 163 165 // We should never succeed the CAS if it's poisonned and the elem should be 1p. 166 /* paranoid */ verify( expected != 1p ); 167 /* paranoid */ verify( elem`next == 1p ); 164 // We should never succeed the CAS if it's poisonned. 165 /* paranoid */ verify( expected != 1p ); 168 166 169 167 // If we aren't the first, we need to tell the person before us 170 168 // No need to 171 169 elem`next = expected; 172 return true;170 return expected; 173 171 } 174 172 } … … 192 190 T * poison(poison_list(T) & this) { 193 191 T * ret = __atomic_exchange_n( &this.head, (T*)1p, __ATOMIC_SEQ_CST ); 194 /* paranoid */ verify f( ret != (T*)1p, "Poison list %p poisoned more than once!", &this);192 /* paranoid */ verify( ret != (T*)1p ); 195 193 return ret; 196 194 } -
src/AST/Pass.impl.hpp
re50d9cb8 r0bdfcc3 617 617 maybe_accept( node, &FunctionDecl::returns ); 618 618 maybe_accept( node, &FunctionDecl::type ); 619 maybe_accept( node, &FunctionDecl::attributes );620 619 // First remember that we are now within a function. 621 620 ValueGuard< bool > oldInFunction( inFunction ); … … 626 625 atFunctionTop = true; 627 626 maybe_accept( node, &FunctionDecl::stmts ); 627 maybe_accept( node, &FunctionDecl::attributes ); 628 628 } 629 629 } -
src/Common/PassVisitor.impl.h
re50d9cb8 r0bdfcc3 607 607 indexerAddId( &func ); 608 608 maybeMutate_impl( node->type, *this ); 609 maybeMutate_impl( node->attributes, *this );610 609 // First remember that we are now within a function. 611 610 ValueGuard< bool > oldInFunction( inFunction ); … … 616 615 atFunctionTop = true; 617 616 maybeMutate_impl( node->statements, *this ); 617 maybeMutate_impl( node->attributes, *this ); 618 618 } 619 619 } -
src/GenPoly/Box.cc
re50d9cb8 r0bdfcc3 68 68 /// Adds layout-generation functions to polymorphic types. 69 69 class LayoutFunctionBuilder final : public WithDeclsToAdd, public WithVisitorRef<LayoutFunctionBuilder>, public WithShortCircuiting { 70 // Current level of nested functions: 71 unsigned int functionNesting = 0; 70 72 public: 73 void previsit( FunctionDecl *functionDecl ); 71 74 void previsit( StructDecl *structDecl ); 72 75 void previsit( UnionDecl *unionDecl ); … … 234 237 ////////////////////////////////// LayoutFunctionBuilder //////////////////////////////////////////// 235 238 239 void LayoutFunctionBuilder::previsit( FunctionDecl *functionDecl ) { 240 visit_children = false; 241 maybeAccept( functionDecl->get_functionType(), *visitor ); 242 ++functionNesting; 243 maybeAccept( functionDecl->get_statements(), *visitor ); 244 --functionNesting; 245 } 246 236 247 /// Get a list of type declarations that will affect a layout function 237 248 std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) { … … 260 271 261 272 /// Builds a layout function declaration 262 FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, bool isInFunction, FunctionType *layoutFnType ) {273 FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, unsigned int functionNesting, FunctionType *layoutFnType ) { 263 274 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 264 275 // because each unit generates copies of the default routines for each aggregate. 265 276 FunctionDecl *layoutDecl = new FunctionDecl( layoutofName( typeDecl ), 266 isInFunction? Type::StorageClasses() : Type::StorageClasses( Type::Static ),277 functionNesting > 0 ? Type::StorageClasses() : Type::StorageClasses( Type::Static ), 267 278 LinkageSpec::AutoGen, layoutFnType, new CompoundStmt(), 268 279 std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) ); … … 336 347 337 348 // build function decl 338 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, isInFunction(), layoutFnType );349 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, functionNesting, layoutFnType ); 339 350 340 351 // calculate struct layout in function body … … 343 354 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant::from_ulong( 0 ) ) ) ); 344 355 addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant::from_ulong( 1 ) ) ) ); 345 for ( auto index_member : enumerate( structDecl->members ) ) { 346 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( index_member.val ); 356 unsigned long n_members = 0; 357 bool firstMember = true; 358 for ( Declaration* member : structDecl->get_members() ) { 359 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( member ); 347 360 assert( dwt ); 348 361 Type *memberType = dwt->get_type(); 349 362 350 if ( 0 < index_member.idx ) { 363 if ( firstMember ) { 364 firstMember = false; 365 } else { 351 366 // make sure all members after the first (automatically aligned at 0) are properly padded for alignment 352 367 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) ); … … 354 369 355 370 // place current size in the current offset index 356 addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from_ulong( index_member.idx) ) ),371 addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from_ulong( n_members ) ) ), 357 372 derefVar( sizeParam ) ) ); 373 ++n_members; 358 374 359 375 // add member size to current size … … 390 406 391 407 // build function decl 392 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, isInFunction(), layoutFnType );408 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, functionNesting, layoutFnType ); 393 409 394 410 // calculate union layout in function body … … 550 566 if ( tyParam.second.isComplete ) { 551 567 Type *concrete = env->lookup( tyParam.first ); 552 // If there is an unbound type variable, it should have detected already. 553 assertf( concrete, "Unbound type variable: %s in: %s", 554 toCString( tyParam.first ), toCString( *env ) ); 555 556 arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) ); 557 arg++; 558 arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) ); 559 arg++; 568 if ( concrete ) { 569 arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) ); 570 arg++; 571 arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) ); 572 arg++; 573 } else { 574 // xxx - should this be an assertion? 575 SemanticError( appExpr, toString( *env, "\nunbound type variable: ", tyParam.first, " in application " ) ); 576 } // if 560 577 } // if 561 578 } // for … … 621 638 622 639 void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) { 623 for ( Expression * const param : params) {624 TypeExpr *paramType = dynamic_cast< TypeExpr* >( param );640 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) { 641 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 625 642 assertf(paramType, "Aggregate parameters should be type expressions"); 626 643 paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) ); … … 675 692 } 676 693 677 // find instances of polymorphic type parameters678 struct PolyFinder {679 const TyVarMap * tyVars = nullptr;680 bool found = false;681 682 void previsit( TypeInstType * t ) {683 if ( isPolyType( t, *tyVars ) ) {684 found = true;685 }686 }687 };688 689 // true if there is an instance of a polymorphic type parameter in t690 bool hasPolymorphism( Type * t, const TyVarMap &tyVars ) {691 PassVisitor<PolyFinder> finder;692 finder.pass.tyVars = &tyVars;693 maybeAccept( t, finder );694 return finder.pass.found;695 }696 697 /// cast parameters to polymorphic functions so that types are replaced with698 /// void * if they are type parameters in the formal type.699 /// this gets rid of warnings from gcc.700 void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {701 // type contains polymorphism, but isn't exactly a polytype, in which case it702 // has some real actual type (e.g. unsigned int) and casting to void * is wrong703 if ( hasPolymorphism( formal, tyVars ) && ! isPolyType( formal, tyVars ) ) {704 Type * newType = formal->clone();705 newType = ScrubTyVars::scrub( newType, tyVars );706 actual = new CastExpr( actual, newType );707 } // if708 }709 710 694 void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) { 711 695 assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() ); 712 addCast( arg, param, exprTyVars );713 696 if ( ! needsBoxing( param, arg->result, exprTyVars, env ) ) return; 714 697 … … 741 724 } 742 725 726 // find instances of polymorphic type parameters 727 struct PolyFinder { 728 const TyVarMap * tyVars = nullptr; 729 bool found = false; 730 731 void previsit( TypeInstType * t ) { 732 if ( isPolyType( t, *tyVars ) ) { 733 found = true; 734 } 735 } 736 }; 737 738 // true if there is an instance of a polymorphic type parameter in t 739 bool hasPolymorphism( Type * t, const TyVarMap &tyVars ) { 740 PassVisitor<PolyFinder> finder; 741 finder.pass.tyVars = &tyVars; 742 maybeAccept( t, finder ); 743 return finder.pass.found; 744 } 745 746 /// cast parameters to polymorphic functions so that types are replaced with 747 /// void * if they are type parameters in the formal type. 748 /// this gets rid of warnings from gcc. 749 void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) { 750 // type contains polymorphism, but isn't exactly a polytype, in which case it 751 // has some real actual type (e.g. unsigned int) and casting to void * is wrong 752 if ( hasPolymorphism( formal, tyVars ) && ! isPolyType( formal, tyVars ) ) { 753 Type * newType = formal->clone(); 754 newType = ScrubTyVars::scrub( newType, tyVars ); 755 actual = new CastExpr( actual, newType ); 756 } // if 757 } 758 743 759 void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) { 744 for ( DeclarationWithType * param : function->parameters) {745 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() );746 boxParam( param->get_type(), *arg, exprTyVars );747 ++arg;760 for ( std::list< DeclarationWithType *>::const_iterator param = function->get_parameters().begin(); param != function->parameters.end(); ++param, ++arg ) { 761 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() ); 762 addCast( *arg, (*param)->get_type(), exprTyVars ); 763 boxParam( (*param)->get_type(), *arg, exprTyVars ); 748 764 } // for 749 765 } … … 751 767 void Pass1::addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) { 752 768 std::list< Expression *>::iterator cur = arg; 753 for ( Type Decl * const tyVar : functionType->forall) {754 for ( DeclarationWithType * const assert : tyVar->assertions) {755 InferredParams::const_iterator inferParam = appExpr->inferParams.find( assert->get_uniqueId() );756 assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( assert ).c_str(), toString( appExpr ).c_str() );769 for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) { 770 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->assertions.begin(); assert != (*tyVar)->assertions.end(); ++assert ) { 771 InferredParams::const_iterator inferParam = appExpr->inferParams.find( (*assert)->get_uniqueId() ); 772 assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() ); 757 773 Expression *newExpr = inferParam->second.expr->clone(); 758 boxParam( assert->get_type(), newExpr, tyVars ); 774 addCast( newExpr, (*assert)->get_type(), tyVars ); 775 boxParam( (*assert)->get_type(), newExpr, tyVars ); 759 776 appExpr->get_args().insert( cur, newExpr ); 760 777 } // for … … 786 803 assert( param ); 787 804 assert( arg ); 788 if ( isPolyType( realParam->get_type(), tyVars ) 789 && ! isPolyType( arg->get_type() ) ) { 790 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 791 deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) ); 792 deref->result = arg->get_type()->clone(); 793 return deref; 805 if ( isPolyType( realParam->get_type(), tyVars ) ) { 806 if ( ! isPolyType( arg->get_type() ) ) { 807 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 808 deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) ); 809 deref->result = arg->get_type()->clone(); 810 return deref; 811 } // if 794 812 } // if 795 813 return new VariableExpr( param ); … … 1127 1145 } 1128 1146 1129 bool isPolyDeref( UntypedExpr * expr, TyVarMap const & scopeTyVars, TypeSubstitution const * env) {1147 Expression * Pass1::postmutate( UntypedExpr *expr ) { 1130 1148 if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) { 1131 1149 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) { 1132 1150 if ( name->name == "*?" ) { 1133 return true; 1151 Expression *ret = expr->args.front(); 1152 expr->args.clear(); 1153 delete expr; 1154 return ret; 1134 1155 } // if 1135 1156 } // if 1136 1157 } // if 1137 return false;1138 }1139 1140 Expression * Pass1::postmutate( UntypedExpr *expr ) {1141 if ( isPolyDeref( expr, scopeTyVars, env ) ) {1142 Expression *ret = expr->args.front();1143 expr->args.clear();1144 delete expr;1145 return ret;1146 }1147 1158 return expr; 1148 1159 } … … 1154 1165 bool needs = false; 1155 1166 if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->arg ) ) { 1156 if ( isPolyDeref( expr, scopeTyVars, env ) ) { 1157 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->args.front() ) ) { 1158 assert( appExpr->function->result ); 1159 FunctionType *function = getFunctionType( appExpr->function->result ); 1160 assert( function ); 1161 needs = needsAdapter( function, scopeTyVars ); 1167 if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) { 1168 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) { 1169 if ( name->name == "*?" ) { 1170 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->args.front() ) ) { 1171 assert( appExpr->function->result ); 1172 FunctionType *function = getFunctionType( appExpr->function->result ); 1173 assert( function ); 1174 needs = needsAdapter( function, scopeTyVars ); 1175 } // if 1176 } // if 1162 1177 } // if 1163 1178 } // if … … 1211 1226 std::list< DeclarationWithType *> ¶mList = functionType->parameters; 1212 1227 std::list< FunctionType *> functions; 1213 for ( DeclarationWithType * const arg : functionType->parameters ) {1228 for ( DeclarationWithType * const arg : functionType->parameters ) { 1214 1229 Type *orig = arg->get_type(); 1215 1230 findAndReplaceFunction( orig, functions, scopeTyVars, needsAdapter ); … … 1432 1447 1433 1448 if(!expect_func_type) { 1449 GuardAction( [this]() { 1450 knownLayouts.endScope(); 1451 knownOffsets.endScope(); 1452 }); 1434 1453 // If this is the first function type we see 1435 1454 // Then it's the type of the declaration and we care about it 1436 GuardScope( *this ); 1455 knownLayouts.beginScope(); 1456 knownOffsets.beginScope(); 1437 1457 } 1438 1458 -
src/GenPoly/GenPoly.cc
re50d9cb8 r0bdfcc3 120 120 const ast::Type * replaceTypeInst(const ast::Type * type, const ast::TypeSubstitution * env) { 121 121 if (!env) return type; 122 if ( auto typeInst = dynamic_cast<const ast::TypeInstType*>(type)) {122 if (auto typeInst = dynamic_cast<const ast::TypeInstType*> (type)) { 123 123 auto newType = env->lookup(typeInst); 124 124 if (newType) return newType; … … 229 229 auto var = typeVars.find( *inst ); 230 230 if ( var != typeVars.end() && var->second.isComplete ) { 231 return inst; 231 232 232 } 233 233 } else if ( auto inst = dynamic_cast<ast::StructInstType const *>( type ) ) { -
src/GenPoly/InstantiateGenericNew.cpp
re50d9cb8 r0bdfcc3 10 10 // Created On : Tue Aug 16 10:51:00 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Oct 31 16:48:00 202213 // Update Count : 112 // Last Modified On : Tue Sep 13 16:03:00 2022 13 // Update Count : 0 14 14 // 15 15 … … 378 378 // Ptr(int) p; 379 379 // int i; 380 // The original expression:381 380 // p.x = &i; 382 // Becomes the expression/declaration: 383 // int *& _dtype_static_member_0; 384 // (_dtype_static_member_0 = (int**)&p.x, 385 // _dtype_static_member_0) = &i; 386 387 // The declaration is simple: 381 // becomes 382 // int *& _dtype_static_member_0 = (int **)&p.x; 383 // _dtype_static_member_0 = &i; 388 384 static UniqueName tmpNamer( "_dtype_static_member_" ); 385 ast::Expr * init = new ast::CastExpr( location, 386 new ast::AddressExpr( location, memberExpr ), 387 new ast::PointerType( ast::deepCopy( concType ) ), 388 ast::ExplicitCast 389 ); 389 390 ast::ObjectDecl * tmp = new ast::ObjectDecl( location, 390 391 tmpNamer.newName(), 391 392 new ast::ReferenceType( concType ), 392 n ullptr,393 new ast::SingleInit( location, init ), 393 394 ast::Storage::Classes(), 394 395 ast::Linkage::C 395 396 ); 396 397 stmtsToAddBefore.push_back( new ast::DeclStmt( location, tmp ) ); 397 398 // The expression is more complex, uses references and reference / 399 // pointer parity. But breaking it up risks reordering. 400 return new ast::CommaExpr( location, 401 ast::UntypedExpr::createAssign( location, 402 new ast::VariableExpr( location, tmp ), 403 new ast::CastExpr( location, 404 new ast::AddressExpr( location, memberExpr ), 405 new ast::PointerType( ast::deepCopy( concType ) ), 406 ast::ExplicitCast 407 ) 408 ), 409 new ast::VariableExpr( location, tmp ) 410 ); 398 return new ast::VariableExpr( location, tmp ); 411 399 } else { 412 400 // Here, it can simply add a cast to actual types.
Note:
See TracChangeset
for help on using the changeset viewer.