Changes in / [b3d413b:8135d4c]
- Location:
- src
- Files:
-
- 1 added
- 130 edited
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/CodeGenerator.cc
rb3d413b r8135d4c 192 192 genCommaList( aggDecl->get_parameters().begin(), aggDecl->get_parameters().end() ); 193 193 output << ")" << endl; 194 output << indent; 194 195 } 195 196 … … 332 333 void CodeGenerator::visit( __attribute__((unused)) ConstructorInit * init ){ 333 334 assertf( ! genC, "ConstructorInit nodes should not reach code generation." ); 334 // xxx - generate something reasonable for constructor/destructor pairs 335 output << "<ctorinit>"; 335 // pseudo-output for constructor/destructor pairs 336 output << "<ctorinit>{" << std::endl << ++indent << "ctor: "; 337 maybeAccept( init->get_ctor(), *this ); 338 output << ", " << std::endl << indent << "dtor: "; 339 maybeAccept( init->get_dtor(), *this ); 340 output << std::endl << --indent << "}"; 336 341 } 337 342 … … 347 352 if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( varExpr->get_var()->get_name(), opInfo ) ) { 348 353 std::list< Expression* >::iterator arg = applicationExpr->get_args().begin(); 349 switch ( opInfo.type ) {350 case OT_PREFIXASSIGN:351 case OT_POSTFIXASSIGN:352 case OT_INFIXASSIGN:353 case OT_CTOR:354 case OT_DTOR:355 {356 assert( arg != applicationExpr->get_args().end() );357 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) {358 // remove & from first assignment/ctor argument359 *arg = addrExpr->get_arg();360 } else {361 // no address-of operator, so must be a pointer - add dereference362 // NOTE: if the assertion starts to trigger, check that the application expr isn't being shared.363 // Since its arguments are modified here, this assertion most commonly triggers when the application364 // is visited multiple times.365 UntypedExpr * newExpr = new UntypedExpr( new NameExpr( "*?" ) );366 newExpr->get_args().push_back( *arg );367 Type * type = InitTweak::getPointerBase( (*arg)->get_result() );368 assertf( type, "First argument to a derefence must be a pointer. Ensure that expressions are not being shared." );369 newExpr->set_result( type->clone() );370 *arg = newExpr;371 } // if372 break;373 }374 375 default:376 // do nothing377 ;378 } // switch379 380 354 switch ( opInfo.type ) { 381 355 case OT_INDEX: … … 584 558 if ( castExpr->get_result()->isVoid() ) { 585 559 output << "(void)" ; 586 } else if ( ! castExpr->get_result()->get_lvalue() ) { 587 // at least one result type of cast, but not an lvalue 560 } else { 561 // at least one result type of cast. 562 // Note: previously, lvalue casts were skipped. Since it's now impossible for the user to write 563 // an lvalue cast, this has been taken out. 588 564 output << "("; 589 565 output << genType( castExpr->get_result(), "", pretty, genC ); 590 566 output << ")"; 591 } else {592 // otherwise, the cast is to an lvalue type, so the cast should be dropped, since the result of a cast is593 // never an lvalue in C594 567 } // if 595 568 castExpr->get_arg()->accept( *this ); … … 706 679 extension( commaExpr ); 707 680 output << "("; 681 if ( genC ) { 682 // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings. 683 commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) ); 684 } 708 685 commaExpr->get_arg1()->accept( *this ); 709 686 output << " , "; 710 687 commaExpr->get_arg2()->accept( *this ); 711 688 output << ")"; 689 } 690 691 void CodeGenerator::visit( TupleAssignExpr * tupleExpr ) { 692 assertf( ! genC, "TupleAssignExpr should not reach code generation." ); 693 tupleExpr->stmtExpr->accept( *this ); 712 694 } 713 695 … … 759 741 output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")"; 760 742 compLitExpr->get_initializer()->accept( *this ); 743 } 744 745 void CodeGenerator::visit( UniqueExpr * unqExpr ) { 746 assertf( ! genC, "Unique expressions should not reach code generation." ); 747 output << "unq<" << unqExpr->get_id() << ">{ "; 748 unqExpr->get_expr()->accept( *this ); 749 output << " }"; 761 750 } 762 751 … … 770 759 for ( Statement * stmt : stmts ) { 771 760 updateLocation( stmt ); 772 761 output << printLabels( stmt->get_labels() ); 773 762 if ( i+1 == numStmts ) { 774 763 // last statement in a statement expression needs to be handled specially - … … 815 804 void CodeGenerator::visit( ExprStmt * exprStmt ) { 816 805 assert( exprStmt ); 817 Expression * expr = exprStmt->get_expr();818 806 if ( genC ) { 819 807 // cast the top-level expression to void to reduce gcc warnings. 820 expr = new CastExpr( expr);821 } 822 expr ->accept( *this );808 exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) ); 809 } 810 exprStmt->get_expr()->accept( *this ); 823 811 output << ";"; 824 812 } -
src/CodeGen/CodeGenerator.h
rb3d413b r8135d4c 74 74 virtual void visit( CommaExpr *commaExpr ); 75 75 virtual void visit( CompoundLiteralExpr *compLitExpr ); 76 virtual void visit( UniqueExpr * ); 77 virtual void visit( TupleAssignExpr * tupleExpr ); 76 78 virtual void visit( UntypedTupleExpr *tupleExpr ); 77 79 virtual void visit( TupleExpr *tupleExpr ); -
src/CodeGen/GenType.cc
rb3d413b r8135d4c 37 37 virtual void visit( PointerType *pointerType ); 38 38 virtual void visit( ArrayType *arrayType ); 39 virtual void visit( ReferenceType *refType ); 39 40 virtual void visit( StructInstType *structInst ); 40 41 virtual void visit( UnionInstType *unionInst ); … … 145 146 void GenType::visit( ArrayType *arrayType ) { 146 147 genArray( arrayType->get_qualifiers(), arrayType->get_base(), arrayType->get_dimension(), arrayType->get_isVarLen(), arrayType->get_isStatic() ); 148 } 149 150 void GenType::visit( ReferenceType *refType ) { 151 assert( refType->get_base() != 0); 152 assertf( ! genC, "Reference types should not reach code generation." ); 153 handleQualifiers( refType ); 154 typeString = "&" + typeString; 155 refType->get_base()->accept( *this ); 147 156 } 148 157 … … 278 287 typeString = "_Atomic " + typeString; 279 288 } // if 289 if ( type->get_lvalue() && ! genC ) { 290 // when not generating C code, print lvalue for debugging. 291 typeString = "lvalue " + typeString; 292 } 280 293 } 281 294 } // namespace CodeGen -
src/CodeGen/OperatorTable.cc
rb3d413b r8135d4c 14 14 // 15 15 16 #include <map> // for map, _Rb_tree_const_iterator, map<>::const_iterator 17 #include <utility> // for pair 16 #include <algorithm> // for any_of 17 #include <map> // for map, _Rb_tree_const_iterator, map<>::const_iterator 18 #include <utility> // for pair 18 19 19 20 #include "OperatorTable.h" … … 93 94 } // if 94 95 } 96 97 /// determines if a given function name is one of the operator types between [begin, end) 98 template<typename Iterator> 99 bool isOperatorType( const std::string & funcName, Iterator begin, Iterator end ) { 100 OperatorInfo info; 101 if ( operatorLookup( funcName, info ) ) { 102 return std::find( begin, end, info.type ) != end; 103 } 104 return false; 105 } 106 107 bool isConstructor( const std::string & funcName ) { 108 static OperatorType types[] = { OT_CTOR }; 109 return isOperatorType( funcName, std::begin(types), std::end(types) ); 110 } 111 112 bool isDestructor( const std::string & funcName ) { 113 static OperatorType types[] = { OT_DTOR }; 114 return isOperatorType( funcName, std::begin(types), std::end(types) ); 115 } 116 117 bool isAssignment( const std::string & funcName ) { 118 static OperatorType types[] = { OT_PREFIXASSIGN, OT_POSTFIXASSIGN, OT_INFIXASSIGN }; 119 return isOperatorType( funcName, std::begin(types), std::end(types) ); 120 } 121 122 bool isCtorDtor( const std::string & funcName ) { 123 static OperatorType types[] = { OT_CTOR, OT_DTOR }; 124 return isOperatorType( funcName, std::begin(types), std::end(types) ); 125 } 126 127 bool isCtorDtorAssign( const std::string & funcName ) { 128 static OperatorType types[] = { OT_CTOR, OT_DTOR, OT_PREFIXASSIGN, OT_POSTFIXASSIGN, OT_INFIXASSIGN }; 129 return isOperatorType( funcName, std::begin(types), std::end(types) ); 130 } 95 131 } // namespace CodeGen 96 132 -
src/CodeGen/OperatorTable.h
rb3d413b r8135d4c 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // OperatorTable.h -- 7 // OperatorTable.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 42 42 43 43 bool operatorLookup( std::string funcName, OperatorInfo &info ); 44 45 bool isConstructor( const std::string & ); 46 bool isDestructor( const std::string & ); 47 bool isAssignment( const std::string & ); 48 bool isCtorDtor( const std::string & ); 49 bool isCtorDtorAssign( const std::string & ); 44 50 } // namespace CodeGen 45 51 -
src/Common/PassVisitor.h
rb3d413b r8135d4c 116 116 virtual void visit( PointerType *pointerType ) override final; 117 117 virtual void visit( ArrayType *arrayType ) override final; 118 virtual void visit( ReferenceType *referenceType ) override final; 118 119 virtual void visit( FunctionType *functionType ) override final; 119 120 virtual void visit( StructInstType *aggregateUseType ) override final; … … 202 203 virtual Type* mutate( PointerType *pointerType ) override final; 203 204 virtual Type* mutate( ArrayType *arrayType ) override final; 205 virtual Type* mutate( ReferenceType *referenceType ) override final; 204 206 virtual Type* mutate( FunctionType *functionType ) override final; 205 207 virtual Type* mutate( StructInstType *aggregateUseType ) override final; -
src/Common/PassVisitor.impl.h
rb3d413b r8135d4c 792 792 793 793 template< typename pass_type > 794 void PassVisitor< pass_type >::visit( ReferenceType * node ) { 795 VISIT_BODY( node ); 796 } 797 798 template< typename pass_type > 794 799 void PassVisitor< pass_type >::visit( FunctionType * node ) { 795 800 VISIT_BODY( node ); … … 1129 1134 1130 1135 template< typename pass_type > 1136 Type * PassVisitor< pass_type >::mutate( ReferenceType * node ) { 1137 MUTATE_BODY( Type, node ); 1138 } 1139 1140 template< typename pass_type > 1131 1141 Type * PassVisitor< pass_type >::mutate( FunctionType * node ) { 1132 1142 MUTATE_BODY( Type, node ); -
src/Common/utility.h
rb3d413b r8135d4c 310 310 template< typename T1, typename T2 > 311 311 struct group_iterate_t { 312 group_iterate_t( const T1 & v1, const T2 & v2 ) : args(v1, v2) {313 assertf( v1.size() == v2.size(), "group iteration requires containers of the same size.");312 group_iterate_t( bool skipBoundsCheck, const T1 & v1, const T2 & v2 ) : args(v1, v2) { 313 assertf(skipBoundsCheck || v1.size() == v2.size(), "group iteration requires containers of the same size: <%lu, %lu>.", v1.size(), v2.size()); 314 314 }; 315 315 … … 336 336 }; 337 337 338 /// performs bounds check to ensure that all arguments are of the same length. 338 339 template< typename... Args > 339 340 group_iterate_t<Args...> group_iterate( Args &&... args ) { 340 return group_iterate_t<Args...>(std::forward<Args>( args )...); 341 return group_iterate_t<Args...>(false, std::forward<Args>( args )...); 342 } 343 344 /// does not perform a bounds check - requires user to ensure that iteration terminates when appropriate. 345 template< typename... Args > 346 group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) { 347 return group_iterate_t<Args...>(true, std::forward<Args>( args )...); 341 348 } 342 349 -
src/Concurrency/Keywords.cc
rb3d413b r8135d4c 21 21 #include "Common/SemanticError.h" // for SemanticError 22 22 #include "Common/utility.h" // for deleteAll, map_range 23 #include "InitTweak/InitTweak.h" // for isConstructor 23 #include "CodeGen/OperatorTable.h" // for isConstructor 24 #include "InitTweak/InitTweak.h" // for getPointerBase 24 25 #include "Parser/LinkageSpec.h" // for Cforall 25 26 #include "SymTab/AddVisit.h" // for acceptAndAdd … … 289 290 LinkageSpec::Cforall, 290 291 nullptr, 291 new PointerType(292 new ReferenceType( 292 293 noQualifiers, 293 294 new StructInstType( … … 445 446 446 447 //Makes sure it's not a copy 447 PointerType* pty = dynamic_cast< PointerType * >( ty );448 if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg );448 ReferenceType* rty = dynamic_cast< ReferenceType * >( ty ); 449 if( ! rty ) throw SemanticError( "Mutex argument must be of reference type ", arg ); 449 450 450 451 //Make sure the we are pointing directly to a type 451 Type* base = pty->get_base(); 452 if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg ); 452 Type* base = rty->get_base(); 453 if( dynamic_cast< ReferenceType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg ); 454 if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg ); 453 455 454 456 //Make sure that typed isn't mutex … … 520 522 Visitor::visit(decl); 521 523 522 if( ! InitTweak::isConstructor(decl->get_name()) ) return;524 if( ! CodeGen::isConstructor(decl->get_name()) ) return; 523 525 524 526 DeclarationWithType * param = decl->get_functionType()->get_parameters().front(); 525 auto ptr = dynamic_cast< PointerType * >( param->get_type() ); 526 // if( ptr ) std::cerr << "FRED1" << std::endl; 527 auto type = dynamic_cast< StructInstType * >( ptr->get_base() ); 527 auto type = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) ); 528 528 // if( type ) std::cerr << "FRED2" << std::endl; 529 529 if( type && type->get_baseStruct()->is_thread() ) { -
src/GenPoly/Box.cc
rb3d413b r8135d4c 25 25 26 26 #include "Box.h" 27 28 #include "CodeGen/OperatorTable.h" 27 29 #include "Common/ScopedMap.h" // for ScopedMap, ScopedMap<>::iter... 28 30 #include "Common/SemanticError.h" // for SemanticError … … 564 566 // To compound the issue, the right side can be *x, etc. because of lvalue-returning functions 565 567 if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) { 566 if ( InitTweak::isAssignment( InitTweak::getFunctionName( assign ) ) ) {568 if ( CodeGen::isAssignment( InitTweak::getFunctionName( assign ) ) ) { 567 569 assert( assign->get_args().size() == 2 ); 568 570 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) { … … 604 606 } 605 607 } else { 606 throw SemanticError( "Cannot pass non-struct type for generic struct ");608 throw SemanticError( "Cannot pass non-struct type for generic struct: ", argBaseType ); 607 609 } 608 610 } … … 1019 1021 } // if 1020 1022 if ( baseType1 || baseType2 ) { 1023 delete ret->get_result(); 1021 1024 ret->set_result( appExpr->get_result()->clone() ); 1022 1025 if ( appExpr->get_env() ) { … … 1032 1035 assert( ! appExpr->get_args().empty() ); 1033 1036 if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) { 1037 // remove dereference from polymorphic types since they are boxed. 1034 1038 Expression *ret = appExpr->get_args().front(); 1039 // fix expr type to remove pointer 1035 1040 delete ret->get_result(); 1036 1041 ret->set_result( appExpr->get_result()->clone() ); … … 1122 1127 1123 1128 assert( appExpr->get_function()->has_result() ); 1124 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );1125 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );1129 FunctionType * function = getFunctionType( appExpr->get_function()->get_result() ); 1130 assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->get_function()->get_result() ).c_str() ); 1126 1131 1127 1132 if ( Expression *newExpr = handleIntrinsics( appExpr ) ) { … … 1200 1205 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) { 1201 1206 assert( appExpr->get_function()->has_result() ); 1202 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );1203 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base());1207 FunctionType *function = getFunctionType( appExpr->get_function()->get_result() ); 1208 assert( function ); 1204 1209 needs = needsAdapter( function, scopeTyVars ); 1205 1210 } // if … … 1210 1215 // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward 1211 1216 // out of the if condition. 1217 addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) ); 1218 // ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment 1212 1219 bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env ); 1213 addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );1214 1220 if ( polytype || needs ) { 1215 1221 Expression *ret = addrExpr->get_arg(); … … 1278 1284 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) { 1279 1285 std::string adapterName = makeAdapterName( mangleName ); 1280 paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) ); 1286 // adapter may not be used in body, pass along with unused attribute. 1287 paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0, { new Attribute( "unused" ) } ) ); 1281 1288 adaptersDone.insert( adaptersDone.begin(), mangleName ); 1282 1289 } … … 1384 1391 std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin(); 1385 1392 std::list< DeclarationWithType *> inferredParams; 1386 ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 ); 1393 // size/align/offset parameters may not be used in body, pass along with unused attribute. 1394 ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, 1395 { new Attribute( "unused" ) } ); 1387 1396 ObjectDecl newPtr( "", Type::StorageClasses(), LinkageSpec::C, 0, 1388 1397 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 ); … … 1407 1416 for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) { 1408 1417 // *assert = (*assert)->acceptMutator( *this ); 1418 // assertion parameters may not be used in body, pass along with unused attribute. 1419 (*assert)->get_attributes().push_back( new Attribute( "unused" ) ); 1409 1420 inferredParams.push_back( *assert ); 1410 1421 } -
src/GenPoly/InstantiateGeneric.cc
rb3d413b r8135d4c 162 162 /// Should not make use of type environment to replace types of function parameter and return values. 163 163 bool inFunctionType = false; 164 /// Index of current member, used to recreate MemberExprs with the member from an instantiation 165 int memberIndex = -1; 164 166 GenericInstantiator() : instantiations(), dtypeStatics(), typeNamer("_conc_") {} 165 167 … … 167 169 Type* postmutate( UnionInstType *inst ); 168 170 169 void premutate( __attribute__((unused)) FunctionType * ftype ) { 171 // fix MemberExprs to use the member from the instantiation 172 void premutate( MemberExpr * memberExpr ); 173 Expression * postmutate( MemberExpr * memberExpr ); 174 175 void premutate( FunctionType * ) { 170 176 GuardValue( inFunctionType ); 171 177 inFunctionType = true; … … 414 420 } 415 421 422 namespace { 423 bool isGenericType( Type * t ) { 424 if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) { 425 return ! inst->parameters.empty(); 426 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) { 427 return ! inst->parameters.empty(); 428 } 429 return false; 430 } 431 432 AggregateDecl * getAggr( Type * t ) { 433 if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) { 434 return inst->baseStruct; 435 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) { 436 return inst->baseUnion; 437 } 438 assertf( false, "Non-aggregate type: %s", toString( t ).c_str() ); 439 } 440 } 441 442 void GenericInstantiator::premutate( MemberExpr * memberExpr ) { 443 GuardValue( memberIndex ); 444 memberIndex = -1; 445 if ( isGenericType( memberExpr->aggregate->result ) ) { 446 // find the location of the member 447 AggregateDecl * aggr = getAggr( memberExpr->aggregate->result ); 448 std::list< Declaration * > & members = aggr->members; 449 memberIndex = std::distance( members.begin(), std::find( members.begin(), members.end(), memberExpr->member ) ); 450 assertf( memberIndex < (int)members.size(), "Could not find member %s in generic type %s", toString( memberExpr->member ).c_str(), toString( memberExpr->aggregate ).c_str() ); 451 } 452 } 453 454 Expression * GenericInstantiator::postmutate( MemberExpr * memberExpr ) { 455 if ( memberIndex != -1 ) { 456 // using the location from the generic type, find the member in the instantiation and rebuild the member expression 457 AggregateDecl * aggr = getAggr( memberExpr->aggregate->result ); 458 assertf( memberIndex < (int)aggr->members.size(), "Instantiation somehow has fewer members than the generic type." ); 459 Declaration * member = *std::next( aggr->members.begin(), memberIndex ); 460 assertf( member->name == memberExpr->member->name, "Instantiation has different member order than the generic type. %s / %s", toString( member ).c_str(), toString( memberExpr->member ).c_str() ); 461 DeclarationWithType * field = safe_dynamic_cast< DeclarationWithType * >( member ); 462 MemberExpr * ret = new MemberExpr( field, memberExpr->aggregate->clone() ); 463 std::swap( ret->env, memberExpr->env ); 464 delete memberExpr; 465 return ret; 466 } 467 return memberExpr; 468 } 469 416 470 void GenericInstantiator::beginScope() { 417 471 instantiations.beginScope(); -
src/GenPoly/Lvalue.cc
rb3d413b r8135d4c 17 17 #include <string> // for string 18 18 19 #include "Common/PassVisitor.h" 19 20 #include "Common/SemanticError.h" // for SemanticError 20 21 #include "GenPoly.h" // for isPolyType 21 22 #include "Lvalue.h" 23 22 24 #include "Parser/LinkageSpec.h" // for Spec, isBuiltin, Intrinsic 23 25 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet 24 26 #include "ResolvExpr/Unify.h" // for unify 27 #include "ResolvExpr/typeops.h" 28 #include "SymTab/Autogen.h" 25 29 #include "SymTab/Indexer.h" // for Indexer 26 30 #include "SynTree/Declaration.h" // for Declaration, FunctionDecl … … 31 35 #include "SynTree/Visitor.h" // for Visitor, acceptAll 32 36 37 #if 0 38 #define PRINT(x) x 39 #else 40 #define PRINT(x) 41 #endif 42 33 43 namespace GenPoly { 34 44 namespace { 35 /// Replace uses of lvalue returns with appropriate pointers 36 class Pass1 : public Mutator { 37 public: 38 Pass1(); 39 40 virtual Expression *mutate( ApplicationExpr *appExpr ); 41 virtual Statement *mutate( ReturnStmt *appExpr ); 42 virtual DeclarationWithType *mutate( FunctionDecl *funDecl ); 43 private: 44 DeclarationWithType* retval; 45 }; 46 47 /// Replace declarations of lvalue returns with appropriate pointers 48 class Pass2 : public Visitor { 49 public: 50 virtual void visit( FunctionType *funType ); 51 private: 45 // TODO: fold this into the general createDeref function?? 46 Expression * mkDeref( Expression * arg ) { 47 if ( SymTab::dereferenceOperator ) { 48 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator ); 49 deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) ); 50 Type * base = InitTweak::getPointerBase( arg->get_result() ); 51 assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() ); 52 ApplicationExpr * ret = new ApplicationExpr( deref, { arg } ); 53 delete ret->get_result(); 54 ret->set_result( base->clone() ); 55 ret->get_result()->set_lvalue( true ); 56 return ret; 57 } else { 58 return UntypedExpr::createDeref( arg ); 59 } 60 } 61 62 struct ReferenceConversions final { 63 Expression * postmutate( CastExpr * castExpr ); 64 Expression * postmutate( AddressExpr * addrExpr ); 65 }; 66 67 /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced. 68 struct FixIntrinsicArgs final { 69 Expression * postmutate( ApplicationExpr * appExpr ); 70 }; 71 72 struct FixIntrinsicResult final { 73 Expression * postmutate( ApplicationExpr * appExpr ); 74 }; 75 76 /// Replace reference types with pointer types 77 struct ReferenceTypeElimination final { 78 Type * postmutate( ReferenceType * refType ); 52 79 }; 53 80 … … 55 82 /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues 56 83 /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c) 57 class GeneralizedLvalue : public Mutator { 58 typedef Mutator Parent; 59 60 virtual Expression * mutate( MemberExpr * memExpr ); 61 virtual Expression * mutate( AddressExpr * addressExpr ); 84 struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> { 85 Expression * postmutate( AddressExpr * addressExpr ); 86 Expression * postmutate( MemberExpr * memExpr ); 62 87 63 88 template<typename Func> 64 89 Expression * applyTransformation( Expression * expr, Expression * arg, Func mkExpr ); 65 90 }; 91 92 /// Removes redundant &*/*& pattern that this pass can generate 93 struct CollapseAddrDeref final { 94 Expression * postmutate( AddressExpr * addressExpr ); 95 Expression * postmutate( ApplicationExpr * appExpr ); 96 }; 97 98 struct AddrRef final : public WithGuards { 99 void premutate( AddressExpr * addrExpr ); 100 Expression * postmutate( AddressExpr * addrExpr ); 101 void premutate( Expression * expr ); 102 103 bool first = true; 104 bool current = false; 105 int refDepth = 0; 106 }; 66 107 } // namespace 67 108 109 static bool referencesEliminated = false; 110 // used by UntypedExpr::createDeref to determine whether result type of dereference should be ReferenceType or value type. 111 bool referencesPermissable() { 112 return ! referencesEliminated; 113 } 114 68 115 void convertLvalue( std::list< Declaration* >& translationUnit ) { 69 Pass1 p1; 70 Pass2 p2; 71 GeneralizedLvalue genLval; 72 mutateAll( translationUnit, p1 ); 73 acceptAll( translationUnit, p2 ); 116 PassVisitor<ReferenceConversions> refCvt; 117 PassVisitor<ReferenceTypeElimination> elim; 118 PassVisitor<GeneralizedLvalue> genLval; 119 PassVisitor<FixIntrinsicArgs> fixer; 120 PassVisitor<CollapseAddrDeref> collapser; 121 PassVisitor<AddrRef> addrRef; 122 PassVisitor<FixIntrinsicResult> intrinsicResults; 123 mutateAll( translationUnit, intrinsicResults ); 124 mutateAll( translationUnit, addrRef ); 125 mutateAll( translationUnit, refCvt ); 126 mutateAll( translationUnit, fixer ); 127 mutateAll( translationUnit, collapser ); 74 128 mutateAll( translationUnit, genLval ); 129 mutateAll( translationUnit, elim ); // last because other passes need reference types to work 130 131 // from this point forward, no other pass should create reference types. 132 referencesEliminated = true; 75 133 } 76 134 77 135 Expression * generalizedLvalue( Expression * expr ) { 78 GeneralizedLvaluegenLval;136 PassVisitor<GeneralizedLvalue> genLval; 79 137 return expr->acceptMutator( genLval ); 80 138 } 81 139 82 140 namespace { 83 Type* isLvalueRet( FunctionType *function ) { 84 if ( function->get_returnVals().empty() ) return 0; 85 Type *ty = function->get_returnVals().front()->get_type(); 86 return ty->get_lvalue() ? ty : 0; 87 } 88 89 bool isIntrinsicApp( ApplicationExpr *appExpr ) { 90 if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) { 91 return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic; 92 } else { 93 return false; 94 } // if 95 } 96 97 Pass1::Pass1() { 98 } 99 100 DeclarationWithType * Pass1::mutate( FunctionDecl *funcDecl ) { 101 if ( funcDecl->get_statements() ) { 102 DeclarationWithType* oldRetval = retval; 103 retval = 0; 104 if ( ! LinkageSpec::isBuiltin( funcDecl->get_linkage() ) && isLvalueRet( funcDecl->get_functionType() ) ) { 105 retval = funcDecl->get_functionType()->get_returnVals().front(); 106 } 107 // fix expressions and return statements in this function 108 funcDecl->set_statements( funcDecl->get_statements()->acceptMutator( *this ) ); 109 retval = oldRetval; 110 } // if 111 return funcDecl; 112 } 113 114 Expression * Pass1::mutate( ApplicationExpr *appExpr ) { 115 appExpr->get_function()->acceptMutator( *this ); 116 mutateAll( appExpr->get_args(), *this ); 117 118 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 119 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 120 121 Type *funType = isLvalueRet( function ); 122 if ( funType && ! isIntrinsicApp( appExpr ) ) { 123 Expression *expr = appExpr; 124 Type *appType = appExpr->get_result(); 125 if ( isPolyType( funType ) && ! isPolyType( appType ) ) { 126 // make sure cast for polymorphic type is inside dereference 127 expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) ); 128 } 129 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 130 deref->set_result( appType->clone() ); 131 appExpr->set_result( new PointerType( Type::Qualifiers(), appType ) ); 132 deref->get_args().push_back( expr ); 133 return deref; 134 } else { 135 return appExpr; 136 } // if 137 } 138 139 Statement * Pass1::mutate(ReturnStmt *retStmt) { 140 if ( retval && retStmt->get_expr() ) { 141 if ( retStmt->get_expr()->get_result()->get_lvalue() ) { 142 // ***** Code Removal ***** because casts may be stripped already 143 144 // strip casts because not allowed to take address of cast 145 // while ( CastExpr *castExpr = dynamic_cast< CastExpr* >( retStmt->get_expr() ) ) { 146 // retStmt->set_expr( castExpr->get_arg() ); 147 // retStmt->get_expr()->set_env( castExpr->get_env() ); 148 // castExpr->set_env( 0 ); 149 // castExpr->set_arg( 0 ); 150 // delete castExpr; 151 // } // while 152 retStmt->set_expr( new AddressExpr( retStmt->get_expr()->acceptMutator( *this ) ) ); 141 // true for intrinsic function calls that return a reference 142 bool isIntrinsicReference( Expression * expr ) { 143 if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) { 144 std::string fname = InitTweak::getFunctionName( untyped ); 145 // known intrinsic-reference prelude functions 146 return fname == "*?" || fname == "?[?]"; 147 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 148 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) { 149 // use type of return variable rather than expr result type, since it may have been changed to a pointer type 150 FunctionType * ftype = GenPoly::getFunctionType( func->get_type() ); 151 Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type(); 152 return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret ); 153 } 154 } 155 return false; 156 } 157 158 Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) { 159 if ( isIntrinsicReference( appExpr ) ) { 160 // eliminate reference types from intrinsic applications - now they return lvalues 161 Type * result = appExpr->get_result(); 162 appExpr->set_result( result->stripReferences()->clone() ); 163 appExpr->get_result()->set_lvalue( true ); 164 Expression * ret = new CastExpr( appExpr, result ); 165 ret->set_env( appExpr->get_env() ); 166 appExpr->set_env( nullptr ); 167 return ret; 168 } 169 return appExpr; 170 } 171 172 Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) { 173 // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments. 174 if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) { 175 FunctionType * ftype = GenPoly::getFunctionType( function->get_type() ); 176 assertf( ftype, "Function declaration does not have function type." ); 177 // can be of differing lengths only when function is variadic 178 assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." ); 179 180 181 unsigned int i = 0; 182 const unsigned int end = ftype->get_parameters().size(); 183 for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) { 184 if (i == end) break; 185 Expression *& arg = std::get<0>( p ); 186 Type * formal = std::get<1>( p )->get_type(); 187 PRINT( 188 std::cerr << "pair<0>: " << arg << std::endl; 189 std::cerr << "pair<1>: " << formal << std::endl; 190 ) 191 if ( dynamic_cast<ReferenceType*>( formal ) ) { 192 if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if 193 if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references 194 // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument 195 PRINT( 196 std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl; 197 ) 198 arg = new AddressExpr( arg ); 199 } 200 } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) { 201 // std::cerr << "===adding deref to arg" << std::endl; 202 // if the parameter is a reference, add a dereference to the reference-typed argument. 203 Type * baseType = InitTweak::getPointerBase( arg->get_result() ); 204 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() ); 205 PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() ); 206 delete arg->get_result(); 207 arg->set_result( ptrType ); 208 arg = mkDeref( arg ); 209 } 210 } 211 ++i; 212 } 213 } 214 return appExpr; 215 } 216 217 // idea: &&&E: get outer &, inner & 218 // at inner &, record depth D of reference type 219 // at outer &, add D derefs. 220 void AddrRef::premutate( Expression * ) { 221 GuardValue( current ); 222 GuardValue( first ); 223 current = false; 224 first = true; 225 } 226 227 void AddrRef::premutate( AddressExpr * ) { 228 GuardValue( current ); 229 GuardValue( first ); 230 current = first; 231 first = false; 232 if ( current ) { 233 GuardValue( refDepth ); 234 refDepth = 0; 235 } 236 } 237 238 Expression * AddrRef::postmutate( AddressExpr * addrExpr ) { 239 if ( refDepth == 0 ) { 240 if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) { 241 // try to avoid ?[?] 242 refDepth = addrExpr->get_arg()->get_result()->referenceDepth(); 243 } 244 } 245 if ( current ) { 246 Expression * ret = addrExpr; 247 while ( refDepth ) { 248 ret = mkDeref( ret ); 249 refDepth--; 250 } 251 return ret; 252 } 253 return addrExpr; 254 } 255 256 Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) { 257 // Inner expression may have been lvalue to reference conversion, which becomes an address expression. 258 // In this case, remove the outer address expression and return the argument. 259 // TODO: It's possible that this might catch too much and require a more sophisticated check. 260 return addrExpr; 261 } 262 263 Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) { 264 // xxx - is it possible to convert directly between reference types with a different base? E.g., 265 // int x; 266 // (double&)x; 267 // At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant 268 // after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct 269 // pointer casts in the right places. 270 271 // conversion to reference type 272 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) { 273 (void)refType; 274 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) { 275 // nothing to do if casting from reference to reference. 276 (void)otherRef; 277 PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; ) 278 if ( isIntrinsicReference( castExpr->get_arg() ) ) { 279 Expression * callExpr = castExpr->get_arg(); 280 PRINT( 281 std::cerr << "but arg is deref -- &" << std::endl; 282 std::cerr << callExpr << std::endl; 283 ) 284 callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts 285 delete callExpr->get_result(); 286 callExpr->set_result( refType->clone() ); 287 // move environment out to new top-level 288 callExpr->set_env( castExpr->get_env() ); 289 castExpr->set_arg( nullptr ); 290 castExpr->set_env( nullptr ); 291 delete castExpr; 292 return callExpr; 293 } 294 int depth1 = refType->referenceDepth(); 295 int depth2 = otherRef->referenceDepth(); 296 int diff = depth1-depth2; 297 if ( diff == 0 ) { 298 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 299 PRINT( std::cerr << castExpr << std::endl; ) 300 return castExpr; 301 } else if ( diff < 0 ) { 302 Expression * ret = castExpr->get_arg(); 303 for ( int i = 0; i < diff; ++i ) { 304 ret = mkDeref( ret ); 305 } 306 ret->set_env( castExpr->get_env() ); 307 delete ret->get_result(); 308 ret->set_result( castExpr->get_result() ); 309 castExpr->set_env( nullptr ); 310 castExpr->set_arg( nullptr ); 311 castExpr->set_result( nullptr ); 312 delete castExpr; 313 return ret; 314 } else if ( diff > 0 ) { 315 Expression * ret = castExpr->get_arg(); 316 for ( int i = 0; i < diff; ++i ) { 317 ret = new AddressExpr( ret ); 318 } 319 ret->set_env( castExpr->get_env() ); 320 delete ret->get_result(); 321 ret->set_result( castExpr->get_result() ); 322 castExpr->set_env( nullptr ); 323 castExpr->set_arg( nullptr ); 324 castExpr->set_result( nullptr ); 325 delete castExpr; 326 return ret; 327 } 328 329 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 330 PRINT( std::cerr << castExpr << std::endl; ) 331 return castExpr; 332 } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) { 333 // conversion from lvalue to reference 334 // xxx - keep cast, but turn into pointer cast?? 335 // xxx - memory 336 PRINT( 337 std::cerr << "convert lvalue to reference -- &" << std::endl; 338 std::cerr << castExpr->get_arg() << std::endl; 339 ) 340 AddressExpr * ret = new AddressExpr( castExpr->get_arg() ); 341 if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) { 342 // must keep cast if cast-to type is different from the actual type 343 castExpr->set_arg( ret ); 344 return castExpr; 345 } 346 ret->set_env( castExpr->get_env() ); 347 delete ret->get_result(); 348 ret->set_result( castExpr->get_result() ); 349 castExpr->set_env( nullptr ); 350 castExpr->set_arg( nullptr ); 351 castExpr->set_result( nullptr ); 352 delete castExpr; 353 return ret; 153 354 } else { 154 throw SemanticError( "Attempt to return non-lvalue from an lvalue-qualified function" ); 155 } // if 156 } // if 157 return retStmt; 158 } 159 160 void Pass2::visit( FunctionType *funType ) { 161 std::string typeName; 162 if ( isLvalueRet( funType ) ) { 163 DeclarationWithType *retParm = funType->get_returnVals().front(); 164 165 // make a new parameter that is a pointer to the type of the old return value 166 retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) ); 167 } // if 168 169 Visitor::visit( funType ); 355 // rvalue to reference conversion -- introduce temporary 356 } 357 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() ); 358 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) { 359 (void)refType; 360 // conversion from reference to rvalue 361 PRINT( 362 std::cerr << "convert reference to rvalue -- *" << std::endl; 363 std::cerr << "was = " << castExpr << std::endl; 364 ) 365 Expression * ret = castExpr->get_arg(); 366 TypeSubstitution * env = castExpr->get_env(); 367 castExpr->set_env( nullptr ); 368 if ( ! isIntrinsicReference( ret ) ) { 369 // dereference if not already dereferenced 370 ret = mkDeref( ret ); 371 } 372 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) { 373 // can remove cast if types are compatible, changing expression type to value type 374 ret->set_result( castExpr->get_result()->clone() ); 375 castExpr->set_arg( nullptr ); 376 delete castExpr; 377 } else { 378 // must keep cast if types are different 379 castExpr->set_arg( ret ); 380 ret = castExpr; 381 } 382 ret->set_env( env ); 383 PRINT( std::cerr << "now: " << ret << std::endl; ) 384 return ret; 385 } 386 return castExpr; 387 } 388 389 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) { 390 Type * base = refType->get_base(); 391 Type::Qualifiers qualifiers = refType->get_qualifiers(); 392 refType->set_base( nullptr ); 393 delete refType; 394 return new PointerType( qualifiers, base ); 170 395 } 171 396 … … 175 400 Expression * arg1 = commaExpr->get_arg1()->clone(); 176 401 Expression * arg2 = commaExpr->get_arg2()->clone(); 177 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 ) );402 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) ); 178 403 ret->set_env( expr->get_env() ); 179 404 expr->set_env( nullptr ); 180 405 delete expr; 181 return ret ->acceptMutator( *this );406 return ret; 182 407 } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) { 183 408 Expression * arg1 = condExpr->get_arg1()->clone(); 184 409 Expression * arg2 = condExpr->get_arg2()->clone(); 185 410 Expression * arg3 = condExpr->get_arg3()->clone(); 186 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 ) , mkExpr( arg3) );411 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) ); 187 412 ret->set_env( expr->get_env() ); 188 413 expr->set_env( nullptr ); … … 197 422 unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType ); 198 423 ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() ); 199 return ret ->acceptMutator( *this );424 return ret; 200 425 } 201 426 return expr; 202 427 } 203 428 204 Expression * GeneralizedLvalue::mutate( MemberExpr * memExpr ) { 205 Parent::mutate( memExpr ); 429 Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) { 206 430 return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } ); 207 431 } 208 432 209 Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) { 210 addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) ); 433 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) { 211 434 return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } ); 435 } 436 437 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) { 438 Expression * arg = addrExpr->get_arg(); 439 if ( isIntrinsicReference( arg ) ) { 440 std::string fname = InitTweak::getFunctionName( arg ); 441 if ( fname == "*?" ) { 442 Expression *& arg0 = InitTweak::getCallArg( arg, 0 ); 443 Expression * ret = arg0; 444 ret->set_env( addrExpr->get_env() ); 445 arg0 = nullptr; 446 addrExpr->set_env( nullptr ); 447 delete addrExpr; 448 return ret; 449 } 450 } 451 return addrExpr; 452 } 453 454 Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) { 455 if ( isIntrinsicReference( appExpr ) ) { 456 std::string fname = InitTweak::getFunctionName( appExpr ); 457 if ( fname == "*?" ) { 458 Expression * arg = InitTweak::getCallArg( appExpr, 0 ); 459 // xxx - this isn't right, because it can remove casts that should be there... 460 // while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) { 461 // arg = castExpr->get_arg(); 462 // } 463 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) { 464 Expression * ret = addrExpr->get_arg(); 465 ret->set_env( appExpr->get_env() ); 466 addrExpr->set_arg( nullptr ); 467 appExpr->set_env( nullptr ); 468 delete appExpr; 469 return ret; 470 } 471 } 472 } 473 return appExpr; 212 474 } 213 475 } // namespace -
src/GenPoly/Lvalue.h
rb3d413b r8135d4c 25 25 void convertLvalue( std::list< Declaration* >& translationUnit ); 26 26 27 /// true after reference types have been eliminated from the source code. After this point, reference types should not be added to the AST. 28 bool referencesPermissable(); 29 27 30 /// applies transformations that allow GCC to accept more complicated lvalue expressions, e.g. &(a, b) 28 31 Expression * generalizedLvalue( Expression * expr ); -
src/GenPoly/Specialize.cc
rb3d413b r8135d4c 131 131 // conversion of 0 (null) to function type does not require tuple specialization 132 132 if ( dynamic_cast< ZeroType * >( actualType ) ) return false; 133 FunctionType * aftype = getFunctionType( actualType );134 assertf( aftype, "formal type is a function type, but actual type is not .");133 FunctionType * aftype = getFunctionType( actualType->stripReferences() ); 134 assertf( aftype, "formal type is a function type, but actual type is not: %s", toString( actualType ).c_str() ); 135 135 // Can't tuple specialize if parameter sizes deeply-differ. 136 136 if ( functionParameterSize( fftype ) != functionParameterSize( aftype ) ) return false; -
src/InitTweak/FixInit.cc
rb3d413b r8135d4c 29 29 30 30 #include "CodeGen/GenType.h" // for genPrettyType 31 #include "CodeGen/OperatorTable.h" 31 32 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 32 33 #include "Common/SemanticError.h" // for SemanticError … … 254 255 SemanticError errors; 255 256 private: 256 void handleFirstParam( Expression * firstParam );257 257 template< typename... Params > 258 258 void emit( CodeLocation, const Params &... params ); … … 379 379 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 380 380 assert( ftype ); 381 if ( isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {382 Type * t1 = ftype->get_parameters().front()->get_type();381 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) { 382 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); 383 383 Type * t2 = ftype->get_parameters().back()->get_type(); 384 PointerType * ptrType = safe_dynamic_cast< PointerType * >( t1 );385 386 if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {384 assert( t1 ); 385 386 if ( ResolvExpr::typesCompatible( t1, t2, SymTab::Indexer() ) ) { 387 387 // optimization: don't need to copy construct in order to call a copy constructor 388 388 return appExpr; 389 389 } // if 390 } else if ( isDestructor( funcDecl->get_name() ) ) {390 } else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) { 391 391 // correctness: never copy construct arguments to a destructor 392 392 return appExpr; … … 417 417 418 418 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { 419 return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );419 return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type ); 420 420 } 421 421 … … 505 505 impCpCtorExpr->get_returnDecls().push_back( ret ); 506 506 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 507 if ( ! result->get_lvalue() ) {507 if ( ! dynamic_cast< ReferenceType * >( result ) ) { 508 508 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 509 509 destructRet( ret, impCpCtorExpr ); … … 607 607 608 608 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 609 if ( callExpr->get_result()->get_lvalue() ) {610 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning611 // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the612 // type of the return temporary from T to T* to properly capture the return value. Then dereference613 // the result of the comma expression, since the lvalue returning call was originally wrapped with614 // an AddressExpr. Effectively, this turns615 // lvalue T f();616 // &*f();617 // into618 // T * f();619 // T * tmp_cp_retN;620 // &*(tmp_cp_retN = &*f(), tmp_cp_retN); // the first * and second & are generated here621 // which work out in terms of types, but is pretty messy. It would be nice to find a better way.622 assign->get_args().back() = new AddressExpr( assign->get_args().back() );623 624 returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );625 retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) );626 retExpr = UntypedExpr::createDeref( retExpr );627 } // if628 609 // move env from callExpr to retExpr 629 610 retExpr->set_env( callExpr->get_env() ); … … 991 972 if ( ! funcDecl ) return false; 992 973 if ( ! funcDecl->get_statements() ) return false; 993 return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );974 return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() ); 994 975 } 995 976 … … 1008 989 1009 990 function = funcDecl; 1010 isCtor = isConstructor( function->get_name() );991 isCtor = CodeGen::isConstructor( function->get_name() ); 1011 992 if ( checkWarnings( function ) ) { 1012 993 FunctionType * type = function->get_functionType(); 1013 994 assert( ! type->get_parameters().empty() ); 1014 995 thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() ); 1015 PointerType * ptrType = safe_dynamic_cast< PointerType * >( thisParam->get_type() );1016 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base());996 Type * thisType = getPointerBase( thisParam->get_type() ); 997 StructInstType * structType = dynamic_cast< StructInstType * >( thisType ); 1017 998 if ( structType ) { 1018 999 structDecl = structType->get_baseStruct(); … … 1047 1028 1048 1029 if ( ! unhandled.empty() ) { 1049 // need to explicitly re-add function parameters in order to resolve copy constructors1030 // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors 1050 1031 enterScope(); 1051 1032 maybeAccept( function->get_functionType(), *this ); … … 1062 1043 // insert and resolve default/copy constructor call for each field that's unhandled 1063 1044 std::list< Statement * > stmt; 1064 UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) );1065 1066 1045 Expression * arg2 = 0; 1067 1046 if ( isCopyConstructor( function ) ) { … … 1072 1051 } 1073 1052 InitExpander srcParam( arg2 ); 1074 SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor ); 1053 // cast away reference type and construct field. 1054 Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() ); 1055 Expression * memberDest = new MemberExpr( field, thisExpr ); 1056 SymTab::genImplicitCall( srcParam, memberDest, function->get_name(), back_inserter( stmt ), field, isCtor ); 1075 1057 1076 1058 assert( stmt.size() <= 1 ); … … 1099 1081 } 1100 1082 1083 /// true if expr is effectively just the 'this' parameter 1084 bool isThisExpression( Expression * expr, DeclarationWithType * thisParam ) { 1085 // TODO: there are more complicated ways to pass 'this' to a constructor, e.g. &*, *&, etc. 1086 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 1087 return varExpr->get_var() == thisParam; 1088 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( expr ) ) { 1089 return isThisExpression( castExpr->get_arg(), thisParam ); 1090 } 1091 return false; 1092 } 1093 1094 /// returns a MemberExpr if expr is effectively just member access on the 'this' parameter, else nullptr 1095 MemberExpr * isThisMemberExpr( Expression * expr, DeclarationWithType * thisParam ) { 1096 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) { 1097 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { 1098 return memberExpr; 1099 } 1100 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 1101 return isThisMemberExpr( castExpr->get_arg(), thisParam ); 1102 } 1103 return nullptr; 1104 } 1105 1101 1106 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) { 1102 1107 if ( ! checkWarnings( function ) ) return; … … 1107 1112 Expression * firstParam = appExpr->get_args().front(); 1108 1113 1109 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {1114 if ( isThisExpression( firstParam, thisParam ) ) { 1110 1115 // if calling another constructor on thisParam, assume that function handles 1111 1116 // all members - if it doesn't a warning will appear in that function. 1112 if ( varExpr->get_var() == thisParam ) { 1113 unhandled.clear(); 1114 } 1115 } else { 1116 // if first parameter is a member expression then 1117 // remove the member from unhandled set. 1118 handleFirstParam( firstParam ); 1119 } 1120 } 1121 1122 Parent::visit( appExpr ); 1123 } 1124 1125 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) { 1126 using namespace std; 1127 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) { 1128 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) { 1129 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 1130 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 1131 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 1132 if ( varExpr->get_var() == thisParam ) { 1133 unhandled.erase( memberExpr->get_member() ); 1134 } 1135 } 1136 } 1117 unhandled.clear(); 1118 } else if ( MemberExpr * memberExpr = isThisMemberExpr( firstParam, thisParam ) ) { 1119 // if first parameter is a member expression on the this parameter, 1120 // then remove the member from unhandled set. 1121 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { 1122 unhandled.erase( memberExpr->get_member() ); 1137 1123 } 1138 1124 } 1139 1125 } 1126 Parent::visit( appExpr ); 1140 1127 } 1141 1128 … … 1144 1131 if ( ! isCtor ) return; 1145 1132 1146 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 1147 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 1148 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 1149 if ( varExpr->get_var() == thisParam ) { 1150 if ( unhandled.count( memberExpr->get_member() ) ) { 1151 // emit a warning because a member was used before it was constructed 1152 usedUninit.insert( { memberExpr->get_member(), memberExpr->location } ); 1153 } 1154 } 1155 } 1133 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { 1134 if ( unhandled.count( memberExpr->get_member() ) ) { 1135 // emit a warning because a member was used before it was constructed 1136 usedUninit.insert( { memberExpr->get_member(), memberExpr->location } ); 1156 1137 } 1157 1138 } … … 1199 1180 ctorExpr->set_callExpr( nullptr ); 1200 1181 ctorExpr->set_env( nullptr ); 1182 delete ctorExpr; 1201 1183 1202 1184 Expression *& firstArg = callExpr->get_args().front(); 1203 UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) ); 1204 assign->get_args().push_back( new VariableExpr( tmp ) ); 1205 assign->get_args().push_back( firstArg ); 1206 assign->set_result( ctorExpr->get_result()->clone() ); 1207 firstArg = assign; 1208 1209 CommaExpr * commaExpr = new CommaExpr( callExpr, new VariableExpr( tmp ) ); 1185 1186 // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away. 1187 1188 // generate the type of assignment operator using the type of tmp minus any reference types 1189 Type * type = tmp->get_type()->stripReferences(); 1190 FunctionType * ftype = SymTab::genAssignType( type ); 1191 1192 // generate fake assignment decl and call it using &tmp and &firstArg 1193 // since tmp is guaranteed to be a reference and we want to assign pointers 1194 FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr ); 1195 ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) ); 1196 assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) ); 1197 Expression * addrArg = new AddressExpr( firstArg ); 1198 // if firstArg has type T&&, then &firstArg has type T*&. 1199 // Cast away the reference to a value type so that the argument 1200 // matches the assignment's parameter types 1201 if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) { 1202 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() ); 1203 } 1204 assign->get_args().push_back( addrArg ); 1205 firstArg = new VariableExpr( tmp ); 1206 1207 // for constructor expr: 1208 // T x; 1209 // x{}; 1210 // results in: 1211 // T x; 1212 // T & tmp; 1213 // &tmp = &x, ?{}(tmp), tmp 1214 CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) ); 1210 1215 commaExpr->set_env( env ); 1211 delete ctorExpr;1212 1216 return commaExpr; 1213 1217 } -
src/InitTweak/GenInit.cc
rb3d413b r8135d4c 21 21 #include <list> // for _List_iterator, list 22 22 23 #include "CodeGen/OperatorTable.h" 23 24 #include "Common/PassVisitor.h" // for PassVisitor, WithGuards, WithShort... 24 25 #include "Common/SemanticError.h" // for SemanticError … … 57 58 58 59 protected: 59 FunctionType * ftype ;60 FunctionType * ftype = nullptr; 60 61 std::string funcName; 61 62 }; … … 140 141 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals(); 141 142 assert( returnVals.size() == 0 || returnVals.size() == 1 ); 142 // hands off if the function returns a n lvalue - we don't want to allocate a temporary if a variable's address143 // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address 143 144 // is being returned 144 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! returnVals.front()->get_type()->get_lvalue() ) {145 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) { 145 146 // explicitly construct the return value using the return expression and the retVal object 146 147 assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() ); 147 UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) ); 148 construct->get_args().push_back( new AddressExpr( new VariableExpr( returnVals.front() ) ) ); 149 construct->get_args().push_back( returnStmt->get_expr() ); 150 stmtsToAddBefore.push_back(new ExprStmt(noLabels, construct)); 148 149 stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) ); 151 150 152 151 // return the retVal object … … 215 214 216 215 bool CtorDtor::isManaged( Type * type ) const { 216 // at least for now, references are never constructed 217 if ( dynamic_cast< ReferenceType * >( type ) ) return false; 217 218 // need to clear and reset qualifiers when determining if a type is managed 218 219 ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() ); … … 238 239 void CtorDtor::handleDWT( DeclarationWithType * dwt ) { 239 240 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 240 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && isCtorDtor( dwt->get_name() ) ) {241 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) { 241 242 std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters(); 242 243 assert( ! params.empty() ); 243 PointerType * type = safe_dynamic_cast< PointerType * >( params.front()->get_type() ); 244 managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) ); 244 Type * type = InitTweak::getPointerBase( params.front()->get_type() ); 245 assert( type ); 246 managedTypes.insert( SymTab::Mangler::mangle( type ) ); 245 247 } 246 248 } -
src/InitTweak/InitTweak.cc
rb3d413b r8135d4c 187 187 188 188 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) ); 189 increment->get_args().push_back( new AddressExpr( index->clone()) );189 increment->get_args().push_back( index->clone() ); 190 190 *out++ = new ExprStmt( noLabels, increment ); 191 191 } … … 397 397 template<typename CallExpr> 398 398 Expression *& callArg( CallExpr * callExpr, unsigned int pos ) { 399 if ( pos >= callExpr->get_args().size() ) assertf( false, " asking for argument that doesn't exist. Return NULL/throw exception?");399 if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() ); 400 400 for ( Expression *& arg : callExpr->get_args() ) { 401 401 if ( pos == 0 ) return arg; … … 475 475 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 476 476 return arrayType->get_base(); 477 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) { 478 return refType->get_base(); 477 479 } else { 478 480 return NULL; … … 560 562 if ( ftype->get_parameters().size() != 2 ) return 0; 561 563 562 Type * t1 = ftype->get_parameters().front()->get_type();564 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); 563 565 Type * t2 = ftype->get_parameters().back()->get_type(); 564 PointerType * ptrType = dynamic_cast< PointerType * > ( t1 ); 565 assert( ptrType ); 566 567 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( ptrType->get_base(), t2, SymTab::Indexer() ) ) { 566 assert( t1 ); 567 568 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) { 568 569 return function; 569 570 } else { -
src/InitTweak/InitTweak.h
rb3d413b r8135d4c 24 24 // helper functions for initialization 25 25 namespace InitTweak { 26 bool isConstructor( const std::string & );27 bool isDestructor( const std::string & );28 bool isAssignment( const std::string & );29 bool isCtorDtor( const std::string & );30 bool isCtorDtorAssign( const std::string & );31 32 26 FunctionDecl * isAssignment( Declaration * decl ); 33 27 FunctionDecl * isDestructor( Declaration * decl ); -
src/Makefile.in
rb3d413b r8135d4c 224 224 SynTree/driver_cfa_cpp-PointerType.$(OBJEXT) \ 225 225 SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT) \ 226 SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT) \ 226 227 SynTree/driver_cfa_cpp-FunctionType.$(OBJEXT) \ 227 228 SynTree/driver_cfa_cpp-ReferenceToType.$(OBJEXT) \ … … 520 521 SynTree/VoidType.cc SynTree/BasicType.cc \ 521 522 SynTree/PointerType.cc SynTree/ArrayType.cc \ 522 SynTree/FunctionType.cc SynTree/ReferenceToType.cc \ 523 SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \ 523 SynTree/ReferenceType.cc SynTree/FunctionType.cc \ 524 SynTree/ReferenceToType.cc SynTree/TupleType.cc \ 525 SynTree/TypeofType.cc SynTree/AttrType.cc \ 524 526 SynTree/VarArgsType.cc SynTree/ZeroOneType.cc \ 525 527 SynTree/Constant.cc SynTree/Expression.cc SynTree/TupleExpr.cc \ … … 867 869 SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT): SynTree/$(am__dirstamp) \ 868 870 SynTree/$(DEPDIR)/$(am__dirstamp) 871 SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT): \ 872 SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp) 869 873 SynTree/driver_cfa_cpp-FunctionType.$(OBJEXT): \ 870 874 SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp) … … 1070 1074 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Po@am__quote@ 1071 1075 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Po@am__quote@ 1076 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po@am__quote@ 1072 1077 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Po@am__quote@ 1073 1078 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Po@am__quote@ … … 2167 2172 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2168 2173 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ArrayType.obj `if test -f 'SynTree/ArrayType.cc'; then $(CYGPATH_W) 'SynTree/ArrayType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ArrayType.cc'; fi` 2174 2175 SynTree/driver_cfa_cpp-ReferenceType.o: SynTree/ReferenceType.cc 2176 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceType.o `test -f 'SynTree/ReferenceType.cc' || echo '$(srcdir)/'`SynTree/ReferenceType.cc 2177 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po 2178 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='SynTree/ReferenceType.cc' object='SynTree/driver_cfa_cpp-ReferenceType.o' libtool=no @AMDEPBACKSLASH@ 2179 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2180 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceType.o `test -f 'SynTree/ReferenceType.cc' || echo '$(srcdir)/'`SynTree/ReferenceType.cc 2181 2182 SynTree/driver_cfa_cpp-ReferenceType.obj: SynTree/ReferenceType.cc 2183 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceType.obj `if test -f 'SynTree/ReferenceType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceType.cc'; fi` 2184 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po 2185 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='SynTree/ReferenceType.cc' object='SynTree/driver_cfa_cpp-ReferenceType.obj' libtool=no @AMDEPBACKSLASH@ 2186 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2187 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceType.obj `if test -f 'SynTree/ReferenceType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceType.cc'; fi` 2169 2188 2170 2189 SynTree/driver_cfa_cpp-FunctionType.o: SynTree/FunctionType.cc -
src/Parser/DeclarationNode.cc
rb3d413b r8135d4c 340 340 } // DeclarationNode::newTypeDecl 341 341 342 DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers ) {343 DeclarationNode * newnode = new DeclarationNode; 344 newnode->type = new TypeData( TypeData::Pointer);342 DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers, OperKinds kind ) { 343 DeclarationNode * newnode = new DeclarationNode; 344 newnode->type = new TypeData( kind == OperKinds::PointTo ? TypeData::Pointer : TypeData::Reference ); 345 345 if ( qualifiers ) { 346 346 return newnode->addQualifiers( qualifiers ); … … 759 759 DeclarationNode * DeclarationNode::addPointer( DeclarationNode * p ) { 760 760 if ( p ) { 761 assert( p->type->kind == TypeData::Pointer );761 assert( p->type->kind == TypeData::Pointer || TypeData::Reference ); 762 762 setBase( p->type ); 763 763 p->type = nullptr; … … 781 781 DeclarationNode * DeclarationNode::addNewPointer( DeclarationNode * p ) { 782 782 if ( p ) { 783 assert( p->type->kind == TypeData::Pointer );783 assert( p->type->kind == TypeData::Pointer || p->type->kind == TypeData::Reference ); 784 784 if ( type ) { 785 785 switch ( type->kind ) { -
src/Parser/ExpressionNode.cc
rb3d413b r8135d4c 314 314 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) { 315 315 std::list< Expression * > args; 316 args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node) ) );316 args.push_back( maybeMoveBuild< Expression >(expr_node) ); // xxx 317 317 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); 318 318 } // build_unary_ptr … … 327 327 Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) { 328 328 std::list< Expression * > args; 329 args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node1)) );329 args.push_back( maybeMoveBuild< Expression >(expr_node1) ); 330 330 args.push_back( maybeMoveBuild< Expression >(expr_node2) ); 331 331 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); -
src/Parser/ParseNode.h
rb3d413b r8135d4c 243 243 static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params ); 244 244 static DeclarationNode * newTypeDecl( std::string * name, DeclarationNode * typeParams ); 245 static DeclarationNode * newPointer( DeclarationNode * qualifiers );245 static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind ); 246 246 static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic ); 247 247 static DeclarationNode * newVarArray( DeclarationNode * qualifiers ); -
src/Parser/TypeData.cc
rb3d413b r8135d4c 35 35 case Unknown: 36 36 case Pointer: 37 case Reference: 37 38 case EnumConstant: 38 39 // nothing else to initialize … … 104 105 case Unknown: 105 106 case Pointer: 107 case Reference: 106 108 case EnumConstant: 107 109 // nothing to destroy … … 170 172 case EnumConstant: 171 173 case Pointer: 174 case Reference: 172 175 // nothing else to copy 173 176 break; … … 405 408 // add dtor: void ^?{}(T *) 406 409 FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false ); 407 dtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );410 dtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 408 411 td->get_assertions().push_front( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, dtorType, nullptr ) ); 409 412 410 413 // add copy ctor: void ?{}(T *, T) 411 414 FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false ); 412 copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );415 copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 413 416 copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 414 417 td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, copyCtorType, nullptr ) ); … … 416 419 // add default ctor: void ?{}(T *) 417 420 FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false ); 418 ctorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );421 ctorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 419 422 td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, ctorType, nullptr ) ); 420 423 421 424 // add assignment operator: T * ?=?(T *, T) 422 425 FunctionType * assignType = new FunctionType( Type::Qualifiers(), false ); 423 assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );426 assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 424 427 assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 425 428 assignType->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); … … 441 444 case TypeData::Array: 442 445 return buildArray( td ); 446 case TypeData::Reference: 447 return buildReference( td ); 443 448 case TypeData::Function: 444 449 return buildFunction( td ); … … 619 624 buildForall( td->forall, at->get_forall() ); 620 625 return at; 621 } // buildPointer 626 } // buildArray 627 628 ReferenceType * buildReference( const TypeData * td ) { 629 ReferenceType * rt; 630 if ( td->base ) { 631 rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) ); 632 } else { 633 rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 634 } // if 635 buildForall( td->forall, rt->get_forall() ); 636 return rt; 637 } // buildReference 622 638 623 639 AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) { -
src/Parser/TypeData.h
rb3d413b r8135d4c 26 26 27 27 struct TypeData { 28 enum Kind { Basic, Pointer, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,28 enum Kind { Basic, Pointer, Array, Reference, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic, 29 29 SymbolicInst, Tuple, Typeof, Builtin, Unknown }; 30 30 … … 109 109 PointerType * buildPointer( const TypeData * ); 110 110 ArrayType * buildArray( const TypeData * ); 111 ReferenceType * buildReference( const TypeData * ); 111 112 AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > ); 112 113 ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ); -
src/Parser/lex.ll
rb3d413b r8135d4c 236 236 __label__ { KEYWORD_RETURN(LABEL); } // GCC 237 237 long { KEYWORD_RETURN(LONG); } 238 lvalue { KEYWORD_RETURN(LVALUE); } // CFA239 238 monitor { KEYWORD_RETURN(MONITOR); } // CFA 240 239 mutex { KEYWORD_RETURN(MUTEX); } // CFA -
src/Parser/parser.yy
rb3d413b r8135d4c 119 119 %token RESTRICT // C99 120 120 %token ATOMIC // C11 121 %token FORALL LVALUEMUTEX VIRTUAL // CFA121 %token FORALL MUTEX VIRTUAL // CFA 122 122 %token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED 123 123 %token BOOL COMPLEX IMAGINARY // C99 … … 670 670 conditional_expression 671 671 | unary_expression assignment_operator assignment_expression 672 { $$ = new ExpressionNode( build_binary_ ptr( $2, $1, $3 ) ); }672 { $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); } 673 673 ; 674 674 … … 1439 1439 | VOLATILE 1440 1440 { $$ = DeclarationNode::newTypeQualifier( Type::Volatile ); } 1441 | LVALUE // CFA1442 { $$ = DeclarationNode::newTypeQualifier( Type::Lvalue ); }1443 1441 | MUTEX 1444 1442 { $$ = DeclarationNode::newTypeQualifier( Type::Mutex ); } … … 2421 2419 variable_ptr: 2422 2420 ptrref_operator variable_declarator 2423 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2421 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2424 2422 | ptrref_operator type_qualifier_list variable_declarator 2425 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2423 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2426 2424 | '(' variable_ptr ')' attribute_list_opt 2427 2425 { $$ = $2->addQualifiers( $4 ); } // redundant parenthesis … … 2469 2467 function_ptr: 2470 2468 ptrref_operator function_declarator 2471 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2469 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2472 2470 | ptrref_operator type_qualifier_list function_declarator 2473 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2471 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2474 2472 | '(' function_ptr ')' 2475 2473 { $$ = $2; } … … 2509 2507 KR_function_ptr: 2510 2508 ptrref_operator KR_function_declarator 2511 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2509 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2512 2510 | ptrref_operator type_qualifier_list KR_function_declarator 2513 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2511 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2514 2512 | '(' KR_function_ptr ')' 2515 2513 { $$ = $2; } … … 2553 2551 type_ptr: 2554 2552 ptrref_operator variable_type_redeclarator 2555 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2553 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2556 2554 | ptrref_operator type_qualifier_list variable_type_redeclarator 2557 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2555 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2558 2556 | '(' type_ptr ')' attribute_list_opt 2559 2557 { $$ = $2->addQualifiers( $4 ); } … … 2597 2595 identifier_parameter_ptr: 2598 2596 ptrref_operator identifier_parameter_declarator 2599 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2597 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2600 2598 | ptrref_operator type_qualifier_list identifier_parameter_declarator 2601 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2599 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2602 2600 | '(' identifier_parameter_ptr ')' attribute_list_opt 2603 2601 { $$ = $2->addQualifiers( $4 ); } … … 2657 2655 type_parameter_ptr: 2658 2656 ptrref_operator type_parameter_redeclarator 2659 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2657 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2660 2658 | ptrref_operator type_qualifier_list type_parameter_redeclarator 2661 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2659 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2662 2660 | '(' type_parameter_ptr ')' attribute_list_opt 2663 2661 { $$ = $2->addQualifiers( $4 ); } … … 2700 2698 abstract_ptr: 2701 2699 ptrref_operator 2702 { $$ = DeclarationNode::newPointer( 0 ); }2700 { $$ = DeclarationNode::newPointer( 0, $1 ); } 2703 2701 | ptrref_operator type_qualifier_list 2704 { $$ = DeclarationNode::newPointer( $2 ); }2702 { $$ = DeclarationNode::newPointer( $2, $1 ); } 2705 2703 | ptrref_operator abstract_declarator 2706 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2704 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2707 2705 | ptrref_operator type_qualifier_list abstract_declarator 2708 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2706 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2709 2707 | '(' abstract_ptr ')' attribute_list_opt 2710 2708 { $$ = $2->addQualifiers( $4 ); } … … 2789 2787 abstract_parameter_ptr: 2790 2788 ptrref_operator 2791 { $$ = DeclarationNode::newPointer( nullptr ); }2789 { $$ = DeclarationNode::newPointer( nullptr, $1 ); } 2792 2790 | ptrref_operator type_qualifier_list 2793 { $$ = DeclarationNode::newPointer( $2 ); }2791 { $$ = DeclarationNode::newPointer( $2, $1 ); } 2794 2792 | ptrref_operator abstract_parameter_declarator 2795 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr ) ); }2793 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 2796 2794 | ptrref_operator type_qualifier_list abstract_parameter_declarator 2797 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2795 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2798 2796 | '(' abstract_parameter_ptr ')' attribute_list_opt 2799 2797 { $$ = $2->addQualifiers( $4 ); } … … 2868 2866 variable_abstract_ptr: 2869 2867 ptrref_operator 2870 { $$ = DeclarationNode::newPointer( 0 ); }2868 { $$ = DeclarationNode::newPointer( 0, $1 ); } 2871 2869 | ptrref_operator type_qualifier_list 2872 { $$ = DeclarationNode::newPointer( $2 ); }2870 { $$ = DeclarationNode::newPointer( $2, $1 ); } 2873 2871 | ptrref_operator variable_abstract_declarator 2874 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2872 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2875 2873 | ptrref_operator type_qualifier_list variable_abstract_declarator 2876 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2874 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2877 2875 | '(' variable_abstract_ptr ')' attribute_list_opt 2878 2876 { $$ = $2->addQualifiers( $4 ); } … … 2914 2912 // No SUE declaration in parameter list. 2915 2913 ptrref_operator type_specifier_nobody 2916 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2914 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2917 2915 | type_qualifier_list ptrref_operator type_specifier_nobody 2918 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2916 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 2919 2917 | ptrref_operator cfa_abstract_function 2920 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2918 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2921 2919 | type_qualifier_list ptrref_operator cfa_abstract_function 2922 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2920 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 2923 2921 | ptrref_operator cfa_identifier_parameter_declarator_tuple 2924 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2922 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2925 2923 | type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple 2926 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2924 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 2927 2925 ; 2928 2926 … … 3002 3000 cfa_abstract_ptr: // CFA 3003 3001 ptrref_operator type_specifier 3004 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }3002 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 3005 3003 | type_qualifier_list ptrref_operator type_specifier 3006 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }3004 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 3007 3005 | ptrref_operator cfa_abstract_function 3008 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }3006 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 3009 3007 | type_qualifier_list ptrref_operator cfa_abstract_function 3010 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }3008 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 3011 3009 | ptrref_operator cfa_abstract_declarator_tuple 3012 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }3010 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 3013 3011 | type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple 3014 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }3012 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 3015 3013 ; 3016 3014 -
src/ResolvExpr/Alternative.cc
rb3d413b r8135d4c 34 34 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {} 35 35 36 Alternative::Alternative( const Alternative &other ) { 37 initialize( other, *this ); 36 Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) { 38 37 } 39 38 40 39 Alternative &Alternative::operator=( const Alternative &other ) { 41 40 if ( &other == this ) return *this; 42 initialize( other, *this ); 41 delete expr; 42 cost = other.cost; 43 cvtCost = other.cvtCost; 44 expr = maybeClone( other.expr ); 45 env = other.env; 43 46 return *this; 44 47 } … … 57 60 other.expr = nullptr; 58 61 return *this; 59 }60 61 void Alternative::initialize( const Alternative &src, Alternative &dest ) {62 dest.cost = src.cost;63 dest.cvtCost = src.cvtCost;64 dest.expr = maybeClone( src.expr );65 dest.env = src.env;66 62 } 67 63 -
src/ResolvExpr/Alternative.h
rb3d413b r8135d4c 39 39 ~Alternative(); 40 40 41 void initialize( const Alternative &src, Alternative &dest );42 43 41 void print( std::ostream &os, int indent = 0 ) const; 44 42 -
src/ResolvExpr/AlternativeFinder.cc
rb3d413b r8135d4c 67 67 68 68 Cost sumCost( const AltList &in ) { 69 Cost total ;69 Cost total = Cost::zero; 70 70 for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) { 71 71 total += i->cost; … … 144 144 expr->get_result()->accept( global_renamer ); 145 145 } 146 } 146 147 void referenceToRvalueConversion( Expression *& expr ) { 148 if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) { 149 // cast away reference from expr 150 expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() ); 151 } 152 } 153 } // namespace 147 154 148 155 template< typename InputIterator, typename OutputIterator > … … 186 193 if ( alternatives.begin() == oldBegin ) { 187 194 std::ostringstream stream; 188 stream << "Can't choose between " << alternatives.size() << " alternatives for expression "; 195 AltList winners; 196 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) ); 197 stream << "Can't choose between " << winners.size() << " alternatives for expression "; 189 198 expr->print( stream ); 190 199 stream << "Alternatives are:"; 191 AltList winners;192 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );193 200 printAlts( winners, stream, 8 ); 194 201 throw SemanticError( stream.str() ); … … 213 220 void AlternativeFinder::addAnonConversions( const Alternative & alt ) { 214 221 // adds anonymous member interpretations whenever an aggregate value type is seen. 215 Expression * expr = alt.expr->clone(); 216 std::unique_ptr< Expression > manager( expr ); // RAII for expr 217 alt.env.apply( expr->get_result() ); 218 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( expr->get_result() ) ) { 222 // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value 223 std::unique_ptr<Expression> aggrExpr( alt.expr->clone() ); 224 alt.env.apply( aggrExpr->get_result() ); 225 Type * aggrType = aggrExpr->get_result(); 226 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 227 aggrType = aggrType->stripReferences(); 228 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 229 } 230 231 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 219 232 NameExpr nameExpr( "" ); 220 addAggMembers( structInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );221 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( expr->get_result() ) ) {233 addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 234 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 222 235 NameExpr nameExpr( "" ); 223 addAggMembers( unionInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );236 addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 224 237 } // if 225 238 } … … 228 241 void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 229 242 // by this point, member must be a name expr 230 NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member ); 243 NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ); 244 if ( ! nameExpr ) return; 231 245 const std::string & name = nameExpr->get_name(); 232 246 std::list< Declaration* > members; … … 250 264 // during parsing and reusing that information here. 251 265 std::stringstream ss( constantExpr->get_constant()->get_value() ); 252 int val ;266 int val = 0; 253 267 std::string tmp; 254 268 if ( ss >> val && ! (ss >> tmp) ) { … … 277 291 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 278 292 279 Cost convCost ( 0, 0, 0 );293 Cost convCost = Cost::zero; 280 294 std::list< DeclarationWithType* >& formals = function->get_parameters(); 281 295 std::list< DeclarationWithType* >::iterator formal = formals.begin(); … … 290 304 actualType->print( std::cerr, 8 ); 291 305 ) 292 Cost actualCost ;306 Cost actualCost = Cost::zero; 293 307 if ( formal == formals.end() ) { 294 308 if ( function->get_isVarArgs() ) { 295 convCost += Cost( 1, 0, 0 ); 309 convCost.incUnsafe(); 310 // convert reference-typed expressions to value-typed expressions 311 referenceToRvalueConversion( *actualExpr ); 296 312 continue; 297 313 } else { … … 305 321 std::cerr << std::endl << " to "; 306 322 formalType->print( std::cerr, 8 ); 323 std::cerr << std::endl << "environment is: "; 324 alt.env.print( std::cerr, 8 ); 325 std::cerr << std::endl; 307 326 ) 308 327 Cost newCost = conversionCost( actualType, formalType, indexer, alt.env ); … … 316 335 convCost += newCost; 317 336 actualCost += newCost; 318 if ( actualCost != Cost ( 0, 0, 0 )) {337 if ( actualCost != Cost::zero ) { 319 338 Type *newType = formalType->clone(); 320 339 alt.env.apply( newType ); 321 340 *actualExpr = new CastExpr( *actualExpr, newType ); 322 341 } 323 convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0);342 convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) ); 324 343 ++formal; // can't be in for-loop update because of the continue 325 344 } … … 343 362 } 344 363 convCost += newCost; 345 convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0);364 convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) ); 346 365 } 347 366 … … 400 419 Expression * actual = actualIt->expr; 401 420 Type * actualType = actual->get_result(); 421 402 422 PRINT( 403 423 std::cerr << "formal type is "; … … 408 428 ) 409 429 if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 430 // std::cerr << "unify failed" << std::endl; 410 431 return false; 411 432 } … … 452 473 // match flattened actuals with formal parameters - actuals will be grouped to match 453 474 // with formals as appropriate 454 Cost cost ;475 Cost cost = Cost::zero; 455 476 std::list< Expression * > newExprs; 456 477 ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal ); … … 613 634 AssertionSet newNeed; 614 635 //AssertionParentSet needParents; 636 PRINT( 637 std::cerr << "env is: " << std::endl; 638 newAlt.env.print( std::cerr, 0 ); 639 std::cerr << std::endl; 640 ) 641 615 642 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out ); 616 643 // PRINT( … … 643 670 makeExprList( instantiatedActuals, appExpr->get_args() ); 644 671 PRINT( 672 std::cerr << "instantiate function success: " << appExpr << std::endl; 645 673 std::cerr << "need assertions:" << std::endl; 646 674 printAssertionSet( resultNeed, std::cerr, 8 ); … … 663 691 UntypedExpr *vexpr = untypedExpr->clone(); 664 692 vexpr->set_result( pt.clone() ); 665 alternatives.push_back( Alternative( vexpr, env, Cost ()) );693 alternatives.push_back( Alternative( vexpr, env, Cost::zero) ); 666 694 return; 667 695 } … … 681 709 AltList candidates; 682 710 SemanticError errors; 683 for ( AltList:: const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {711 for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) { 684 712 try { 685 713 PRINT( … … 688 716 ) 689 717 // check if the type is pointer to function 690 PointerType *pointer; 691 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) { 718 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) { 692 719 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 720 referenceToRvalueConversion( func->expr ); 693 721 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 694 722 // XXX … … 696 724 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 697 725 } 698 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( pointer->get_base() ) ) { 699 EqvClass eqvClass; 700 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 701 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 702 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 703 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 704 } // for 705 } // if 726 } 727 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) 728 referenceToRvalueConversion( func->expr ); 729 EqvClass eqvClass; 730 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 731 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 732 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 733 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 734 } // for 706 735 } // if 707 736 } // if … … 722 751 } 723 752 724 for ( AltList:: const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {753 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) { 725 754 // check if the type is pointer to function 726 PointerType *pointer; 727 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) { 755 if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) { 728 756 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 757 referenceToRvalueConversion( funcOp->expr ); 729 758 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 730 759 AltList currentAlt; … … 753 782 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 754 783 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 755 std::cerr << "Case +++++++++++++ "<< std::endl;784 std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl; 756 785 std::cerr << "formals are:" << std::endl; 757 786 printAll( function->get_parameters(), std::cerr, 8 ); … … 796 825 bool isLvalue( Expression *expr ) { 797 826 // xxx - recurse into tuples? 798 return expr->has_result() && expr->get_result()->get_lvalue();827 return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) ); 799 828 } 800 829 … … 810 839 811 840 Expression * restructureCast( Expression * argExpr, Type * toType ) { 812 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) { 813 // Argument expression is a tuple and the target type is not void. Cast each member of the tuple 814 // to its corresponding target type, producing the tuple of those cast expressions. If there are 815 // more components of the tuple than components in the target type, then excess components do not 816 // come out in the result expression (but UniqueExprs ensure that side effects will still be done). 817 if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) { 841 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) { 842 // Argument expression is a tuple and the target type is not void and not a reference type. 843 // Cast each member of the tuple to its corresponding target type, producing the tuple of those 844 // cast expressions. If there are more components of the tuple than components in the target type, 845 // then excess components do not come out in the result expression (but UniqueExprs ensure that 846 // side effects will still be done). 847 if ( Tuples::maybeImpureIgnoreUnique( argExpr ) ) { 818 848 // expressions which may contain side effects require a single unique instance of the expression. 819 849 argExpr = new UniqueExpr( argExpr ); … … 855 885 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 856 886 // to. 857 int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();887 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size(); 858 888 if ( discardedValues < 0 ) continue; 859 889 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 860 890 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 861 891 // unification run for side-effects 862 unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );863 Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );892 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 893 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 864 894 if ( thisCost != Cost::infinity ) { 865 895 // count one safe conversion for each value that is thrown away 866 thisCost += Cost( 0, 0,discardedValues );896 thisCost.incSafe( discardedValues ); 867 897 868 898 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) ); … … 895 925 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); 896 926 for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) { 897 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) { 898 addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 899 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) { 900 addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 901 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) { 902 addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 927 // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value 928 std::unique_ptr<Expression> aggrExpr( agg->expr->clone() ); 929 Type * aggrType = aggrExpr->get_result(); 930 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 931 aggrType = aggrType->stripReferences(); 932 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 933 } 934 // find member of the given type 935 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 936 addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 937 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 938 addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 939 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 940 addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 903 941 } // if 904 942 } // for … … 915 953 for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) { 916 954 VariableExpr newExpr( *i, nameExpr->get_argName() ); 917 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );955 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 918 956 PRINT( 919 957 std::cerr << "decl is "; … … 955 993 // return the lowest cost alternative for the argument 956 994 Alternative &choice = winners.front(); 995 referenceToRvalueConversion( choice.expr ); 957 996 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 958 997 } // if … … 975 1014 // return the lowest cost alternative for the argument 976 1015 Alternative &choice = winners.front(); 1016 referenceToRvalueConversion( choice.expr ); 977 1017 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 978 1018 } // if … … 1059 1099 for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) { 1060 1100 VariableExpr newExpr( *i ); 1061 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );1101 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 1062 1102 renameTypes( alternatives.back().expr ); 1063 1103 } // for … … 1232 1272 if ( thisCost != Cost::infinity ) { 1233 1273 // count one safe conversion for each value that is thrown away 1234 thisCost += Cost( 0, 0,discardedValues );1274 thisCost.incSafe( discardedValues ); 1235 1275 candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) ); 1236 1276 } -
src/ResolvExpr/CastCost.cc
rb3d413b r8135d4c 49 49 assert( type ); 50 50 if ( type->get_base() ) { 51 return castCost( src, type->get_base(), indexer, env ) + Cost ( 0, 0, 1 );51 return castCost( src, type->get_base(), indexer, env ) + Cost::safe; 52 52 } // if 53 53 } // if 54 54 } // if 55 55 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) { 56 return Cost ( 0, 0, 0 );56 return Cost::zero; 57 57 } else if ( dynamic_cast< VoidType* >( dest ) ) { 58 return Cost( 0, 0, 1 ); 58 return Cost::safe; 59 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 60 return convertToReferenceCost( src, refType, indexer, env ); 59 61 } else { 60 62 CastCost converter( dest, indexer, env ); … … 64 66 } else { 65 67 // xxx - why are we adding cost 0 here? 66 return converter.get_cost() + Cost ( 0, 0, 0 );68 return converter.get_cost() + Cost::zero; 67 69 } // if 68 70 } // if … … 77 79 if ( destAsPointer && basicType->isInteger() ) { 78 80 // necessary for, e.g. unsigned long => void* 79 cost = Cost ( 1, 0, 0 );81 cost = Cost::unsafe; 80 82 } else { 81 ConversionCost::visit( basicType);83 cost = conversionCost( basicType, dest, indexer, env ); 82 84 } // if 83 85 } … … 86 88 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 87 89 if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 88 cost = Cost ( 0, 0, 1 );90 cost = Cost::safe; 89 91 } else { 90 92 TypeEnvironment newEnv( env ); … … 93 95 int castResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer ); 94 96 if ( castResult > 0 ) { 95 cost = Cost ( 0, 0, 1 );97 cost = Cost::safe; 96 98 } else if ( castResult < 0 ) { 97 99 cost = Cost::infinity; … … 101 103 if ( destAsBasic->isInteger() ) { 102 104 // necessary for, e.g. void* => unsigned long 103 cost = Cost ( 1, 0, 0 );105 cost = Cost::unsafe; 104 106 } // if 105 107 } -
src/ResolvExpr/CommonType.cc
rb3d413b r8135d4c 26 26 #include "typeops.h" // for isFtype 27 27 28 29 /// #define DEBUG 28 // #define DEBUG 30 29 31 30 namespace ResolvExpr { … … 39 38 virtual void visit( PointerType *pointerType ); 40 39 virtual void visit( ArrayType *arrayType ); 40 virtual void visit( ReferenceType *refType ); 41 41 virtual void visit( FunctionType *functionType ); 42 42 virtual void visit( StructInstType *aggregateUseType ); … … 50 50 virtual void visit( OneType *oneType ); 51 51 52 void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ); 52 template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ); 53 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 53 54 54 55 Type *result; … … 60 61 }; 61 62 63 Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) { 64 Type * result = nullptr, * common = nullptr; 65 AssertionSet have, need; 66 OpenVarSet newOpen( openVars ); 67 // need unify to bind type variables 68 if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) { 69 // std::cerr << "unify success" << std::endl; 70 if ( widenSecond ) { 71 // std::cerr << "widen second" << std::endl; 72 if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) { 73 result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone(); 74 result->get_qualifiers() |= other->get_qualifiers(); 75 } 76 } else if ( widenFirst ) { 77 // std::cerr << "widen first" << std::endl; 78 if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) { 79 result = common; 80 result->get_qualifiers() |= refType->get_qualifiers(); 81 } 82 } 83 } else { 84 // std::cerr << "exact unify failed: " << refType << " " << other << std::endl; 85 } 86 // std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl; 87 return result; 88 } 89 62 90 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 63 91 CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 92 93 int depth1 = type1->referenceDepth(); 94 int depth2 = type2->referenceDepth(); 95 if ( depth1 > 0 || depth2 > 0 ) { 96 int diff = depth1-depth2; 97 // TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed. 98 if ( diff > 1 || diff < -1 ) return nullptr; 99 100 // special case where one type has a reference depth of 1 larger than the other 101 if ( diff > 0 ) { 102 return handleReference( safe_dynamic_cast<ReferenceType *>( type1 ), type2, widenFirst, widenSecond, indexer, env, openVars ); 103 } else if ( diff < 0 ) { 104 return handleReference( safe_dynamic_cast<ReferenceType *>( type2 ), type1, widenSecond, widenFirst, indexer, env, openVars ); 105 } 106 // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor. 107 } 108 64 109 type1->accept( visitor ); 65 110 Type *result = visitor.get_result(); … … 88 133 } // if 89 134 #ifdef DEBUG 90 std::c out<< "============= commonType" << std::endl << "type1 is ";91 type1->print( std::c out);92 std::c out<< " type2 is ";93 type2->print( std::c out);135 std::cerr << "============= commonType" << std::endl << "type1 is "; 136 type1->print( std::cerr ); 137 std::cerr << " type2 is "; 138 type2->print( std::cerr ); 94 139 if ( result ) { 95 std::c out<< " common type is ";96 result->print( std::c out);140 std::cerr << " common type is "; 141 result->print( std::cerr ); 97 142 } else { 98 std::c out<< " no common type";99 } // if 100 std::c out<< std::endl;143 std::cerr << " no common type"; 144 } // if 145 std::cerr << std::endl; 101 146 #endif 102 147 return result; … … 150 195 } 151 196 152 void CommonType::getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ) { 197 template< typename Pointer > 198 void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) { 153 199 if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) { 154 200 OpenVarSet::const_iterator entry = openVars.find( var->get_name() ); … … 165 211 void CommonType::visit( PointerType *pointerType ) { 166 212 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 213 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; 167 214 if ( widenFirst && dynamic_cast< VoidType* >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) { 168 215 getCommonWithVoidPointer( otherPointer, pointerType ); … … 171 218 } else if ( ( pointerType->get_base()->get_qualifiers() >= otherPointer->get_base()->get_qualifiers() || widenFirst ) 172 219 && ( pointerType->get_base()->get_qualifiers() <= otherPointer->get_base()->get_qualifiers() || widenSecond ) ) { 220 // std::cerr << "middle case" << std::endl; 173 221 Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(), tq2 = otherPointer->get_base()->get_qualifiers(); 174 222 pointerType->get_base()->get_qualifiers() = Type::Qualifiers(); … … 177 225 OpenVarSet newOpen( openVars ); 178 226 if ( unifyExact( pointerType->get_base(), otherPointer->get_base(), env, have, need, newOpen, indexer ) ) { 227 // std::cerr << "unifyExact success" << std::endl; 179 228 if ( tq1 < tq2 ) { 180 229 result = pointerType->clone(); … … 184 233 result->get_qualifiers() = tq1 | tq2; 185 234 } else { 186 /// std::c out<< "place for ptr-to-type" << std::endl;235 /// std::cerr << "place for ptr-to-type" << std::endl; 187 236 } // if 188 237 pointerType->get_base()->get_qualifiers() = tq1; … … 196 245 197 246 void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {} 247 248 void CommonType::visit( ReferenceType *refType ) { 249 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 250 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; 251 // std::cerr << ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) << (refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond) << std::endl; 252 if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) { 253 getCommonWithVoidPointer( otherRef, refType ); 254 } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) { 255 getCommonWithVoidPointer( refType, otherRef ); 256 } else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) 257 && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) { 258 // std::cerr << "middle case" << std::endl; 259 Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers(); 260 refType->get_base()->get_qualifiers() = Type::Qualifiers(); 261 otherRef->get_base()->get_qualifiers() = Type::Qualifiers(); 262 AssertionSet have, need; 263 OpenVarSet newOpen( openVars ); 264 if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) { 265 if ( tq1 < tq2 ) { 266 result = refType->clone(); 267 } else { 268 result = otherRef->clone(); 269 } // if 270 result->get_qualifiers() = tq1 | tq2; 271 } else { 272 /// std::cerr << "place for ptr-to-type" << std::endl; 273 } // if 274 refType->get_base()->get_qualifiers() = tq1; 275 otherRef->get_base()->get_qualifiers() = tq2; 276 } // if 277 } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) { 278 result = refType->clone(); 279 result->get_qualifiers() |= type2->get_qualifiers(); 280 } // if 281 } 282 198 283 void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {} 199 284 void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {} … … 203 288 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 204 289 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType 205 Type * temp = type2;290 ValueGuard< Type * > temp( type2 ); 206 291 type2 = enumInstType; 207 temp->accept( *this ); 208 type2 = temp; 292 temp.old->accept( *this ); 209 293 } // if 210 294 } -
src/ResolvExpr/ConversionCost.cc
rb3d413b r8135d4c 28 28 29 29 namespace ResolvExpr { 30 const Cost Cost::zero = Cost( 0, 0, 0 ); 31 const Cost Cost::infinity = Cost( -1, -1, -1 ); 30 const Cost Cost::zero = Cost( 0, 0, 0, 0 ); 31 const Cost Cost::infinity = Cost( -1, -1, -1, -1 ); 32 const Cost Cost::unsafe = Cost( 1, 0, 0, 0 ); 33 const Cost Cost::poly = Cost( 0, 1, 0, 0 ); 34 const Cost Cost::safe = Cost( 0, 0, 1, 0 ); 35 const Cost Cost::reference = Cost( 0, 0, 0, 1 ); 36 37 #if 0 38 #define PRINT(x) x 39 #else 40 #define PRINT(x) 41 #endif 32 42 33 43 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { … … 35 45 EqvClass eqvClass; 36 46 NamedTypeDecl *namedType; 37 /// std::cout << "type inst " << destAsTypeInst->get_name(); 47 PRINT( std::cerr << "type inst " << destAsTypeInst->get_name(); ) 38 48 if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) { 39 49 if ( eqvClass.type ) { … … 43 53 } 44 54 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) { 45 /// std::cout << " found" << std::endl; 55 PRINT( std::cerr << " found" << std::endl; ) 46 56 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 47 57 // all typedefs should be gone by this point 48 58 assert( type ); 49 59 if ( type->get_base() ) { 50 return conversionCost( src, type->get_base(), indexer, env ) + Cost ( 0, 0, 1 );60 return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe; 51 61 } // if 52 62 } // if 53 /// std::cout << " not found" << std::endl; 54 } // if 55 /// std::cout << "src is "; 56 /// src->print( std::cout ); 57 /// std::cout << std::endl << "dest is "; 58 /// dest->print( std::cout ); 59 /// std::cout << std::endl << "env is" << std::endl; 60 /// env.print( std::cout, 8 ); 63 PRINT( std::cerr << " not found" << std::endl; ) 64 } // if 65 PRINT( 66 std::cerr << "src is "; 67 src->print( std::cerr ); 68 std::cerr << std::endl << "dest is "; 69 dest->print( std::cerr ); 70 std::cerr << std::endl << "env is" << std::endl; 71 env.print( std::cerr, 8 ); 72 ) 61 73 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) { 62 /// std::cout << "compatible!" << std::endl; 63 return Cost ( 0, 0, 0 );74 PRINT( std::cerr << "compatible!" << std::endl; ) 75 return Cost::zero; 64 76 } else if ( dynamic_cast< VoidType* >( dest ) ) { 65 return Cost( 0, 0, 1 ); 77 return Cost::safe; 78 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 79 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 80 return convertToReferenceCost( src, refType, indexer, env ); 66 81 } else { 67 82 ConversionCost converter( dest, indexer, env ); … … 70 85 return Cost::infinity; 71 86 } else { 72 return converter.get_cost() + Cost( 0, 0, 0 ); 73 } // if 74 } // if 87 return converter.get_cost() + Cost::zero; 88 } // if 89 } // if 90 } 91 92 Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 93 PRINT( std::cerr << "convert to reference cost..." << std::endl; ) 94 if ( diff > 0 ) { 95 // TODO: document this 96 Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env ); 97 cost.incReference(); 98 return cost; 99 } else if ( diff < -1 ) { 100 // TODO: document this 101 Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env ); 102 cost.incReference(); 103 return cost; 104 } else if ( diff == 0 ) { 105 ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src ); 106 ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest ); 107 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 108 PRINT( std::cerr << "converting between references" << std::endl; ) 109 if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) { 110 return Cost::safe; 111 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 112 int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env ); 113 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 114 if ( assignResult < 0 ) { 115 return Cost::safe; 116 } else if ( assignResult > 0 ) { 117 return Cost::unsafe; 118 } // if 119 } // if 120 } else { 121 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 122 ConversionCost converter( dest, indexer, env ); 123 src->accept( converter ); 124 return converter.get_cost(); 125 } // if 126 } else { 127 ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest ); 128 assert( diff == -1 && destAsRef ); 129 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) { 130 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 131 if ( src->get_lvalue() ) { 132 PRINT( 133 std::cerr << "lvalue to reference conversion" << std::endl; 134 std::cerr << src << " => " << destAsRef << std::endl; 135 ) 136 // lvalue-to-reference conversion: cv lvalue T => cv T & 137 if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) { 138 return Cost::reference; // cost needs to be non-zero to add cast 139 } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) { 140 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 141 } else { 142 return Cost::unsafe; 143 } // if 144 } else if ( destAsRef->get_base()->get_const() ) { 145 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; ) 146 // rvalue-to-const-reference conversion: T => const T & 147 return Cost::safe; 148 } else { 149 PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; ) 150 // rvalue-to-reference conversion: T => T & 151 return Cost::unsafe; 152 } // if 153 } // if 154 PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; ) 155 } 156 return Cost::infinity; 157 } 158 159 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 160 int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth(); 161 return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env ); 75 162 } 76 163 … … 164 251 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; 165 252 if ( tableResult == -1 ) { 166 cost = Cost( 1, 0, 0 ); 167 } else { 168 cost = Cost( 0, 0, tableResult ); 253 cost = Cost::unsafe; 254 } else { 255 cost = Cost::zero; 256 cost.incSafe( tableResult ); 169 257 } // if 170 258 } else if ( dynamic_cast< EnumInstType *>( dest ) ) { 171 259 // xxx - not positive this is correct, but appears to allow casting int => enum 172 cost = Cost ( 1, 0, 0 );260 cost = Cost::unsafe; 173 261 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) { 174 cost = Cost ( 1, 0, 0 );262 cost = Cost::unsafe; 175 263 } // if 176 264 } … … 178 266 void ConversionCost::visit(PointerType *pointerType) { 179 267 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 180 if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 181 cost = Cost( 0, 0, 1 ); 182 } else { 268 PRINT( std::cerr << pointerType << " ===> " << destAsPtr; ) 269 Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(); 270 Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers(); 271 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 272 if ( tq1 == tq2 ) { 273 // types are the same 274 cost = Cost::zero; 275 } else { 276 // types are the same, except otherPointer has more qualifiers 277 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 278 cost = Cost::safe; 279 } 280 } else { // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 183 281 int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env ); 184 if ( assignResult < 0 ) { 185 cost = Cost( 0, 0, 1 ); 282 PRINT( std::cerr << " :: " << assignResult << std::endl; ) 283 if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) { 284 cost = Cost::safe; 186 285 } else if ( assignResult > 0 ) { 187 cost = Cost ( 1, 0, 0 );286 cost = Cost::unsafe; 188 287 } // if 288 // assignResult == 0 means Cost::Infinity 189 289 } // if 190 290 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) { 191 cost = Cost ( 1, 0, 0 );291 cost = Cost::unsafe; 192 292 } // if 193 293 } 194 294 195 295 void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {} 296 297 void ConversionCost::visit(ReferenceType *refType) { 298 // Note: dest can never be a reference, since it would have been caught in an earlier check 299 assert( ! dynamic_cast< ReferenceType * >( dest ) ); 300 // convert reference to rvalue: cv T1 & => T2 301 // recursively compute conversion cost from T1 to T2. 302 // cv can be safely dropped because of 'implicit dereference' behavior. 303 refType->get_base()->accept( *this ); 304 if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) { 305 cost.incReference(); // prefer exact qualifiers 306 } else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) { 307 cost.incSafe(); // then gaining qualifiers 308 } else { 309 cost.incUnsafe(); // lose qualifiers as last resort 310 } 311 PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; ) 312 } 313 196 314 void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {} 197 315 … … 215 333 static Type::Qualifiers q; 216 334 static BasicType integer( q, BasicType::SignedInt ); 217 integer.accept( *this ); 218 if ( cost < Cost ( 1, 0, 0 )) {335 integer.accept( *this ); // safe if dest >= int 336 if ( cost < Cost::unsafe ) { 219 337 cost.incSafe(); 220 338 } // if … … 238 356 assert( type ); 239 357 if ( type->get_base() ) { 240 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost ( 0, 0, 1 );358 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe; 241 359 } // if 242 360 } // if … … 244 362 245 363 void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) { 246 Cost c ;364 Cost c = Cost::zero; 247 365 if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) { 248 366 std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin(); … … 276 394 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ]; 277 395 if ( tableResult == -1 ) { 278 cost = Cost( 1, 0, 0 ); 279 } else { 280 cost = Cost( 0, 0, tableResult + 1 ); 396 cost = Cost::unsafe; 397 } else { 398 cost = Cost::zero; 399 cost.incSafe( tableResult + 1 ); 281 400 } 282 401 } else if ( dynamic_cast< PointerType* >( dest ) ) { 283 cost = Cost ( 0, 0, 1 );402 cost = Cost::safe; 284 403 } 285 404 } … … 292 411 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ]; 293 412 if ( tableResult == -1 ) { 294 cost = Cost( 1, 0, 0 ); 295 } else { 296 cost = Cost( 0, 0, tableResult + 1 ); 413 cost = Cost::unsafe; 414 } else { 415 cost = Cost::zero; 416 cost.incSafe( tableResult + 1 ); 297 417 } 298 418 } -
src/ResolvExpr/ConversionCost.h
rb3d413b r8135d4c 37 37 virtual void visit(PointerType *pointerType); 38 38 virtual void visit(ArrayType *arrayType); 39 virtual void visit(ReferenceType *refType); 39 40 virtual void visit(FunctionType *functionType); 40 41 virtual void visit(StructInstType *aggregateUseType); … … 53 54 const TypeEnvironment &env; 54 55 }; 56 57 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 55 58 } // namespace ResolvExpr 56 59 -
src/ResolvExpr/Cost.h
rb3d413b r8135d4c 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Cost.h -- 7 // Cost.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 20 20 namespace ResolvExpr { 21 21 class Cost { 22 private: 23 Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ); 24 22 25 public: 23 Cost(); 24 Cost( int unsafe, int poly, int safe ); 25 26 void incUnsafe( int inc = 1 ); 27 void incPoly( int inc = 1 ); 28 void incSafe( int inc = 1 ); 29 26 Cost & incUnsafe( int inc = 1 ); 27 Cost & incPoly( int inc = 1 ); 28 Cost & incSafe( int inc = 1 ); 29 Cost & incReference( int inc = 1 ); 30 30 31 Cost operator+( const Cost &other ) const; 31 32 Cost operator-( const Cost &other ) const; … … 35 36 bool operator!=( const Cost &other ) const; 36 37 friend std::ostream &operator<<( std::ostream &os, const Cost &cost ); 37 38 38 39 static const Cost zero; 39 40 static const Cost infinity; 41 42 static const Cost unsafe; 43 static const Cost poly; 44 static const Cost safe; 45 static const Cost reference; 40 46 private: 41 47 int compare( const Cost &other ) const; 42 48 43 int unsafe; 44 int poly; 45 int safe; 49 int unsafeCost; 50 int polyCost; 51 int safeCost; 52 int referenceCost; 46 53 }; 47 54 48 inline Cost::Cost( ) : unsafe( 0 ), poly( 0 ), safe( 0) {}55 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {} 49 56 50 inline Cost ::Cost( int unsafe, int poly, int safe ) : unsafe( unsafe ), poly( poly ), safe( safe ) {}51 52 inline void Cost::incUnsafe( int inc ) {53 unsafe += inc;57 inline Cost & Cost::incUnsafe( int inc ) { 58 if ( *this == infinity ) return *this; 59 unsafeCost += inc; 60 return *this; 54 61 } 55 62 56 inline void Cost::incPoly( int inc ) { 57 poly += inc; 63 inline Cost & Cost::incPoly( int inc ) { 64 if ( *this == infinity ) return *this; 65 polyCost += inc; 66 return *this; 58 67 } 59 68 60 inline void Cost::incSafe( int inc ) { 61 safe += inc; 69 inline Cost & Cost::incSafe( int inc ) { 70 if ( *this == infinity ) return *this; 71 safeCost += inc; 72 return *this; 73 } 74 75 inline Cost & Cost::incReference( int inc ) { 76 if ( *this == infinity ) return *this; 77 referenceCost += inc; 78 return *this; 62 79 } 63 80 64 81 inline Cost Cost::operator+( const Cost &other ) const { 65 return Cost( unsafe + other.unsafe, poly + other.poly, safe + other.safe ); 82 if ( *this == infinity || other == infinity ) return infinity; 83 return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost ); 66 84 } 67 85 68 86 inline Cost Cost::operator-( const Cost &other ) const { 69 return Cost( unsafe - other.unsafe, poly - other.poly, safe - other.safe ); 87 if ( *this == infinity || other == infinity ) return infinity; 88 return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost ); 70 89 } 71 90 72 91 inline Cost &Cost::operator+=( const Cost &other ) { 73 unsafe += other.unsafe; 74 poly += other.poly; 75 safe += other.safe; 92 if ( *this == infinity ) return *this; 93 if ( other == infinity ) { 94 *this = infinity; 95 return *this; 96 } 97 unsafeCost += other.unsafeCost; 98 polyCost += other.polyCost; 99 safeCost += other.safeCost; 100 referenceCost += other.referenceCost; 76 101 return *this; 77 102 } 78 103 79 104 inline bool Cost::operator<( const Cost &other ) const { 80 if ( *this == infinity ) return false; 81 if ( other == infinity ) return true; 82 if ( unsafe > other.unsafe ) { 105 if ( *this == infinity ) return false; 106 if ( other == infinity ) return true; 107 108 if ( unsafeCost > other.unsafeCost ) { 83 109 return false; 84 } else if ( unsafe < other.unsafe) {110 } else if ( unsafeCost < other.unsafeCost ) { 85 111 return true; 86 } else if ( poly > other.poly) {112 } else if ( polyCost > other.polyCost ) { 87 113 return false; 88 } else if ( poly < other.poly) {114 } else if ( polyCost < other.polyCost ) { 89 115 return true; 90 } else if ( safe > other.safe) {116 } else if ( safeCost > other.safeCost ) { 91 117 return false; 92 } else if ( safe < other.safe) {118 } else if ( safeCost < other.safeCost ) { 93 119 return true; 94 } else{120 } else if ( referenceCost > other.referenceCost ) { 95 121 return false; 96 } // if 122 } else if ( referenceCost < other.referenceCost ) { 123 return true; 124 } else { 125 return false; 126 } // if 97 127 } 98 128 99 129 inline bool Cost::operator==( const Cost &other ) const { 100 return unsafe == other.unsafe 101 && poly == other.poly 102 && safe == other.safe; 130 return unsafeCost == other.unsafeCost 131 && polyCost == other.polyCost 132 && safeCost == other.safeCost 133 && referenceCost == other.referenceCost; 103 134 } 104 135 … … 108 139 109 140 inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) { 110 os << "( " << cost.unsafe << ", " << cost.poly << ", " << cost.safe<< " )";141 os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )"; 111 142 return os; 112 143 } -
src/ResolvExpr/PtrsAssignable.cc
rb3d413b r8135d4c 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // PtrsAssignable.cc -- 7 // PtrsAssignable.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 82 82 void PtrsAssignable::visit( __attribute__((unused)) UnionInstType *inst ) {} 83 83 84 void PtrsAssignable::visit( EnumInstType * inst) {85 if ( dynamic_cast< EnumInstType* >( inst ) ) {84 void PtrsAssignable::visit( EnumInstType * ) { 85 if ( dynamic_cast< EnumInstType* >( dest ) ) { 86 86 result = 1; 87 } else if ( BasicType *bt = dynamic_cast< BasicType* >( inst ) ) {87 } else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) { 88 88 result = bt->get_kind() == BasicType::SignedInt; 89 89 } … … 104 104 void PtrsAssignable::visit( __attribute__((unused)) ZeroType *zeroType ) {} 105 105 void PtrsAssignable::visit( __attribute__((unused)) OneType *oneType ) {} 106 106 107 107 } // namespace ResolvExpr 108 108 -
src/ResolvExpr/ResolveTypeof.cc
rb3d413b r8135d4c 65 65 assert( newExpr->has_result() && ! newExpr->get_result()->isVoid() ); 66 66 Type *newType = newExpr->get_result(); 67 newExpr->set_result( nullptr ); 67 68 delete typeofType; 69 delete newExpr; 68 70 return newType; 69 71 } // if -
src/ResolvExpr/Unify.cc
rb3d413b r8135d4c 53 53 virtual void visit(PointerType *pointerType); 54 54 virtual void visit(ArrayType *arrayType); 55 virtual void visit(ReferenceType *refType); 55 56 virtual void visit(FunctionType *functionType); 56 57 virtual void visit(StructInstType *aggregateUseType); … … 153 154 154 155 bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 156 // remove references from other, so that type variables can only bind to value types 157 other = other->stripReferences(); 155 158 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() ); 156 159 assert( tyvar != openVars.end() ); … … 387 390 } // if 388 391 } else { 392 common = type1->clone(); 393 common->get_qualifiers() = tq1 | tq2; 389 394 result = true; 390 395 } // if … … 436 441 markAssertions( haveAssertions, needAssertions, pointerType ); 437 442 markAssertions( haveAssertions, needAssertions, otherPointer ); 443 } // if 444 } 445 446 void Unify::visit(ReferenceType *refType) { 447 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 448 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 449 markAssertions( haveAssertions, needAssertions, refType ); 450 markAssertions( haveAssertions, needAssertions, otherRef ); 438 451 } // if 439 452 } -
src/ResolvExpr/typeops.h
rb3d413b r8135d4c 66 66 Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 67 67 68 template< typename SrcIterator, typename DestIterator >69 Cost castCostList( SrcIterator srcBegin, SrcIterator srcEnd, DestIterator destBegin, DestIterator destEnd, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {70 Cost ret;71 if ( destBegin == destEnd ) {72 if ( srcBegin == srcEnd ) {73 return Cost::zero;74 } else {75 return Cost( 0, 0, 1 );76 } // if77 } // if78 while ( srcBegin != srcEnd && destBegin != destEnd ) {79 Cost thisCost = castCost( *srcBegin++, *destBegin++, indexer, env );80 if ( thisCost == Cost::infinity ) {81 return Cost::infinity;82 } // if83 ret += thisCost;84 } // while85 if ( srcBegin == srcEnd && destBegin == destEnd ) {86 return ret;87 } else {88 return Cost::infinity;89 } // if90 }91 92 68 // in ConversionCost.cc 93 69 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 94 95 template< typename SrcIterator, typename DestIterator >96 Cost conversionCostList( SrcIterator srcBegin, SrcIterator srcEnd, DestIterator destBegin, DestIterator destEnd, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {97 Cost ret;98 while ( srcBegin != srcEnd && destBegin != destEnd ) {99 Cost thisCost = conversionCost( *srcBegin++, *destBegin++, indexer, env );100 if ( thisCost == Cost::infinity ) {101 return Cost::infinity;102 } // if103 ret += thisCost;104 } // while105 if ( srcBegin == srcEnd && destBegin == destEnd ) {106 return ret;107 } else {108 return Cost::infinity;109 } // if110 }111 70 112 71 // in PtrsAssignable.cc -
src/SymTab/Autogen.cc
rb3d413b r8135d4c 13 13 // Update Count : 62 14 14 // 15 15 16 #include "Autogen.h" 16 17 … … 24 25 #include <vector> // for vector 25 26 26 #include "AddVisit.h" // for addVisit 27 #include "Common/ScopedMap.h" // for ScopedMap 28 #include "GenPoly/DeclMutator.h" // for DeclMutator 29 #include "GenPoly/ScopedSet.h" // for ScopedSet 30 #include "Parser/LinkageSpec.h" // for AutoGen, Intrinsic, Spec 31 #include "SymTab/Mangler.h" // for mangleType 32 #include "SynTree/Statement.h" // for SwitchStmt (ptr only), CompoundStmt 33 #include "SynTree/Type.h" // for Type, ArrayType, Type::StorageClasses 34 #include "SynTree/Visitor.h" // for Visitor 27 #include "AddVisit.h" // for addVisit 28 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 29 #include "Common/ScopedMap.h" // for ScopedMap<>::const_iterator, Scope... 30 #include "Common/utility.h" // for cloneAll, operator+ 31 #include "GenPoly/DeclMutator.h" // for DeclMutator 32 #include "GenPoly/ScopedSet.h" // for ScopedSet, ScopedSet<>::iterator 33 #include "SymTab/Mangler.h" // for Mangler 34 #include "SynTree/Attribute.h" // For Attribute 35 #include "SynTree/Mutator.h" // for maybeMutate 36 #include "SynTree/Statement.h" // for CompoundStmt, ReturnStmt, ExprStmt 37 #include "SynTree/Type.h" // for FunctionType, Type, TypeInstType 38 #include "SynTree/Visitor.h" // for maybeAccept, Visitor, acceptAll 39 40 class Attribute; 35 41 36 42 namespace SymTab { … … 130 136 FunctionType * genDefaultType( Type * paramType ) { 131 137 FunctionType *ftype = new FunctionType( Type::Qualifiers(), false ); 132 ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), paramType->clone() ), nullptr );138 ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr ); 133 139 ftype->get_parameters().push_back( dstParam ); 134 140 … … 150 156 ftype->get_returnVals().push_back( returnVal ); 151 157 return ftype; 152 }153 154 /// true if the aggregate's layout is dynamic155 template< typename AggrDecl >156 bool hasDynamicLayout( AggrDecl * aggregateDecl ) {157 for ( TypeDecl * param : aggregateDecl->get_parameters() ) {158 if ( param->isComplete() ) return true;159 }160 return false;161 158 } 162 159 … … 181 178 FunctionType * ftype = funcDecl->get_functionType(); 182 179 assert( ! ftype->get_parameters().empty() ); 183 Type * t = safe_dynamic_cast< PointerType * >( ftype->get_parameters().front()->get_type() )->get_base(); 180 Type * t = InitTweak::getPointerBase( ftype->get_parameters().front()->get_type() ); 181 assert( t ); 184 182 map.insert( Mangler::mangleType( t ), true ); 185 183 } … … 227 225 FunctionType * ftype = data.genType( refType ); 228 226 229 if(concurrent_type && InitTweak::isDestructor( data.fname )) {227 if(concurrent_type && CodeGen::isDestructor( data.fname )) { 230 228 ftype->get_parameters().front()->get_type()->set_mutex( true ); 231 229 } … … 279 277 FunctionType *copyCtorType = genCopyType( refType->clone() ); 280 278 279 // add unused attribute to parameters of default constructor and destructor 280 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 281 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 282 281 283 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)? 282 284 // right now these cases work, but that might change. … … 301 303 302 304 /// generates a single struct member operation (constructor call, destructor call, assignment call) 303 void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) { 304 ObjectDecl * returnVal = NULL; 305 if ( ! func->get_functionType()->get_returnVals().empty() ) { 306 returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() ); 307 } 308 305 void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true ) { 309 306 InitTweak::InitExpander srcParam( src ); 310 307 311 // assign to destination (and return value if generic) 312 UntypedExpr *derefExpr = UntypedExpr::createDeref( new VariableExpr( dstParam ) ); 313 Expression *dstselect = new MemberExpr( field, derefExpr ); 308 // assign to destination 309 Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), safe_dynamic_cast< ReferenceType* >( dstParam->get_type() )->get_base()->clone() ) ); 314 310 genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward ); 315 316 if ( isDynamicLayout && returnVal ) {317 // xxx - there used to be a dereference on returnVal, but this seems to have been wrong?318 Expression *retselect = new MemberExpr( field, new VariableExpr( returnVal ) );319 genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );320 } // if321 311 } 322 312 323 313 /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies 324 314 template<typename Iterator> 325 void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout, boolforward = true ) {315 void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true ) { 326 316 for ( ; member != end; ++member ) { 327 317 if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate … … 359 349 360 350 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL; 361 makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout,forward );351 makeStructMemberOp( dstParam, srcselect, field, func, forward ); 362 352 } // if 363 353 } // for … … 367 357 /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields. 368 358 template<typename Iterator> 369 void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func , bool isDynamicLayout) {359 void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) { 370 360 FunctionType * ftype = func->get_functionType(); 371 361 std::list<DeclarationWithType*> & params = ftype->get_parameters(); … … 393 383 // matching parameter, initialize field with copy ctor 394 384 Expression *srcselect = new VariableExpr(*parameter); 395 makeStructMemberOp( dstParam, srcselect, field, func , isDynamicLayout);385 makeStructMemberOp( dstParam, srcselect, field, func ); 396 386 ++parameter; 397 387 } else { 398 388 // no matching parameter, initialize field with default ctor 399 makeStructMemberOp( dstParam, NULL, field, func , isDynamicLayout);389 makeStructMemberOp( dstParam, NULL, field, func ); 400 390 } 401 391 } … … 413 403 // Make function polymorphic in same parameters as generic struct, if applicable 414 404 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 415 bool isDynamicLayout = hasDynamicLayout( aggregateDecl ); // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)416 405 417 406 // generate each of the functions based on the supplied FuncData objects … … 423 412 424 413 // field ctors are only generated if default constructor and copy constructor are both generated 425 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return InitTweak::isConstructor( dcl->get_name() ); } );414 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } ); 426 415 427 416 if ( functionNesting == 0 ) { … … 438 427 // generate appropriate calls to member ctor, assignment 439 428 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor 440 if ( ! InitTweak::isDestructor( dcl->get_name() ) ) {441 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl , isDynamicLayout);429 if ( ! CodeGen::isDestructor( dcl->get_name() ) ) { 430 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl ); 442 431 } else { 443 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, isDynamicLayout,false );444 } 445 if ( InitTweak::isAssignment( dcl->get_name() ) ) {432 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, false ); 433 } 434 if ( CodeGen::isAssignment( dcl->get_name() ) ) { 446 435 // assignment needs to return a value 447 436 FunctionType * assignType = dcl->get_functionType(); … … 472 461 // our inheritance model. I think the correct way to handle this is to 473 462 // cast the structure to the type of the member and let the resolver 474 // figure out whether it's valid and have a pass afterwards that fixes 475 // the assignment to use pointer arithmetic with the offset of the 476 // member, much like how generic type members are handled. 463 // figure out whether it's valid/choose the correct unnamed member 477 464 continue; 478 465 } 479 466 memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) ); 480 467 FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting ); 481 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor , isDynamicLayout);468 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor ); 482 469 declsToAdd.push_back( ctor ); 483 470 } … … 490 477 void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) { 491 478 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) ); 492 copy->get_args().push_back( new VariableExpr( dstParam) );479 copy->get_args().push_back( new AddressExpr( new VariableExpr( dstParam ) ) ); 493 480 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) ); 494 481 copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) ); … … 502 489 ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() ); 503 490 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() ); 504 ObjectDecl * returnVal = nullptr;505 if ( ! ftype->get_returnVals().empty() ) {506 returnVal = safe_dynamic_cast< ObjectDecl * >( ftype->get_returnVals().front() );507 }508 491 509 492 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) ); 510 if ( returnVal ) { 493 if ( CodeGen::isAssignment( funcDecl->get_name() ) ) { 494 // also generate return statement in assignment 511 495 funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 512 496 } … … 535 519 cloneAll( typeParams, copyCtorType->get_forall() ); 536 520 cloneAll( typeParams, assignType->get_forall() ); 521 522 // add unused attribute to parameters of default constructor and destructor 523 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 524 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 537 525 538 526 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units -
src/SymTab/Autogen.h
rb3d413b r8135d4c 40 40 extern Type * SizeType; 41 41 42 /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations. 43 /// Useful for creating dereference ApplicationExprs without a full resolver pass. 44 extern FunctionDecl * dereferenceOperator; 45 46 // temporary 47 FunctionType * genAssignType( Type * paramType ); 48 42 49 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 43 50 template< typename OutputIterator > … … 48 55 template< typename OutputIterator > 49 56 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) { 50 // want to be able to generate assignment, ctor, and dtor generically,51 // so fname is either ?=?, ?{}, or ^?{}52 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );57 // want to be able to generate assignment, ctor, and dtor generically, 58 // so fname is either ?=?, ?{}, or ^?{} 59 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) ); 53 60 54 // do something special for unnamed members 55 dstParam = new AddressExpr( dstParam ); 56 if ( addCast ) { 57 // cast to T* with qualifiers removed, so that qualified objects can be constructed 58 // and destructed with the same functions as non-qualified objects. 59 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument 60 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 61 // remove lvalue as a qualifier, this can change to 62 // type->get_qualifiers() = Type::Qualifiers(); 63 assert( type ); 64 Type * castType = type->clone(); 65 castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 66 castType->set_lvalue( true ); // xxx - might not need this 67 dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) ); 68 } 69 fExpr->get_args().push_back( dstParam ); 61 if ( addCast ) { 62 // cast to T& with qualifiers removed, so that qualified objects can be constructed 63 // and destructed with the same functions as non-qualified objects. 64 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument 65 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 66 // remove lvalue as a qualifier, this can change to 67 // type->get_qualifiers() = Type::Qualifiers(); 68 assert( type ); 69 Type * castType = type->clone(); 70 castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 71 // castType->set_lvalue( true ); // xxx - might not need this 72 dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) ); 73 } 74 fExpr->get_args().push_back( dstParam ); 70 75 71 Statement * listInit = srcParam.buildListInit( fExpr );76 Statement * listInit = srcParam.buildListInit( fExpr ); 72 77 73 std::list< Expression * > args = *++srcParam;74 fExpr->get_args().splice( fExpr->get_args().end(), args );78 std::list< Expression * > args = *++srcParam; 79 fExpr->get_args().splice( fExpr->get_args().end(), args ); 75 80 76 *out++ = new ExprStmt( noLabels, fExpr );81 *out++ = new ExprStmt( noLabels, fExpr ); 77 82 78 srcParam.clearArrayIndices();83 srcParam.clearArrayIndices(); 79 84 80 return listInit;85 return listInit; 81 86 } 82 87 … … 114 119 115 120 UntypedExpr *inc = new UntypedExpr( update ); 116 inc->get_args().push_back( new AddressExpr( new VariableExpr( index )) );121 inc->get_args().push_back( new VariableExpr( index ) ); 117 122 118 123 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) ); -
src/SymTab/Indexer.cc
rb3d413b r8135d4c 23 23 #include <utility> // for pair, make_pair, move 24 24 25 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 25 26 #include "Common/SemanticError.h" // for SemanticError 26 27 #include "Common/utility.h" // for cloneAll … … 111 112 void Indexer::removeSpecialOverrides( const std::string &id, std::list< DeclarationWithType * > & out ) const { 112 113 // only need to perform this step for constructors, destructors, and assignment functions 113 if ( ! InitTweak::isCtorDtorAssign( id ) ) return;114 if ( ! CodeGen::isCtorDtorAssign( id ) ) return; 114 115 115 116 // helpful data structure … … 139 140 decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } ); 140 141 existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc; 141 existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) );142 existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && CodeGen::isConstructor( function->get_name() ) ); 142 143 existsUserDefinedDtor = existsUserDefinedDtor || (isUserDefinedFunc && isDtor); 143 144 existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc); … … 157 158 assert( ! params.empty() ); 158 159 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 159 Type * base = safe_dynamic_cast< PointerType * >( params.front()->get_type() )->get_base(); 160 Type * base = InitTweak::getPointerBase( params.front()->get_type() ); 161 assert( base ); 160 162 funcMap[ Mangler::mangle( base ) ] += function; 161 163 } else { -
src/SymTab/Mangler.cc
rb3d413b r8135d4c 132 132 mangleName << "A0"; 133 133 maybeAccept( arrayType->get_base(), *this ); 134 } 135 136 void Mangler::visit( ReferenceType *refType ) { 137 printQualifiers( refType ); 138 mangleName << "R"; 139 maybeAccept( refType->get_base(), *this ); 134 140 } 135 141 … … 303 309 // Removed due to restrict not affecting function compatibility in GCC 304 310 // if ( type->get_isRestrict() ) { 305 // mangleName << " R";311 // mangleName << "E"; 306 312 // } // if 307 313 if ( type->get_lvalue() ) { -
src/SymTab/Mangler.h
rb3d413b r8135d4c 42 42 virtual void visit( PointerType *pointerType ); 43 43 virtual void visit( ArrayType *arrayType ); 44 virtual void visit( ReferenceType *refType ); 44 45 virtual void visit( FunctionType *functionType ); 45 46 virtual void visit( StructInstType *aggregateUseType ); -
src/SymTab/Validate.cc
rb3d413b r8135d4c 47 47 48 48 #include "CodeGen/CodeGenerator.h" // for genName 49 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 49 50 #include "Common/PassVisitor.h" // for PassVisitor, WithDeclsToAdd 50 51 #include "Common/ScopedMap.h" // for ScopedMap … … 239 240 }; 240 241 242 243 FunctionDecl * dereferenceOperator = nullptr; 244 struct FindSpecialDeclarations final { 245 void previsit( FunctionDecl * funcDecl ); 246 }; 247 241 248 void validate( std::list< Declaration * > &translationUnit, bool doDebug ) { 242 249 PassVisitor<EnumAndPointerDecay> epc; … … 245 252 PassVisitor<CompoundLiteral> compoundliteral; 246 253 PassVisitor<ValidateGenericParameters> genericParams; 254 PassVisitor<FindSpecialDeclarations> finder; 247 255 248 256 EliminateTypedef::eliminateTypedef( translationUnit ); … … 261 269 acceptAll( translationUnit, fpd ); 262 270 ArrayLength::computeLength( translationUnit ); 271 acceptAll( translationUnit, finder ); 263 272 } 264 273 … … 821 830 std::list< DeclarationWithType * > ¶ms = funcType->get_parameters(); 822 831 823 if ( InitTweak::isCtorDtorAssign( funcDecl->get_name() ) ) {832 if ( CodeGen::isCtorDtorAssign( funcDecl->get_name() ) ) { // TODO: also check /=, etc. 824 833 if ( params.size() == 0 ) { 825 834 throw SemanticError( "Constructors, destructors, and assignment functions require at least one parameter ", funcDecl ); 826 835 } 827 PointerType * ptrType = dynamic_cast< PointerType * >( params.front()->get_type() );828 if ( ! ptrType || ptrType->is_array()) {829 throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a pointer", funcDecl );836 ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() ); 837 if ( ! refType ) { 838 throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a reference ", funcDecl ); 830 839 } 831 if ( InitTweak::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) {840 if ( CodeGen::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) { 832 841 throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl ); 833 842 } … … 945 954 } 946 955 } 956 957 void FindSpecialDeclarations::previsit( FunctionDecl * funcDecl ) { 958 if ( ! dereferenceOperator ) { 959 if ( funcDecl->get_name() == "*?" && funcDecl->get_linkage() == LinkageSpec::Intrinsic ) { 960 FunctionType * ftype = funcDecl->get_functionType(); 961 if ( ftype->get_parameters().size() == 1 && ftype->get_parameters().front()->get_type()->get_qualifiers() == Type::Qualifiers() ) { 962 dereferenceOperator = funcDecl; 963 } 964 } 965 } 966 } 947 967 } // namespace SymTab 948 968 -
src/SynTree/AddressExpr.cc
rb3d413b r8135d4c 21 21 #include "Type.h" // for PointerType, Type, Type::Qualifiers 22 22 23 // Address expressions are typed based on the following inference rules: 24 // E : lvalue T &..& (n references) 25 // &E : T *&..& (n references) 26 // 27 // E : T &..& (m references) 28 // &E : T *&..& (m-1 references) 29 // 30 // That is, lvalues becomes 31 32 namespace { 33 Type * addrType( Type * type ) { 34 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) { 35 return new ReferenceType( refType->get_qualifiers(), addrType( refType->get_base() ) ); 36 } else { 37 return new PointerType( Type::Qualifiers(), type->clone() ); 38 } 39 } 40 } 41 23 42 AddressExpr::AddressExpr( Expression *arg, Expression *_aname ) : Expression( _aname ), arg( arg ) { 24 43 if ( arg->has_result() ) { 25 set_result( new PointerType( Type::Qualifiers(), arg->get_result()->clone() ) ); 44 if ( arg->get_result()->get_lvalue() ) { 45 // lvalue, retains all layers of reference and gains a pointer inside the references 46 set_result( addrType( arg->get_result() ) ); 47 } else { 48 // taking address of non-lvalue -- must be a reference, loses one layer of reference 49 ReferenceType * refType = safe_dynamic_cast< ReferenceType * >( arg->get_result() ); 50 set_result( addrType( refType->get_base() ) ); 51 } 52 // result of & is never an lvalue 53 get_result()->set_lvalue( false ); 26 54 } 27 55 } -
src/SynTree/ApplicationExpr.cc
rb3d413b r8135d4c 49 49 } 50 50 51 ApplicationExpr::ApplicationExpr( Expression *funcExpr, const std::list< Expression * > & argList ) : function( funcExpr ), args( argList) {51 ApplicationExpr::ApplicationExpr( Expression *funcExpr, const std::list<Expression *> & args ) : function( funcExpr ), args( args ) { 52 52 PointerType *pointer = safe_dynamic_cast< PointerType* >( funcExpr->get_result() ); 53 53 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); -
src/SynTree/Expression.cc
rb3d413b r8135d4c 31 31 #include "TypeSubstitution.h" // for TypeSubstitution 32 32 33 #include "GenPoly/Lvalue.h" 33 34 34 35 Expression::Expression( Expression *_aname ) : result( 0 ), env( 0 ), argName( _aname ) {} … … 89 90 } 90 91 92 VariableExpr * VariableExpr::functionPointer( FunctionDecl * func ) { 93 VariableExpr * funcExpr = new VariableExpr( func ); 94 funcExpr->set_result( new PointerType( Type::Qualifiers(), funcExpr->get_result() ) ); 95 return funcExpr; 96 } 97 91 98 void VariableExpr::print( std::ostream &os, int indent ) const { 92 99 os << "Variable Expression: "; … … 149 156 150 157 void AlignofExpr::print( std::ostream &os, int indent) const { 151 os << std::string( indent, ' ' ) <<"Alignof Expression on: ";158 os << "Alignof Expression on: "; 152 159 153 160 if (isType) … … 258 265 259 266 void AttrExpr::print( std::ostream &os, int indent) const { 260 os << std::string( indent, ' ' ) <<"Attr ";267 os << "Attr "; 261 268 attr->print( os, indent + 2 ); 262 269 if ( isType || expr ) { … … 357 364 namespace { 358 365 TypeSubstitution makeSub( Type * t ) { 359 if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) { 366 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( t ) ) { 367 return makeSub( refType->get_base() ); 368 } else if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) { 360 369 return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() ); 361 370 } else if ( UnionInstType * aggInst = dynamic_cast< UnionInstType * >( t ) ) { … … 422 431 if ( Type * type = expr->get_result() ) { 423 432 Type * base = InitTweak::getPointerBase( type ); 424 if ( ! base ) { 425 std::cerr << type << std::endl; 433 assertf( base, "expected pointer type in dereference (type was %s)", toString( type ).c_str() ); 434 ret->set_result( base->clone() ); 435 if ( GenPoly::referencesPermissable() ) { 436 // if references are still allowed in the AST, dereference returns a reference 437 ret->set_result( new ReferenceType( Type::Qualifiers(), ret->get_result() ) ); 438 } else { 439 // references have been removed, in which case dereference returns an lvalue of the base type. 440 ret->get_result()->set_lvalue( true ); 426 441 } 427 assertf( base, "expected pointer type in dereference\n" );428 ret->set_result( maybeClone( base ) );429 442 } 430 443 return ret; … … 490 503 491 504 void LogicalExpr::print( std::ostream &os, int indent )const { 492 os << std::string( indent, ' ' ) <<"Short-circuited operation (" << (isAnd?"and":"or") << ") on: ";505 os << "Short-circuited operation (" << (isAnd?"and":"or") << ") on: "; 493 506 arg1->print(os); 494 507 os << " and "; … … 595 608 CompoundLiteralExpr::CompoundLiteralExpr( Type * type, Initializer * initializer ) : initializer( initializer ) { 596 609 assert( type && initializer ); 610 type->set_lvalue( true ); 597 611 set_result( type ); 598 612 } -
src/SynTree/Expression.h
rb3d413b r8135d4c 284 284 void set_var( DeclarationWithType * newValue ) { var = newValue; } 285 285 286 static VariableExpr * functionPointer( FunctionDecl * decl ); 287 286 288 virtual VariableExpr * clone() const { return new VariableExpr( * this ); } 287 289 virtual void accept( Visitor & v ) { v.visit( this ); } -
src/SynTree/Mutator.cc
rb3d413b r8135d4c 484 484 } 485 485 486 Type *Mutator::mutate( ReferenceType *refType ) { 487 mutateAll( refType->get_forall(), *this ); 488 refType->set_base( maybeMutate( refType->get_base(), *this ) ); 489 return refType; 490 } 491 486 492 Type *Mutator::mutate( FunctionType *functionType ) { 487 493 mutateAll( functionType->get_forall(), *this ); -
src/SynTree/Mutator.h
rb3d413b r8135d4c 92 92 virtual Type* mutate( PointerType *pointerType ); 93 93 virtual Type* mutate( ArrayType *arrayType ); 94 virtual Type* mutate( ReferenceType *refType ); 94 95 virtual Type* mutate( FunctionType *functionType ); 95 96 virtual Type* mutate( StructInstType *aggregateUseType ); -
src/SynTree/SynTree.h
rb3d413b r8135d4c 101 101 class PointerType; 102 102 class ArrayType; 103 class ReferenceType; 103 104 class FunctionType; 104 105 class ReferenceToType; -
src/SynTree/TupleExpr.cc
rb3d413b r8135d4c 67 67 assertf( type->size() > index, "TupleIndexExpr index out of bounds: tuple size %d, requested index %d in expr %s", type->size(), index, toString( tuple ).c_str() ); 68 68 set_result( (*std::next( type->get_types().begin(), index ))->clone() ); 69 get_result()->set_lvalue( type->get_lvalue() ); 69 // like MemberExpr, TupleIndexExpr is always an lvalue 70 get_result()->set_lvalue( true ); 70 71 } 71 72 -
src/SynTree/Type.cc
rb3d413b r8135d4c 64 64 const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" }; 65 65 66 Type * Type::stripDeclarator() {66 Type * Type::stripDeclarator() { 67 67 Type * type = this; 68 68 while ( Type * at = InitTweak::getPointerBase( type ) ) { … … 71 71 return type; 72 72 } 73 74 Type * Type::stripReferences() { 75 Type * type = this; 76 while ( ReferenceType * ref = dynamic_cast<ReferenceType *>( type ) ) { 77 type = ref->get_base(); 78 } 79 return type; 80 } 81 82 int Type::referenceDepth() const { return 0; } 73 83 74 84 void Type::print( std::ostream &os, int indent ) const { -
src/SynTree/Type.h
rb3d413b r8135d4c 168 168 169 169 /// return type without outer pointers and arrays 170 Type *stripDeclarator(); 170 Type * stripDeclarator(); 171 172 /// return type without outer references 173 Type * stripReferences(); 174 175 /// return the number of references occuring consecutively on the outermost layer of this type (i.e. do not count references nested within other types) 176 virtual int referenceDepth() const; 171 177 172 178 virtual bool isComplete() const { return true; } … … 262 268 bool is_array() const { return isStatic || isVarLen || dimension; } 263 269 270 virtual bool isComplete() const { return ! isVarLen; } 271 264 272 virtual PointerType *clone() const { return new PointerType( *this ); } 265 273 virtual void accept( Visitor & v ) { v.visit( this ); } … … 296 304 }; 297 305 306 class ReferenceType : public Type { 307 public: 308 Type *base; 309 310 ReferenceType( const Type::Qualifiers & tq, Type *base, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 311 ReferenceType( const ReferenceType & ); 312 virtual ~ReferenceType(); 313 314 Type *get_base() { return base; } 315 void set_base( Type *newValue ) { base = newValue; } 316 317 virtual int referenceDepth() const; 318 319 // Since reference types act like value types, their size is the size of the base. 320 // This makes it simple to cast the empty tuple to a reference type, since casts that increase 321 // the number of values are disallowed. 322 virtual unsigned size() const { return base->size(); } 323 324 virtual ReferenceType *clone() const { return new ReferenceType( *this ); } 325 virtual void accept( Visitor & v ) { v.visit( this ); } 326 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); } 327 virtual void print( std::ostream & os, int indent = 0 ) const; 328 }; 329 298 330 class FunctionType : public Type { 299 331 public: -
src/SynTree/TypeExpr.cc
rb3d413b r8135d4c 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // TypeExpr.cc -- 7 // TypeExpr.cc -- 8 8 // 9 9 // Author : Richard C. Bilson -
src/SynTree/TypeSubstitution.h
rb3d413b r8135d4c 117 117 } // if 118 118 } else { 119 throw SemanticError( "Attempt to provide non-type parameter for type parameter", formal );119 throw SemanticError( toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ), formal ); 120 120 } // if 121 121 } else { -
src/SynTree/Visitor.cc
rb3d413b r8135d4c 373 373 void Visitor::visit( PointerType *pointerType ) { 374 374 acceptAll( pointerType->get_forall(), *this ); 375 // xxx - should PointerType visit/mutate dimension? 375 376 maybeAccept( pointerType->get_base(), *this ); 376 377 } … … 380 381 maybeAccept( arrayType->get_dimension(), *this ); 381 382 maybeAccept( arrayType->get_base(), *this ); 383 }