Changes in / [54cd58b:9236060]
- Location:
- src
- Files:
-
- 1 added
- 120 edited
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/CodeGenerator.cc
r54cd58b r9236060 182 182 genCommaList( aggDecl->get_parameters().begin(), aggDecl->get_parameters().end() ); 183 183 output << ")" << endl; 184 output << indent; 184 185 } 185 186 … … 321 322 void CodeGenerator::visit( __attribute__((unused)) ConstructorInit * init ){ 322 323 assertf( ! genC, "ConstructorInit nodes should not reach code generation." ); 323 // xxx - generate something reasonable for constructor/destructor pairs 324 output << "<ctorinit>"; 324 // pseudo-output for constructor/destructor pairs 325 output << "<ctorinit>{" << std::endl << ++indent << "ctor: "; 326 maybeAccept( init->get_ctor(), *this ); 327 output << ", " << std::endl << indent << "dtor: "; 328 maybeAccept( init->get_dtor(), *this ); 329 output << std::endl << --indent << "}"; 325 330 } 326 331 … … 336 341 if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( varExpr->get_var()->get_name(), opInfo ) ) { 337 342 std::list< Expression* >::iterator arg = applicationExpr->get_args().begin(); 338 switch ( opInfo.type ) {339 case OT_PREFIXASSIGN:340 case OT_POSTFIXASSIGN:341 case OT_INFIXASSIGN:342 case OT_CTOR:343 case OT_DTOR:344 {345 assert( arg != applicationExpr->get_args().end() );346 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) {347 // remove & from first assignment/ctor argument348 *arg = addrExpr->get_arg();349 } else {350 // no address-of operator, so must be a pointer - add dereference351 // NOTE: if the assertion starts to trigger, check that the application expr isn't being shared.352 // Since its arguments are modified here, this assertion most commonly triggers when the application353 // is visited multiple times.354 UntypedExpr * newExpr = new UntypedExpr( new NameExpr( "*?" ) );355 newExpr->get_args().push_back( *arg );356 Type * type = InitTweak::getPointerBase( (*arg)->get_result() );357 assertf( type, "First argument to a derefence must be a pointer. Ensure that expressions are not being shared." );358 newExpr->set_result( type->clone() );359 *arg = newExpr;360 } // if361 break;362 }363 364 default:365 // do nothing366 ;367 } // switch368 369 343 switch ( opInfo.type ) { 370 344 case OT_INDEX: … … 695 669 extension( commaExpr ); 696 670 output << "("; 671 if ( genC ) { 672 // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings. 673 commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) ); 674 } 697 675 commaExpr->get_arg1()->accept( *this ); 698 676 output << " , "; … … 758 736 for ( Statement * stmt : stmts ) { 759 737 output << lineDirective( stmt ) << indent; 760 738 output << printLabels( stmt->get_labels() ); 761 739 if ( i+1 == numStmts ) { 762 740 // last statement in a statement expression needs to be handled specially - … … 803 781 void CodeGenerator::visit( ExprStmt * exprStmt ) { 804 782 assert( exprStmt ); 805 Expression * expr = exprStmt->get_expr();806 783 if ( genC ) { 807 784 // cast the top-level expression to void to reduce gcc warnings. 808 expr = new CastExpr( expr);809 } 810 expr ->accept( *this );785 exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) ); 786 } 787 exprStmt->get_expr()->accept( *this ); 811 788 output << ";"; 812 789 } -
src/CodeGen/CodeGenerator.h
r54cd58b r9236060 19 19 #include <ostream> // for ostream, operator<< 20 20 #include <string> // for string 21 22 #include "Common/Indenter.h" // for Indenter 21 23 22 24 #include "SynTree/Declaration.h" // for DeclarationWithType (ptr only), Fun... -
src/CodeGen/GenType.cc
r54cd58b r9236060 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 ); … … 147 148 } 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 ); 156 } 157 149 158 void GenType::visit( FunctionType *funcType ) { 150 159 std::ostringstream os; -
src/CodeGen/OperatorTable.cc
r54cd58b r9236060 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
r54cd58b r9236060 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
r54cd58b r9236060 114 114 virtual void visit( PointerType *pointerType ) override final; 115 115 virtual void visit( ArrayType *arrayType ) override final; 116 virtual void visit( ReferenceType *referenceType ) override final; 116 117 virtual void visit( FunctionType *functionType ) override final; 117 118 virtual void visit( StructInstType *aggregateUseType ) override final; … … 200 201 virtual Type* mutate( PointerType *pointerType ) override final; 201 202 virtual Type* mutate( ArrayType *arrayType ) override final; 203 virtual Type* mutate( ReferenceType *referenceType ) override final; 202 204 virtual Type* mutate( FunctionType *functionType ) override final; 203 205 virtual Type* mutate( StructInstType *aggregateUseType ) override final; -
src/Common/PassVisitor.impl.h
r54cd58b r9236060 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
r54cd58b r9236060 309 309 template< typename T1, typename T2 > 310 310 struct group_iterate_t { 311 group_iterate_t( const T1 & v1, const T2 & v2 ) : args(v1, v2) {312 assertf( v1.size() == v2.size(), "group iteration requires containers of the same size.");311 group_iterate_t( bool skipBoundsCheck, const T1 & v1, const T2 & v2 ) : args(v1, v2) { 312 assertf(skipBoundsCheck || v1.size() == v2.size(), "group iteration requires containers of the same size: <%lu, %lu>.", v1.size(), v2.size()); 313 313 }; 314 314 … … 335 335 }; 336 336 337 /// performs bounds check to ensure that all arguments are of the same length. 337 338 template< typename... Args > 338 339 group_iterate_t<Args...> group_iterate( Args &&... args ) { 339 return group_iterate_t<Args...>(std::forward<Args>( args )...); 340 return group_iterate_t<Args...>(false, std::forward<Args>( args )...); 341 } 342 343 /// does not perform a bounds check - requires user to ensure that iteration terminates when appropriate. 344 template< typename... Args > 345 group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) { 346 return group_iterate_t<Args...>(true, std::forward<Args>( args )...); 340 347 } 341 348 -
src/Concurrency/Keywords.cc
r54cd58b r9236060 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
r54cd58b r9236060 56 56 #include "Common/UniqueName.h" 57 57 #include "Common/utility.h" 58 59 #include "CodeGen/OperatorTable.h" 58 60 59 61 #include "InitTweak/InitTweak.h" … … 570 572 // To compound the issue, the right side can be *x, etc. because of lvalue-returning functions 571 573 if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) { 572 if ( InitTweak::isAssignment( InitTweak::getFunctionName( assign ) ) ) {574 if ( CodeGen::isAssignment( InitTweak::getFunctionName( assign ) ) ) { 573 575 assert( assign->get_args().size() == 2 ); 574 576 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) { … … 610 612 } 611 613 } else { 612 throw SemanticError( "Cannot pass non-struct type for generic struct ");614 throw SemanticError( "Cannot pass non-struct type for generic struct: ", argBaseType ); 613 615 } 614 616 } … … 1025 1027 } // if 1026 1028 if ( baseType1 || baseType2 ) { 1029 delete ret->get_result(); 1027 1030 ret->set_result( appExpr->get_result()->clone() ); 1028 1031 if ( appExpr->get_env() ) { … … 1038 1041 assert( ! appExpr->get_args().empty() ); 1039 1042 if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) { 1043 // remove dereference from polymorphic types since they are boxed. 1040 1044 Expression *ret = appExpr->get_args().front(); 1045 // fix expr type to remove pointer 1041 1046 delete ret->get_result(); 1042 1047 ret->set_result( appExpr->get_result()->clone() ); … … 1128 1133 1129 1134 assert( appExpr->get_function()->has_result() ); 1130 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );1131 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );1135 FunctionType * function = getFunctionType( appExpr->get_function()->get_result() ); 1136 assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->get_function()->get_result() ).c_str() ); 1132 1137 1133 1138 if ( Expression *newExpr = handleIntrinsics( appExpr ) ) { … … 1206 1211 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) { 1207 1212 assert( appExpr->get_function()->has_result() ); 1208 PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );1209 FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base());1213 FunctionType *function = getFunctionType( appExpr->get_function()->get_result() ); 1214 assert( function ); 1210 1215 needs = needsAdapter( function, scopeTyVars ); 1211 1216 } // if … … 1216 1221 // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward 1217 1222 // out of the if condition. 1223 addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) ); 1224 // ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment 1218 1225 bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env ); 1219 addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );1220 1226 if ( polytype || needs ) { 1221 1227 Expression *ret = addrExpr->get_arg(); … … 1284 1290 if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) { 1285 1291 std::string adapterName = makeAdapterName( mangleName ); 1286 paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0 ) ); 1292 // adapter may not be used in body, pass along with unused attribute. 1293 paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0, { new Attribute( "unused" ) } ) ); 1287 1294 adaptersDone.insert( adaptersDone.begin(), mangleName ); 1288 1295 } … … 1390 1397 std::list< DeclarationWithType *>::iterator last = funcType->get_parameters().begin(); 1391 1398 std::list< DeclarationWithType *> inferredParams; 1392 ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 ); 1399 // size/align/offset parameters may not be used in body, pass along with unused attribute. 1400 ObjectDecl newObj( "", Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, 1401 { new Attribute( "unused" ) } ); 1393 1402 ObjectDecl newPtr( "", Type::StorageClasses(), LinkageSpec::C, 0, 1394 1403 new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 ); … … 1413 1422 for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) { 1414 1423 // *assert = (*assert)->acceptMutator( *this ); 1424 // assertion parameters may not be used in body, pass along with unused attribute. 1425 (*assert)->get_attributes().push_back( new Attribute( "unused" ) ); 1415 1426 inferredParams.push_back( *assert ); 1416 1427 } -
src/GenPoly/Lvalue.cc
r54cd58b r9236060 27 27 #include "SynTree/Mutator.h" 28 28 #include "SymTab/Indexer.h" 29 #include "SymTab/Autogen.h" 29 30 30 31 #include "ResolvExpr/Resolver.h" … … 35 36 #include "Common/UniqueName.h" 36 37 #include "Common/utility.h" 38 #include "Common/PassVisitor.h" 39 40 #include "InitTweak/InitTweak.h" 41 42 #if 0 43 #define PRINT(x) x 44 #else 45 #define PRINT(x) 46 #endif 37 47 38 48 namespace GenPoly { 39 49 namespace { 40 /// Replace uses of lvalue returns with appropriate pointers 41 class Pass1 : public Mutator { 42 public: 43 Pass1(); 44 45 virtual Expression *mutate( ApplicationExpr *appExpr ); 46 virtual Statement *mutate( ReturnStmt *appExpr ); 47 virtual DeclarationWithType *mutate( FunctionDecl *funDecl ); 48 private: 49 DeclarationWithType* retval; 50 }; 51 52 /// Replace declarations of lvalue returns with appropriate pointers 53 class Pass2 : public Visitor { 54 public: 55 virtual void visit( FunctionType *funType ); 56 private: 50 // TODO: fold this into the general createDeref function?? 51 Expression * mkDeref( Expression * arg ) { 52 if ( SymTab::dereferenceOperator ) { 53 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator ); 54 deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) ); 55 Type * base = InitTweak::getPointerBase( arg->get_result() ); 56 assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() ); 57 ApplicationExpr * ret = new ApplicationExpr( deref, { arg } ); 58 delete ret->get_result(); 59 ret->set_result( base->clone() ); 60 ret->get_result()->set_lvalue( true ); 61 return ret; 62 } else { 63 return UntypedExpr::createDeref( arg ); 64 } 65 } 66 67 struct ReferenceConversions final { 68 Expression * postmutate( CastExpr * castExpr ); 69 Expression * postmutate( AddressExpr * addrExpr ); 70 }; 71 72 /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced. 73 struct FixIntrinsicArgs final { 74 Expression * postmutate( ApplicationExpr * appExpr ); 75 }; 76 77 struct FixIntrinsicResult final { 78 Expression * postmutate( ApplicationExpr * appExpr ); 79 }; 80 81 /// Replace reference types with pointer types 82 struct ReferenceTypeElimination final { 83 Type * postmutate( ReferenceType * refType ); 57 84 }; 58 85 … … 60 87 /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues 61 88 /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c) 62 class GeneralizedLvalue : public Mutator { 63 typedef Mutator Parent; 64 65 virtual Expression * mutate( MemberExpr * memExpr ); 66 virtual Expression * mutate( AddressExpr * addressExpr ); 89 struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> { 90 Expression * postmutate( AddressExpr * addressExpr ); 91 Expression * postmutate( MemberExpr * memExpr ); 67 92 68 93 template<typename Func> 69 94 Expression * applyTransformation( Expression * expr, Expression * arg, Func mkExpr ); 70 95 }; 96 97 /// Removes redundant &*/*& pattern that this pass can generate 98 struct CollapseAddrDeref final { 99 Expression * postmutate( AddressExpr * addressExpr ); 100 Expression * postmutate( ApplicationExpr * appExpr ); 101 }; 102 103 struct AddrRef final : public WithGuards { 104 void premutate( AddressExpr * addrExpr ); 105 Expression * postmutate( AddressExpr * addrExpr ); 106 void premutate( Expression * expr ); 107 108 bool first = true; 109 bool current = false; 110 int refDepth = 0; 111 }; 71 112 } // namespace 72 113 114 static bool referencesEliminated = false; 115 // used by UntypedExpr::createDeref to determine whether result type of dereference should be ReferenceType or value type. 116 bool referencesPermissable() { 117 return ! referencesEliminated; 118 } 119 73 120 void convertLvalue( std::list< Declaration* >& translationUnit ) { 74 Pass1 p1; 75 Pass2 p2; 76 GeneralizedLvalue genLval; 77 mutateAll( translationUnit, p1 ); 78 acceptAll( translationUnit, p2 ); 121 std::cerr << "convertLvalue" << std::endl; 122 PassVisitor<ReferenceConversions> refCvt; 123 PassVisitor<ReferenceTypeElimination> elim; 124 PassVisitor<GeneralizedLvalue> genLval; 125 PassVisitor<FixIntrinsicArgs> fixer; 126 PassVisitor<CollapseAddrDeref> collapser; 127 PassVisitor<AddrRef> addrRef; 128 PassVisitor<FixIntrinsicResult> intrinsicResults; 129 mutateAll( translationUnit, intrinsicResults ); 130 mutateAll( translationUnit, addrRef ); 131 mutateAll( translationUnit, refCvt ); 132 mutateAll( translationUnit, fixer ); 133 mutateAll( translationUnit, collapser ); 79 134 mutateAll( translationUnit, genLval ); 135 mutateAll( translationUnit, elim ); // last because other passes need reference types to work 136 137 // from this point forward, no other pass should create reference types. 138 referencesEliminated = true; 80 139 } 81 140 82 141 Expression * generalizedLvalue( Expression * expr ) { 83 GeneralizedLvaluegenLval;142 PassVisitor<GeneralizedLvalue> genLval; 84 143 return expr->acceptMutator( genLval ); 85 144 } 86 145 87 146 namespace { 88 Type* isLvalueRet( FunctionType *function ) { 89 if ( function->get_returnVals().empty() ) return 0; 90 Type *ty = function->get_returnVals().front()->get_type(); 91 return ty->get_lvalue() ? ty : 0; 92 } 93 94 bool isIntrinsicApp( ApplicationExpr *appExpr ) { 95 if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) { 96 return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic; 97 } else { 98 return false; 99 } // if 100 } 101 102 Pass1::Pass1() { 103 } 104 105 DeclarationWithType * Pass1::mutate( FunctionDecl *funcDecl ) { 106 if ( funcDecl->get_statements() ) { 107 DeclarationWithType* oldRetval = retval; 108 retval = 0; 109 if ( ! LinkageSpec::isBuiltin( funcDecl->get_linkage() ) && isLvalueRet( funcDecl->get_functionType() ) ) { 110 retval = funcDecl->get_functionType()->get_returnVals().front(); 111 } 112 // fix expressions and return statements in this function 113 funcDecl->set_statements( funcDecl->get_statements()->acceptMutator( *this ) ); 114 retval = oldRetval; 115 } // if 116 return funcDecl; 117 } 118 119 Expression * Pass1::mutate( ApplicationExpr *appExpr ) { 120 appExpr->get_function()->acceptMutator( *this ); 121 mutateAll( appExpr->get_args(), *this ); 122 123 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 124 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 125 126 Type *funType = isLvalueRet( function ); 127 if ( funType && ! isIntrinsicApp( appExpr ) ) { 128 Expression *expr = appExpr; 129 Type *appType = appExpr->get_result(); 130 if ( isPolyType( funType ) && ! isPolyType( appType ) ) { 131 // make sure cast for polymorphic type is inside dereference 132 expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) ); 133 } 134 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 135 deref->set_result( appType->clone() ); 136 appExpr->set_result( new PointerType( Type::Qualifiers(), appType ) ); 137 deref->get_args().push_back( expr ); 138 return deref; 139 } else { 140 return appExpr; 141 } // if 142 } 143 144 Statement * Pass1::mutate(ReturnStmt *retStmt) { 145 if ( retval && retStmt->get_expr() ) { 146 if ( retStmt->get_expr()->get_result()->get_lvalue() ) { 147 // ***** Code Removal ***** because casts may be stripped already 148 149 // strip casts because not allowed to take address of cast 150 // while ( CastExpr *castExpr = dynamic_cast< CastExpr* >( retStmt->get_expr() ) ) { 151 // retStmt->set_expr( castExpr->get_arg() ); 152 // retStmt->get_expr()->set_env( castExpr->get_env() ); 153 // castExpr->set_env( 0 ); 154 // castExpr->set_arg( 0 ); 155 // delete castExpr; 156 // } // while 157 retStmt->set_expr( new AddressExpr( retStmt->get_expr()->acceptMutator( *this ) ) ); 147 // true for intrinsic function calls that return a reference 148 bool isIntrinsicReference( Expression * expr ) { 149 if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) { 150 std::string fname = InitTweak::getFunctionName( untyped ); 151 // known intrinsic-reference prelude functions 152 return fname == "*?" || fname == "?[?]"; 153 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 154 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) { 155 // use type of return variable rather than expr result type, since it may have been changed to a pointer type 156 FunctionType * ftype = GenPoly::getFunctionType( func->get_type() ); 157 Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type(); 158 return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret ); 159 } 160 } 161 return false; 162 } 163 164 Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) { 165 if ( isIntrinsicReference( appExpr ) ) { 166 // eliminate reference types from intrinsic applications - now they return lvalues 167 Type * result = appExpr->get_result(); 168 appExpr->set_result( result->stripReferences()->clone() ); 169 appExpr->get_result()->set_lvalue( true ); 170 Expression * ret = new CastExpr( appExpr, result ); 171 ret->set_env( appExpr->get_env() ); 172 appExpr->set_env( nullptr ); 173 return ret; 174 } 175 return appExpr; 176 } 177 178 Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) { 179 // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments. 180 if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) { 181 FunctionType * ftype = GenPoly::getFunctionType( function->get_type() ); 182 assertf( ftype, "Function declaration does not have function type." ); 183 // can be of differing lengths only when function is variadic 184 assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." ); 185 186 187 unsigned int i = 0; 188 const unsigned int end = ftype->get_parameters().size(); 189 for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) { 190 if (i == end) break; 191 Expression *& arg = std::get<0>( p ); 192 Type * formal = std::get<1>( p )->get_type(); 193 PRINT( 194 std::cerr << "pair<0>: " << arg << std::endl; 195 std::cerr << "pair<1>: " << formal << std::endl; 196 ) 197 if ( dynamic_cast<ReferenceType*>( formal ) ) { 198 if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if 199 if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references 200 // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument 201 PRINT( 202 std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl; 203 ) 204 arg = new AddressExpr( arg ); 205 } 206 } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) { 207 // std::cerr << "===adding deref to arg" << std::endl; 208 // if the parameter is a reference, add a dereference to the reference-typed argument. 209 Type * baseType = InitTweak::getPointerBase( arg->get_result() ); 210 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() ); 211 PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() ); 212 delete arg->get_result(); 213 arg->set_result( ptrType ); 214 arg = mkDeref( arg ); 215 } 216 } 217 ++i; 218 } 219 } 220 return appExpr; 221 } 222 223 // idea: &&&E: get outer &, inner & 224 // at inner &, record depth D of reference type 225 // at outer &, add D derefs. 226 void AddrRef::premutate( Expression * expr ) { 227 GuardValue( current ); 228 GuardValue( first ); 229 current = false; 230 first = true; 231 } 232 233 void AddrRef::premutate( AddressExpr * addrExpr ) { 234 GuardValue( current ); 235 GuardValue( first ); 236 current = first; 237 first = false; 238 if ( current ) { 239 GuardValue( refDepth ); 240 refDepth = 0; 241 } 242 } 243 244 Expression * AddrRef::postmutate( AddressExpr * addrExpr ) { 245 if ( refDepth == 0 ) { 246 if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) { 247 // try to avoid ?[?] 248 refDepth = addrExpr->get_arg()->get_result()->referenceDepth(); 249 } 250 } 251 if ( current ) { 252 Expression * ret = addrExpr; 253 while ( refDepth ) { 254 ret = mkDeref( ret ); 255 refDepth--; 256 } 257 return ret; 258 } 259 return addrExpr; 260 } 261 262 Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) { 263 // Inner expression may have been lvalue to reference conversion, which becomes an address expression. 264 // In this case, remove the outer address expression and return the argument. 265 // TODO: It's possible that this might catch too much and require a more sophisticated check. 266 return addrExpr; 267 } 268 269 Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) { 270 // xxx - is it possible to convert directly between reference types with a different base? E.g., 271 // int x; 272 // (double&)x; 273 // At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant 274 // after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct 275 // pointer casts in the right places. 276 277 // conversion to reference type 278 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) { 279 (void)refType; 280 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) { 281 // nothing to do if casting from reference to reference. 282 (void)otherRef; 283 PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; ) 284 if ( isIntrinsicReference( castExpr->get_arg() ) ) { 285 Expression * callExpr = castExpr->get_arg(); 286 PRINT( 287 std::cerr << "but arg is deref -- &" << std::endl; 288 std::cerr << callExpr << std::endl; 289 ) 290 callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts 291 delete callExpr->get_result(); 292 callExpr->set_result( refType->clone() ); 293 // move environment out to new top-level 294 callExpr->set_env( castExpr->get_env() ); 295 castExpr->set_arg( nullptr ); 296 castExpr->set_env( nullptr ); 297 delete castExpr; 298 return callExpr; 299 } 300 int depth1 = refType->referenceDepth(); 301 int depth2 = otherRef->referenceDepth(); 302 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 303 PRINT( std::cerr << castExpr << std::endl; ) 304 return castExpr; 305 } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) { 306 // conversion from lvalue to reference 307 // xxx - keep cast, but turn into pointer cast?? 308 // xxx - memory 309 PRINT( 310 std::cerr << "convert lvalue to reference -- &" << std::endl; 311 std::cerr << castExpr->get_arg() << std::endl; 312 ) 313 AddressExpr * ret = new AddressExpr( castExpr->get_arg() ); 314 if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) { 315 // must keep cast if cast-to type is different from the actual type 316 castExpr->set_arg( ret ); 317 return castExpr; 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; 158 327 } else { 159 throw SemanticError( "Attempt to return non-lvalue from an lvalue-qualified function" ); 160 } // if 161 } // if 162 return retStmt; 163 } 164 165 void Pass2::visit( FunctionType *funType ) { 166 std::string typeName; 167 if ( isLvalueRet( funType ) ) { 168 DeclarationWithType *retParm = funType->get_returnVals().front(); 169 170 // make a new parameter that is a pointer to the type of the old return value 171 retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) ); 172 } // if 173 174 Visitor::visit( funType ); 328 // rvalue to reference conversion -- introduce temporary 329 } 330 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() ); 331 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) { 332 (void)refType; 333 // conversion from reference to rvalue 334 PRINT( 335 std::cerr << "convert reference to rvalue -- *" << std::endl; 336 std::cerr << "was = " << castExpr << std::endl; 337 ) 338 Expression * ret = castExpr->get_arg(); 339 TypeSubstitution * env = castExpr->get_env(); 340 castExpr->set_env( nullptr ); 341 if ( ! isIntrinsicReference( ret ) ) { 342 // dereference if not already dereferenced 343 ret = mkDeref( ret ); 344 } 345 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) { 346 // can remove cast if types are compatible, changing expression type to value type 347 ret->set_result( castExpr->get_result()->clone() ); 348 castExpr->set_arg( nullptr ); 349 delete castExpr; 350 } else { 351 // must keep cast if types are different 352 castExpr->set_arg( ret ); 353 ret = castExpr; 354 } 355 ret->set_env( env ); 356 PRINT( std::cerr << "now: " << ret << std::endl; ) 357 return ret; 358 } 359 return castExpr; 360 } 361 362 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) { 363 Type * base = refType->get_base(); 364 Type::Qualifiers qualifiers = refType->get_qualifiers(); 365 refType->set_base( nullptr ); 366 delete refType; 367 return new PointerType( qualifiers, base ); 175 368 } 176 369 … … 180 373 Expression * arg1 = commaExpr->get_arg1()->clone(); 181 374 Expression * arg2 = commaExpr->get_arg2()->clone(); 182 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 ) );375 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) ); 183 376 ret->set_env( expr->get_env() ); 184 377 expr->set_env( nullptr ); 185 378 delete expr; 186 return ret ->acceptMutator( *this );379 return ret; 187 380 } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) { 188 381 Expression * arg1 = condExpr->get_arg1()->clone(); 189 382 Expression * arg2 = condExpr->get_arg2()->clone(); 190 383 Expression * arg3 = condExpr->get_arg3()->clone(); 191 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 ) , mkExpr( arg3) );384 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) ); 192 385 ret->set_env( expr->get_env() ); 193 386 expr->set_env( nullptr ); … … 202 395 unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType ); 203 396 ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() ); 204 return ret ->acceptMutator( *this );397 return ret; 205 398 } 206 399 return expr; 207 400 } 208 401 209 Expression * GeneralizedLvalue::mutate( MemberExpr * memExpr ) { 210 Parent::mutate( memExpr ); 402 Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) { 211 403 return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } ); 212 404 } 213 405 214 Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) { 215 addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) ); 406 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) { 216 407 return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } ); 408 } 409 410 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) { 411 Expression * arg = addrExpr->get_arg(); 412 if ( isIntrinsicReference( arg ) ) { 413 std::string fname = InitTweak::getFunctionName( arg ); 414 if ( fname == "*?" ) { 415 Expression *& arg0 = InitTweak::getCallArg( arg, 0 ); 416 Expression * ret = arg0; 417 ret->set_env( addrExpr->get_env() ); 418 arg0 = nullptr; 419 addrExpr->set_env( nullptr ); 420 delete addrExpr; 421 return ret; 422 } 423 } 424 return addrExpr; 425 } 426 427 Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) { 428 if ( isIntrinsicReference( appExpr ) ) { 429 std::string fname = InitTweak::getFunctionName( appExpr ); 430 if ( fname == "*?" ) { 431 Expression * arg = InitTweak::getCallArg( appExpr, 0 ); 432 // xxx - this isn't right, because it can remove casts that should be there... 433 // while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) { 434 // arg = castExpr->get_arg(); 435 // } 436 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) { 437 Expression * ret = addrExpr->get_arg(); 438 ret->set_env( appExpr->get_env() ); 439 addrExpr->set_arg( nullptr ); 440 appExpr->set_env( nullptr ); 441 delete appExpr; 442 return ret; 443 } 444 } 445 } 446 return appExpr; 217 447 } 218 448 } // namespace -
src/GenPoly/Lvalue.h
r54cd58b r9236060 24 24 void convertLvalue( std::list< Declaration* >& translationUnit ); 25 25 26 /// true after reference types have been eliminated from the source code. After this point, reference types should not be added to the AST. 27 bool referencesPermissable(); 28 26 29 /// applies transformations that allow GCC to accept more complicated lvalue expressions, e.g. &(a, b) 27 30 Expression * generalizedLvalue( Expression * expr ); -
src/GenPoly/Specialize.cc
r54cd58b r9236060 101 101 // conversion of 0 (null) to function type does not require tuple specialization 102 102 if ( dynamic_cast< ZeroType * >( actualType ) ) return false; 103 FunctionType * aftype = getFunctionType( actualType );104 assertf( aftype, "formal type is a function type, but actual type is not .");103 FunctionType * aftype = getFunctionType( actualType->stripReferences() ); 104 assertf( aftype, "formal type is a function type, but actual type is not: %s", toString( actualType ).c_str() ); 105 105 if ( fftype->get_parameters().size() != aftype->get_parameters().size() ) return true; 106 106 for ( auto params : group_iterate( fftype->get_parameters(), aftype->get_parameters() ) ) { -
src/InitTweak/FixInit.cc
r54cd58b r9236060 26 26 #include "FixGlobalInit.h" 27 27 #include "CodeGen/GenType.h" // for warning/error messages 28 #include "CodeGen/OperatorTable.h" 28 29 #include "Common/PassVisitor.h" 29 30 #include "GenPoly/DeclMutator.h" … … 238 239 SemanticError errors; 239 240 private: 240 void handleFirstParam( Expression * firstParam );241 241 template< typename... Params > 242 242 void emit( CodeLocation, const Params &... params ); … … 363 363 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 364 364 assert( ftype ); 365 if ( isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {366 Type * t1 = ftype->get_parameters().front()->get_type();365 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) { 366 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); 367 367 Type * t2 = ftype->get_parameters().back()->get_type(); 368 PointerType * ptrType = safe_dynamic_cast< PointerType * >( t1 );369 370 if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {368 assert( t1 ); 369 370 if ( ResolvExpr::typesCompatible( t1, t2, SymTab::Indexer() ) ) { 371 371 // optimization: don't need to copy construct in order to call a copy constructor 372 372 return appExpr; 373 373 } // if 374 } else if ( isDestructor( funcDecl->get_name() ) ) {374 } else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) { 375 375 // correctness: never copy construct arguments to a destructor 376 376 return appExpr; … … 401 401 402 402 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { 403 return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );403 return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type ); 404 404 } 405 405 … … 489 489 impCpCtorExpr->get_returnDecls().push_back( ret ); 490 490 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 491 if ( ! result->get_lvalue() ) {491 if ( ! dynamic_cast< ReferenceType * >( result ) ) { 492 492 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 493 493 destructRet( ret, impCpCtorExpr ); … … 975 975 if ( ! funcDecl ) return false; 976 976 if ( ! funcDecl->get_statements() ) return false; 977 return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );977 return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() ); 978 978 } 979 979 … … 992 992 993 993 function = funcDecl; 994 isCtor = isConstructor( function->get_name() );994 isCtor = CodeGen::isConstructor( function->get_name() ); 995 995 if ( checkWarnings( function ) ) { 996 996 FunctionType * type = function->get_functionType(); 997 997 assert( ! type->get_parameters().empty() ); 998 998 thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() ); 999 PointerType * ptrType = safe_dynamic_cast< PointerType * >( thisParam->get_type() );1000 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base());999 Type * thisType = getPointerBase( thisParam->get_type() ); 1000 StructInstType * structType = dynamic_cast< StructInstType * >( thisType ); 1001 1001 if ( structType ) { 1002 1002 structDecl = structType->get_baseStruct(); … … 1031 1031 1032 1032 if ( ! unhandled.empty() ) { 1033 // need to explicitly re-add function parameters in order to resolve copy constructors1033 // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors 1034 1034 enterScope(); 1035 1035 maybeAccept( function->get_functionType(), *this ); … … 1046 1046 // insert and resolve default/copy constructor call for each field that's unhandled 1047 1047 std::list< Statement * > stmt; 1048 UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) );1049 1050 1048 Expression * arg2 = 0; 1051 1049 if ( isCopyConstructor( function ) ) { … … 1056 1054 } 1057 1055 InitExpander srcParam( arg2 ); 1058 SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor ); 1056 // cast away reference type and construct field. 1057 Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() ); 1058 Expression * memberDest = new MemberExpr( field, thisExpr ); 1059 SymTab::genImplicitCall( srcParam, memberDest, function->get_name(), back_inserter( stmt ), field, isCtor ); 1059 1060 1060 1061 assert( stmt.size() <= 1 ); … … 1083 1084 } 1084 1085 1086 /// true if expr is effectively just the 'this' parameter 1087 bool isThisExpression( Expression * expr, DeclarationWithType * thisParam ) { 1088 // TODO: there are more complicated ways to pass 'this' to a constructor, e.g. &*, *&, etc. 1089 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 1090 return varExpr->get_var() == thisParam; 1091 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( expr ) ) { 1092 return isThisExpression( castExpr->get_arg(), thisParam ); 1093 } 1094 return false; 1095 } 1096 1097 /// returns a MemberExpr if expr is effectively just member access on the 'this' parameter, else nullptr 1098 MemberExpr * isThisMemberExpr( Expression * expr, DeclarationWithType * thisParam ) { 1099 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) { 1100 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { 1101 return memberExpr; 1102 } 1103 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 1104 return isThisMemberExpr( castExpr->get_arg(), thisParam ); 1105 } 1106 return nullptr; 1107 } 1108 1085 1109 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) { 1086 1110 if ( ! checkWarnings( function ) ) return; … … 1091 1115 Expression * firstParam = appExpr->get_args().front(); 1092 1116 1093 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {1117 if ( isThisExpression( firstParam, thisParam ) ) { 1094 1118 // if calling another constructor on thisParam, assume that function handles 1095 1119 // all members - if it doesn't a warning will appear in that function. 1096 if ( varExpr->get_var() == thisParam ) { 1097 unhandled.clear(); 1098 } 1099 } else { 1100 // if first parameter is a member expression then 1101 // remove the member from unhandled set. 1102 handleFirstParam( firstParam ); 1103 } 1104 } 1105 1106 Parent::visit( appExpr ); 1107 } 1108 1109 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) { 1110 using namespace std; 1111 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) { 1112 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) { 1113 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 1114 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 1115 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 1116 if ( varExpr->get_var() == thisParam ) { 1117 unhandled.erase( memberExpr->get_member() ); 1118 } 1119 } 1120 } 1120 unhandled.clear(); 1121 } else if ( MemberExpr * memberExpr = isThisMemberExpr( firstParam, thisParam ) ) { 1122 // if first parameter is a member expression on the this parameter, 1123 // then remove the member from unhandled set. 1124 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { 1125 unhandled.erase( memberExpr->get_member() ); 1121 1126 } 1122 1127 } 1123 1128 } 1129 Parent::visit( appExpr ); 1124 1130 } 1125 1131 … … 1128 1134 if ( ! isCtor ) return; 1129 1135 1130 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 1131 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 1132 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 1133 if ( varExpr->get_var() == 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 } ); 1137 } 1138 } 1139 } 1136 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { 1137 if ( unhandled.count( memberExpr->get_member() ) ) { 1138 // emit a warning because a member was used before it was constructed 1139 usedUninit.insert( { memberExpr->get_member(), memberExpr->location } ); 1140 1140 } 1141 1141 } … … 1183 1183 ctorExpr->set_callExpr( nullptr ); 1184 1184 ctorExpr->set_env( nullptr ); 1185 delete ctorExpr; 1185 1186 1186 1187 Expression *& firstArg = callExpr->get_args().front(); 1187 UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) ); 1188 assign->get_args().push_back( new VariableExpr( tmp ) ); 1189 assign->get_args().push_back( firstArg ); 1190 assign->set_result( ctorExpr->get_result()->clone() ); 1191 firstArg = assign; 1192 1193 CommaExpr * commaExpr = new CommaExpr( callExpr, new VariableExpr( tmp ) ); 1188 1189 // 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. 1190 1191 // generate the type of assignment operator using the type of tmp minus any reference types 1192 Type * type = tmp->get_type()->stripReferences(); 1193 FunctionType * ftype = SymTab::genAssignType( type ); 1194 1195 // generate fake assignment decl and call it using &tmp and &firstArg 1196 // since tmp is guaranteed to be a reference and we want to assign pointers 1197 FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr ); 1198 ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) ); 1199 assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) ); 1200 Expression * addrArg = new AddressExpr( firstArg ); 1201 // if firstArg has type T&&, then &firstArg has type T*&. 1202 // Cast away the reference to a value type so that the argument 1203 // matches the assignment's parameter types 1204 if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) { 1205 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() ); 1206 } 1207 assign->get_args().push_back( addrArg ); 1208 firstArg = new VariableExpr( tmp ); 1209 1210 // for constructor expr: 1211 // T x; 1212 // x{}; 1213 // results in: 1214 // T x; 1215 // T & tmp; 1216 // &tmp = &x, ?{}(tmp), tmp 1217 CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) ); 1194 1218 commaExpr->set_env( env ); 1195 delete ctorExpr;1196 1219 return commaExpr; 1197 1220 } -
src/InitTweak/GenInit.cc
r54cd58b r9236060 21 21 22 22 #include "Common/PassVisitor.h" 23 #include "CodeGen/OperatorTable.h" 23 24 24 25 #include "GenPoly/DeclMutator.h" … … 54 55 55 56 protected: 56 FunctionType * ftype ;57 FunctionType * ftype = nullptr; 57 58 std::string funcName; 58 59 }; … … 137 138 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals(); 138 139 assert( returnVals.size() == 0 || returnVals.size() == 1 ); 139 // hands off if the function returns a n lvalue - we don't want to allocate a temporary if a variable's address140 // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address 140 141 // is being returned 141 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! returnVals.front()->get_type()->get_lvalue() ) {142 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) { 142 143 // explicitly construct the return value using the return expression and the retVal object 143 144 assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() ); 144 UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) ); 145 construct->get_args().push_back( new AddressExpr( new VariableExpr( returnVals.front() ) ) ); 146 construct->get_args().push_back( returnStmt->get_expr() ); 147 stmtsToAddBefore.push_back(new ExprStmt(noLabels, construct)); 145 146 stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) ); 148 147 149 148 // return the retVal object … … 212 211 213 212 bool CtorDtor::isManaged( Type * type ) const { 213 // at least for now, references are never constructed 214 if ( dynamic_cast< ReferenceType * >( type ) ) return false; 214 215 // need to clear and reset qualifiers when determining if a type is managed 215 216 ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() ); … … 235 236 void CtorDtor::handleDWT( DeclarationWithType * dwt ) { 236 237 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 237 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && isCtorDtor( dwt->get_name() ) ) {238 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) { 238 239 std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters(); 239 240 assert( ! params.empty() ); 240 PointerType * type = safe_dynamic_cast< PointerType * >( params.front()->get_type() ); 241 managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) ); 241 Type * type = InitTweak::getPointerBase( params.front()->get_type() ); 242 assert( type ); 243 managedTypes.insert( SymTab::Mangler::mangle( type ) ); 242 244 } 243 245 } -
src/InitTweak/InitTweak.cc
r54cd58b r9236060 170 170 171 171 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) ); 172 increment->get_args().push_back( new AddressExpr( index->clone()) );172 increment->get_args().push_back( index->clone() ); 173 173 *out++ = new ExprStmt( noLabels, increment ); 174 174 } … … 380 380 template<typename CallExpr> 381 381 Expression *& callArg( CallExpr * callExpr, unsigned int pos ) { 382 if ( pos >= callExpr->get_args().size() ) assertf( false, " asking for argument that doesn't exist. Return NULL/throw exception?");382 if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() ); 383 383 for ( Expression *& arg : callExpr->get_args() ) { 384 384 if ( pos == 0 ) return arg; … … 458 458 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 459 459 return arrayType->get_base(); 460 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) { 461 return refType->get_base(); 460 462 } else { 461 463 return NULL; … … 543 545 if ( ftype->get_parameters().size() != 2 ) return 0; 544 546 545 Type * t1 = ftype->get_parameters().front()->get_type();547 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); 546 548 Type * t2 = ftype->get_parameters().back()->get_type(); 547 PointerType * ptrType = dynamic_cast< PointerType * > ( t1 ); 548 assert( ptrType ); 549 550 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( ptrType->get_base(), t2, SymTab::Indexer() ) ) { 549 assert( t1 ); 550 551 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) { 551 552 return function; 552 553 } else { -
src/InitTweak/InitTweak.h
r54cd58b r9236060 25 25 // helper functions for initialization 26 26 namespace InitTweak { 27 bool isConstructor( const std::string & );28 bool isDestructor( const std::string & );29 bool isAssignment( const std::string & );30 bool isCtorDtor( const std::string & );31 bool isCtorDtorAssign( const std::string & );32 33 27 FunctionDecl * isAssignment( Declaration * decl ); 34 28 FunctionDecl * isDestructor( Declaration * decl ); -
src/Makefile.in
r54cd58b r9236060 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
r54cd58b r9236060 345 345 } // DeclarationNode::newTypeDecl 346 346 347 DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers ) {348 DeclarationNode * newnode = new DeclarationNode; 349 newnode->type = new TypeData( TypeData::Pointer);347 DeclarationNode * DeclarationNode::newPointer( DeclarationNode * qualifiers, OperKinds kind ) { 348 DeclarationNode * newnode = new DeclarationNode; 349 newnode->type = new TypeData( kind == OperKinds::PointTo ? TypeData::Pointer : TypeData::Reference ); 350 350 if ( qualifiers ) { 351 351 return newnode->addQualifiers( qualifiers ); … … 764 764 DeclarationNode * DeclarationNode::addPointer( DeclarationNode * p ) { 765 765 if ( p ) { 766 assert( p->type->kind == TypeData::Pointer );766 assert( p->type->kind == TypeData::Pointer || TypeData::Reference ); 767 767 setBase( p->type ); 768 768 p->type = nullptr; … … 786 786 DeclarationNode * DeclarationNode::addNewPointer( DeclarationNode * p ) { 787 787 if ( p ) { 788 assert( p->type->kind == TypeData::Pointer );788 assert( p->type->kind == TypeData::Pointer || p->type->kind == TypeData::Reference ); 789 789 if ( type ) { 790 790 switch ( type->kind ) { -
src/Parser/ExpressionNode.cc
r54cd58b r9236060 305 305 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) { 306 306 std::list< Expression * > args; 307 args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node) ) );307 args.push_back( maybeMoveBuild< Expression >(expr_node) ); // xxx 308 308 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); 309 309 } // build_unary_ptr … … 318 318 Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) { 319 319 std::list< Expression * > args; 320 args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node1)) );320 args.push_back( maybeMoveBuild< Expression >(expr_node1) ); 321 321 args.push_back( maybeMoveBuild< Expression >(expr_node2) ); 322 322 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); -
src/Parser/ParseNode.h
r54cd58b r9236060 237 237 static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params ); 238 238 static DeclarationNode * newTypeDecl( std::string * name, DeclarationNode * typeParams ); 239 static DeclarationNode * newPointer( DeclarationNode * qualifiers );239 static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind ); 240 240 static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic ); 241 241 static DeclarationNode * newVarArray( DeclarationNode * qualifiers ); -
src/Parser/TypeData.cc
r54cd58b r9236060 30 30 case Unknown: 31 31 case Pointer: 32 case Reference: 32 33 case EnumConstant: 33 34 // nothing else to initialize … … 101 102 case Unknown: 102 103 case Pointer: 104 case Reference: 103 105 case EnumConstant: 104 106 // nothing to destroy … … 168 170 case EnumConstant: 169 171 case Pointer: 172 case Reference: 170 173 // nothing else to copy 171 174 break; … … 403 406 // add dtor: void ^?{}(T *) 404 407 FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false ); 405 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 ) );408 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 ) ); 406 409 td->get_assertions().push_front( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, dtorType, nullptr ) ); 407 410 408 411 // add copy ctor: void ?{}(T *, T) 409 412 FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false ); 410 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 ) );413 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 ) ); 411 414 copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 412 415 td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, copyCtorType, nullptr ) ); … … 414 417 // add default ctor: void ?{}(T *) 415 418 FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false ); 416 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 ) );419 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 ) ); 417 420 td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, ctorType, nullptr ) ); 418 421 419 422 // add assignment operator: T * ?=?(T *, T) 420 423 FunctionType * assignType = new FunctionType( Type::Qualifiers(), false ); 421 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 ) );424 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 ) ); 422 425 assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 423 426 assignType->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); … … 439 442 case TypeData::Array: 440 443 return buildArray( td ); 444 case TypeData::Reference: 445 return buildReference( td ); 441 446 case TypeData::Function: 442 447 return buildFunction( td ); … … 617 622 buildForall( td->forall, at->get_forall() ); 618 623 return at; 619 } // buildPointer 624 } // buildArray 625 626 ReferenceType * buildReference( const TypeData * td ) { 627 ReferenceType * rt; 628 if ( td->base ) { 629 rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) ); 630 } else { 631 rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 632 } // if 633 buildForall( td->forall, rt->get_forall() ); 634 return rt; 635 } // buildReference 620 636 621 637 AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) { -
src/Parser/TypeData.h
r54cd58b r9236060 20 20 21 21 struct TypeData { 22 enum Kind { Basic, Pointer, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,22 enum Kind { Basic, Pointer, Array, Reference, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic, 23 23 SymbolicInst, Tuple, Typeof, Builtin, Unknown }; 24 24 … … 103 103 PointerType * buildPointer( const TypeData * ); 104 104 ArrayType * buildArray( const TypeData * ); 105 ReferenceType * buildReference( const TypeData * ); 105 106 AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > ); 106 107 ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ); -
src/Parser/lex.ll
r54cd58b r9236060 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
r54cd58b r9236060 118 118 %token RESTRICT // C99 119 119 %token ATOMIC // C11 120 %token FORALL LVALUEMUTEX VIRTUAL // CFA120 %token FORALL MUTEX VIRTUAL // CFA 121 121 %token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED 122 122 %token BOOL COMPLEX IMAGINARY // C99 … … 668 668 conditional_expression 669 669 | unary_expression assignment_operator assignment_expression 670 { $$ = new ExpressionNode( build_binary_ ptr( $2, $1, $3 ) ); }670 { $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); } 671 671 ; 672 672 … … 1425 1425 | VOLATILE 1426 1426 { $$ = DeclarationNode::newTypeQualifier( Type::Volatile ); } 1427 | LVALUE // CFA1428 { $$ = DeclarationNode::newTypeQualifier( Type::Lvalue ); }1429 1427 | MUTEX 1430 1428 { $$ = DeclarationNode::newTypeQualifier( Type::Mutex ); } … … 2407 2405 variable_ptr: 2408 2406 ptrref_operator variable_declarator 2409 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2407 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2410 2408 | ptrref_operator type_qualifier_list variable_declarator 2411 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2409 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2412 2410 | '(' variable_ptr ')' attribute_list_opt 2413 2411 { $$ = $2->addQualifiers( $4 ); } // redundant parenthesis … … 2455 2453 function_ptr: 2456 2454 ptrref_operator function_declarator 2457 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2455 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2458 2456 | ptrref_operator type_qualifier_list function_declarator 2459 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2457 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2460 2458 | '(' function_ptr ')' 2461 2459 { $$ = $2; } … … 2495 2493 KR_function_ptr: 2496 2494 ptrref_operator KR_function_declarator 2497 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2495 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2498 2496 | ptrref_operator type_qualifier_list KR_function_declarator 2499 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2497 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2500 2498 | '(' KR_function_ptr ')' 2501 2499 { $$ = $2; } … … 2539 2537 type_ptr: 2540 2538 ptrref_operator variable_type_redeclarator 2541 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2539 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2542 2540 | ptrref_operator type_qualifier_list variable_type_redeclarator 2543 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2541 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2544 2542 | '(' type_ptr ')' attribute_list_opt 2545 2543 { $$ = $2->addQualifiers( $4 ); } … … 2583 2581 identifier_parameter_ptr: 2584 2582 ptrref_operator identifier_parameter_declarator 2585 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2583 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2586 2584 | ptrref_operator type_qualifier_list identifier_parameter_declarator 2587 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2585 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2588 2586 | '(' identifier_parameter_ptr ')' attribute_list_opt 2589 2587 { $$ = $2->addQualifiers( $4 ); } … … 2643 2641 type_parameter_ptr: 2644 2642 ptrref_operator type_parameter_redeclarator 2645 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2643 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2646 2644 | ptrref_operator type_qualifier_list type_parameter_redeclarator 2647 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2645 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2648 2646 | '(' type_parameter_ptr ')' attribute_list_opt 2649 2647 { $$ = $2->addQualifiers( $4 ); } … … 2686 2684 abstract_ptr: 2687 2685 ptrref_operator 2688 { $$ = DeclarationNode::newPointer( 0 ); }2686 { $$ = DeclarationNode::newPointer( 0, $1 ); } 2689 2687 | ptrref_operator type_qualifier_list 2690 { $$ = DeclarationNode::newPointer( $2 ); }2688 { $$ = DeclarationNode::newPointer( $2, $1 ); } 2691 2689 | ptrref_operator abstract_declarator 2692 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2690 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2693 2691 | ptrref_operator type_qualifier_list abstract_declarator 2694 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2692 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2695 2693 | '(' abstract_ptr ')' attribute_list_opt 2696 2694 { $$ = $2->addQualifiers( $4 ); } … … 2775 2773 abstract_parameter_ptr: 2776 2774 ptrref_operator 2777 { $$ = DeclarationNode::newPointer( nullptr ); }2775 { $$ = DeclarationNode::newPointer( nullptr, $1 ); } 2778 2776 | ptrref_operator type_qualifier_list 2779 { $$ = DeclarationNode::newPointer( $2 ); }2777 { $$ = DeclarationNode::newPointer( $2, $1 ); } 2780 2778 | ptrref_operator abstract_parameter_declarator 2781 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr ) ); }2779 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 2782 2780 | ptrref_operator type_qualifier_list abstract_parameter_declarator 2783 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2781 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2784 2782 | '(' abstract_parameter_ptr ')' attribute_list_opt 2785 2783 { $$ = $2->addQualifiers( $4 ); } … … 2854 2852 variable_abstract_ptr: 2855 2853 ptrref_operator 2856 { $$ = DeclarationNode::newPointer( 0 ); }2854 { $$ = DeclarationNode::newPointer( 0, $1 ); } 2857 2855 | ptrref_operator type_qualifier_list 2858 { $$ = DeclarationNode::newPointer( $2 ); }2856 { $$ = DeclarationNode::newPointer( $2, $1 ); } 2859 2857 | ptrref_operator variable_abstract_declarator 2860 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2858 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2861 2859 | ptrref_operator type_qualifier_list variable_abstract_declarator 2862 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }2860 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 2863 2861 | '(' variable_abstract_ptr ')' attribute_list_opt 2864 2862 { $$ = $2->addQualifiers( $4 ); } … … 2900 2898 // No SUE declaration in parameter list. 2901 2899 ptrref_operator type_specifier_nobody 2902 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2900 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2903 2901 | type_qualifier_list ptrref_operator type_specifier_nobody 2904 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2902 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 2905 2903 | ptrref_operator cfa_abstract_function 2906 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2904 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2907 2905 | type_qualifier_list ptrref_operator cfa_abstract_function 2908 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2906 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 2909 2907 | ptrref_operator cfa_identifier_parameter_declarator_tuple 2910 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2908 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2911 2909 | type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple 2912 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2910 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 2913 2911 ; 2914 2912 … … 2988 2986 cfa_abstract_ptr: // CFA 2989 2987 ptrref_operator type_specifier 2990 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2988 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2991 2989 | type_qualifier_list ptrref_operator type_specifier 2992 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2990 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 2993 2991 | ptrref_operator cfa_abstract_function 2994 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2992 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2995 2993 | type_qualifier_list ptrref_operator cfa_abstract_function 2996 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2994 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 2997 2995 | ptrref_operator cfa_abstract_declarator_tuple 2998 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2996 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); } 2999 2997 | type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple 3000 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2998 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); } 3001 2999 ; 3002 3000 -
src/ResolvExpr/Alternative.cc
r54cd58b r9236060 28 28 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {} 29 29 30 Alternative::Alternative( const Alternative &other ) { 31 initialize( other, *this ); 30 Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) { 32 31 } 33 32 34 33 Alternative &Alternative::operator=( const Alternative &other ) { 35 34 if ( &other == this ) return *this; 36 initialize( other, *this ); 35 delete expr; 36 cost = other.cost; 37 cvtCost = other.cvtCost; 38 expr = maybeClone( other.expr ); 39 env = other.env; 37 40 return *this; 38 41 } … … 51 54 other.expr = nullptr; 52 55 return *this; 53 }54 55 void Alternative::initialize( const Alternative &src, Alternative &dest ) {56 dest.cost = src.cost;57 dest.cvtCost = src.cvtCost;58 dest.expr = maybeClone( src.expr );59 dest.env = src.env;60 56 } 61 57 -
src/ResolvExpr/Alternative.h
r54cd58b r9236060 35 35 ~Alternative(); 36 36 37 void initialize( const Alternative &src, Alternative &dest );38 39 37 void print( std::ostream &os, int indent = 0 ) const; 40 38 -
src/ResolvExpr/AlternativeFinder.cc
r54cd58b r9236060 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 > … … 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 } … … 277 290 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 278 291 279 Cost convCost ( 0, 0, 0 );292 Cost convCost = Cost::zero; 280 293 std::list< DeclarationWithType* >& formals = function->get_parameters(); 281 294 std::list< DeclarationWithType* >::iterator formal = formals.begin(); … … 290 303 actualType->print( std::cerr, 8 ); 291 304 ) 292 Cost actualCost ;305 Cost actualCost = Cost::zero; 293 306 if ( formal == formals.end() ) { 294 307 if ( function->get_isVarArgs() ) { 295 convCost += Cost( 1, 0, 0 ); 308 convCost.incUnsafe(); 309 // convert reference-typed expressions to value-typed expressions 310 referenceToRvalueConversion( *actualExpr ); 296 311 continue; 297 312 } else { … … 305 320 std::cerr << std::endl << " to "; 306 321 formalType->print( std::cerr, 8 ); 322 std::cerr << std::endl << "environment is: "; 323 alt.env.print( std::cerr, 8 ); 324 std::cerr << std::endl; 307 325 ) 308 326 Cost newCost = conversionCost( actualType, formalType, indexer, alt.env ); … … 316 334 convCost += newCost; 317 335 actualCost += newCost; 318 if ( actualCost != Cost ( 0, 0, 0 )) {336 if ( actualCost != Cost::zero ) { 319 337 Type *newType = formalType->clone(); 320 338 alt.env.apply( newType ); 321 339 *actualExpr = new CastExpr( *actualExpr, newType ); 322 340 } 323 convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0);341 convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) ); 324 342 ++formal; // can't be in for-loop update because of the continue 325 343 } … … 343 361 } 344 362 convCost += newCost; 345 convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0);363 convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) ); 346 364 } 347 365 … … 400 418 Expression * actual = actualIt->expr; 401 419 Type * actualType = actual->get_result(); 420 402 421 PRINT( 403 422 std::cerr << "formal type is "; … … 408 427 ) 409 428 if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 429 // std::cerr << "unify failed" << std::endl; 410 430 return false; 411 431 } … … 452 472 // match flattened actuals with formal parameters - actuals will be grouped to match 453 473 // with formals as appropriate 454 Cost cost ;474 Cost cost = Cost::zero; 455 475 std::list< Expression * > newExprs; 456 476 ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal ); … … 643 663 makeExprList( instantiatedActuals, appExpr->get_args() ); 644 664 PRINT( 665 std::cerr << "instantiate function success: " << appExpr << std::endl; 645 666 std::cerr << "need assertions:" << std::endl; 646 667 printAssertionSet( resultNeed, std::cerr, 8 ); … … 663 684 UntypedExpr *vexpr = untypedExpr->clone(); 664 685 vexpr->set_result( pt.clone() ); 665 alternatives.push_back( Alternative( vexpr, env, Cost ()) );686 alternatives.push_back( Alternative( vexpr, env, Cost::zero) ); 666 687 return; 667 688 } … … 681 702 AltList candidates; 682 703 SemanticError errors; 683 for ( AltList:: const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {704 for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) { 684 705 try { 685 706 PRINT( … … 688 709 ) 689 710 // check if the type is pointer to function 690 PointerType *pointer; 691 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) { 711 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) { 692 712 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 713 referenceToRvalueConversion( func->expr ); 693 714 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 694 715 // XXX … … 696 717 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 697 718 } 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 719 } 720 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) 721 referenceToRvalueConversion( func->expr ); 722 EqvClass eqvClass; 723 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 724 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 725 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 726 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 727 } // for 706 728 } // if 707 729 } // if … … 722 744 } 723 745 724 for ( AltList:: const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {746 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) { 725 747 // check if the type is pointer to function 726 PointerType *pointer; 727 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) { 748 if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) { 728 749 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 750 referenceToRvalueConversion( funcOp->expr ); 729 751 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 730 752 AltList currentAlt; … … 753 775 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 754 776 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 755 std::cerr << "Case +++++++++++++ "<< std::endl;777 std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl; 756 778 std::cerr << "formals are:" << std::endl; 757 779 printAll( function->get_parameters(), std::cerr, 8 ); … … 796 818 bool isLvalue( Expression *expr ) { 797 819 // xxx - recurse into tuples? 798 return expr->has_result() && expr->get_result()->get_lvalue();820 return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) ); 799 821 } 800 822 … … 810 832 811 833 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). 834 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) { 835 // Argument expression is a tuple and the target type is not void and not a reference type. 836 // Cast each member of the tuple to its corresponding target type, producing the tuple of those 837 // cast expressions. If there are more components of the tuple than components in the target type, 838 // then excess components do not come out in the result expression (but UniqueExprs ensure that 839 // side effects will still be done). 817 840 if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) { 818 841 // expressions which may contain side effects require a single unique instance of the expression. … … 855 878 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 856 879 // to. 857 int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();880 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size(); 858 881 if ( discardedValues < 0 ) continue; 859 882 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 860 883 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 861 884 // 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 );885 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 886 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 864 887 if ( thisCost != Cost::infinity ) { 865 888 // count one safe conversion for each value that is thrown away 866 thisCost += Cost( 0, 0,discardedValues );889 thisCost.incSafe( discardedValues ); 867 890 868 891 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) ); … … 895 918 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); 896 919 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() ); 920 // 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 921 std::unique_ptr<Expression> aggrExpr( agg->expr->clone() ); 922 Type * aggrType = aggrExpr->get_result(); 923 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 924 aggrType = aggrType->stripReferences(); 925 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 926 } 927 // find member of the given type 928 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 929 addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 930 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 931 addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 932 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 933 addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 903 934 } // if 904 935 } // for … … 915 946 for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) { 916 947 VariableExpr newExpr( *i, nameExpr->get_argName() ); 917 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );948 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 918 949 PRINT( 919 950 std::cerr << "decl is "; … … 1059 1090 for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) { 1060 1091 VariableExpr newExpr( *i ); 1061 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );1092 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 1062 1093 renameTypes( alternatives.back().expr ); 1063 1094 } // for … … 1232 1263 if ( thisCost != Cost::infinity ) { 1233 1264 // count one safe conversion for each value that is thrown away 1234 thisCost += Cost( 0, 0,discardedValues );1265 thisCost.incSafe( discardedValues ); 1235 1266 candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) ); 1236 1267 } -
src/ResolvExpr/CastCost.cc
r54cd58b r9236060 46 46 assert( type ); 47 47 if ( type->get_base() ) { 48 return castCost( src, type->get_base(), indexer, env ) + Cost ( 0, 0, 1 );48 return castCost( src, type->get_base(), indexer, env ) + Cost::safe; 49 49 } // if 50 50 } // if 51 51 } // if 52 52 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) { 53 return Cost ( 0, 0, 0 );53 return Cost::zero; 54 54 } else if ( dynamic_cast< VoidType* >( dest ) ) { 55 return Cost( 0, 0, 1 ); 55 return Cost::safe; 56 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 57 return convertToReferenceCost( src, refType, indexer, env ); 56 58 } else { 57 59 CastCost converter( dest, indexer, env ); … … 61 63 } else { 62 64 // xxx - why are we adding cost 0 here? 63 return converter.get_cost() + Cost ( 0, 0, 0 );65 return converter.get_cost() + Cost::zero; 64 66 } // if 65 67 } // if … … 74 76 if ( destAsPointer && basicType->isInteger() ) { 75 77 // necessary for, e.g. unsigned long => void* 76 cost = Cost ( 1, 0, 0 );78 cost = Cost::unsafe; 77 79 } else { 78 ConversionCost::visit( basicType);80 cost = conversionCost( basicType, dest, indexer, env ); 79 81 } // if 80 82 } … … 83 85 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 84 86 if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 85 cost = Cost ( 0, 0, 1 );87 cost = Cost::safe; 86 88 } else { 87 89 TypeEnvironment newEnv( env ); … … 90 92 int castResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer ); 91 93 if ( castResult > 0 ) { 92 cost = Cost ( 0, 0, 1 );94 cost = Cost::safe; 93 95 } else if ( castResult < 0 ) { 94 96 cost = Cost::infinity; … … 98 100 if ( destAsBasic->isInteger() ) { 99 101 // necessary for, e.g. void* => unsigned long 100 cost = Cost ( 1, 0, 0 );102 cost = Cost::unsafe; 101 103 } // if 102 104 } -
src/ResolvExpr/CommonType.cc
r54cd58b r9236060 17 17 #include "SynTree/Type.h" 18 18 #include "Unify.h" 19 20 19 21 20 /// #define DEBUG … … 31 30 virtual void visit( PointerType *pointerType ); 32 31 virtual void visit( ArrayType *arrayType ); 32 virtual void visit( ReferenceType *refType ); 33 33 virtual void visit( FunctionType *functionType ); 34 34 virtual void visit( StructInstType *aggregateUseType ); … … 42 42 virtual void visit( OneType *oneType ); 43 43 44 void getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ); 44 template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ); 45 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 45 46 46 47 Type *result; … … 52 53 }; 53 54 55 Type * handleReference( ReferenceType * refType, Type * other, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) { 56 Type * result = nullptr, * common = nullptr; 57 AssertionSet have, need; 58 OpenVarSet newOpen( openVars ); 59 // need unify to bind type variables 60 if ( unify( refType->get_base(), other, env, have, need, newOpen, indexer, common ) ) { 61 // std::cerr << "unify success" << std::endl; 62 if ( widenSecond ) { 63 if ( widenFirst || other->get_qualifiers() <= refType->get_qualifiers() ) { 64 result = new ReferenceType( refType->get_qualifiers(), common ); // refType->clone(); 65 result->get_qualifiers() |= other->get_qualifiers(); 66 } 67 } else if ( widenFirst ) { 68 if ( widenSecond || refType->get_qualifiers() <= other->get_qualifiers() ) { 69 result = common; 70 result->get_qualifiers() |= refType->get_qualifiers(); 71 } 72 } 73 } else { 74 // std::cerr << "exact unify failed: " << refType << " " << other << std::endl; 75 } 76 // std::cerr << "common type of reference [" << refType << "] and non-reference [" << other << "] is [" << result << "]" << std::endl; 77 return result; 78 } 79 54 80 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 55 81 CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 82 83 int depth1 = type1->referenceDepth(); 84 int depth2 = type2->referenceDepth(); 85 if ( depth1 > 0 || depth2 > 0 ) { 86 int diff = depth1-depth2; 87 // 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. 88 if ( diff > 1 || diff < -1 ) return nullptr; 89 90 // special case where one type has a reference depth of 1 larger than the other 91 if ( diff > 0 ) { 92 return handleReference( safe_dynamic_cast<ReferenceType *>( type1 ), type2, widenFirst, widenSecond, indexer, env, openVars ); 93 } else if ( diff < 0 ) { 94 return handleReference( safe_dynamic_cast<ReferenceType *>( type2 ), type1, widenSecond, widenFirst, indexer, env, openVars ); 95 } 96 // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor. 97 } 98 56 99 type1->accept( visitor ); 57 100 Type *result = visitor.get_result(); … … 142 185 } 143 186 144 void CommonType::getCommonWithVoidPointer( PointerType* voidPointer, PointerType* otherPointer ) { 187 template< typename Pointer > 188 void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) { 145 189 if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) { 146 190 OpenVarSet::const_iterator entry = openVars.find( var->get_name() ); … … 188 232 189 233 void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {} 234 235 void CommonType::visit( ReferenceType *refType ) { 236 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 237 if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) { 238 getCommonWithVoidPointer( otherRef, refType ); 239 } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) { 240 getCommonWithVoidPointer( refType, otherRef ); 241 } else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) 242 && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) { 243 Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers(); 244 refType->get_base()->get_qualifiers() = Type::Qualifiers(); 245 otherRef->get_base()->get_qualifiers() = Type::Qualifiers(); 246 AssertionSet have, need; 247 OpenVarSet newOpen( openVars ); 248 if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) { 249 if ( tq1 < tq2 ) { 250 result = refType->clone(); 251 } else { 252 result = otherRef->clone(); 253 } // if 254 result->get_qualifiers() = tq1 | tq2; 255 } else { 256 /// std::cout << "place for ptr-to-type" << std::endl; 257 } // if 258 refType->get_base()->get_qualifiers() = tq1; 259 otherRef->get_base()->get_qualifiers() = tq2; 260 } // if 261 } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) { 262 result = refType->clone(); 263 result->get_qualifiers() |= type2->get_qualifiers(); 264 } // if 265 } 266 190 267 void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {} 191 268 void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {} … … 195 272 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 196 273 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType 197 Type * temp = type2;274 ValueGuard< Type * > temp( type2 ); 198 275 type2 = enumInstType; 199 temp->accept( *this ); 200 type2 = temp; 276 temp.old->accept( *this ); 201 277 } // if 202 278 } -
src/ResolvExpr/ConversionCost.cc
r54cd58b r9236060 21 21 22 22 namespace ResolvExpr { 23 const Cost Cost::zero = Cost( 0, 0, 0 ); 24 const Cost Cost::infinity = Cost( -1, -1, -1 ); 23 const Cost Cost::zero = Cost( 0, 0, 0, 0 ); 24 const Cost Cost::infinity = Cost( -1, -1, -1, -1 ); 25 const Cost Cost::unsafe = Cost( 1, 0, 0, 0 ); 26 const Cost Cost::poly = Cost( 0, 1, 0, 0 ); 27 const Cost Cost::safe = Cost( 0, 0, 1, 0 ); 28 const Cost Cost::reference = Cost( 0, 0, 0, 1 ); 29 25 30 26 31 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { … … 41 46 assert( type ); 42 47 if ( type->get_base() ) { 43 return conversionCost( src, type->get_base(), indexer, env ) + Cost ( 0, 0, 1 );48 return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe; 44 49 } // if 45 50 } // if … … 54 59 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) { 55 60 /// std::cout << "compatible!" << std::endl; 56 return Cost ( 0, 0, 0 );61 return Cost::zero; 57 62 } else if ( dynamic_cast< VoidType* >( dest ) ) { 58 return Cost( 0, 0, 1 ); 63 return Cost::safe; 64 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 65 // std::cerr << "conversionCost: dest is reference" << std::endl; 66 return convertToReferenceCost( src, refType, indexer, env ); 59 67 } else { 60 68 ConversionCost converter( dest, indexer, env ); … … 63 71 return Cost::infinity; 64 72 } else { 65 return converter.get_cost() + Cost( 0, 0, 0 ); 66 } // if 67 } // if 73 return converter.get_cost() + Cost::zero; 74 } // if 75 } // if 76 } 77 78 Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 79 std::cerr << "convert to reference cost..." << std::endl; 80 if ( diff > 0 ) { 81 // TODO: document this 82 Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env ); 83 cost.incReference(); 84 return cost; 85 } else if ( diff < -1 ) { 86 // TODO: document this 87 Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env ); 88 cost.incReference(); 89 return cost; 90 } else if ( diff == 0 ) { 91 ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src ); 92 ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest ); 93 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 94 std::cerr << "converting between references" << std::endl; 95 if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) { 96 return Cost::safe; 97 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 98 int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env ); 99 if ( assignResult < 0 ) { 100 return Cost::safe; 101 } else if ( assignResult > 0 ) { 102 return Cost::unsafe; 103 } // if 104 } // if 105 } else { 106 std::cerr << "reference to rvalue conversion" << std::endl; 107 ConversionCost converter( dest, indexer, env ); 108 src->accept( converter ); 109 return converter.get_cost(); 110 } // if 111 } else { 112 ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest ); 113 assert( diff == -1 && destAsRef ); 114 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) { 115 std::cerr << "converting compatible base type" << std::endl; 116 if ( src->get_lvalue() ) { 117 std::cerr << "lvalue to reference conversion" << std::endl; 118 // lvalue-to-reference conversion: cv lvalue T => cv T & 119 if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) { 120 return Cost::reference; // cost needs to be non-zero to add cast 121 } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) { 122 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 123 } else { 124 return Cost::unsafe; 125 } // if 126 } else if ( destAsRef->get_base()->get_const() ) { 127 std::cerr << "rvalue to const ref conversion" << std::endl; 128 // rvalue-to-const-reference conversion: T => const T & 129 return Cost::safe; 130 } else { 131 // std::cerr << "rvalue to non-const reference conversion" << std::endl; 132 // rvalue-to-reference conversion: T => T & 133 return Cost::unsafe; 134 } // if 135 } // if 136 std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; 137 } 138 return Cost::infinity; 139 } 140 141 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 142 int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth(); 143 return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env ); 68 144 } 69 145 … … 157 233 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; 158 234 if ( tableResult == -1 ) { 159 cost = Cost( 1, 0, 0 ); 160 } else { 161 cost = Cost( 0, 0, tableResult ); 235 cost = Cost::unsafe; 236 } else { 237 cost = Cost::zero; 238 cost.incSafe( tableResult ); 162 239 } // if 163 240 } else if ( dynamic_cast< EnumInstType *>( dest ) ) { 164 241 // xxx - not positive this is correct, but appears to allow casting int => enum 165 cost = Cost ( 1, 0, 0 );242 cost = Cost::unsafe; 166 243 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) { 167 cost = Cost ( 1, 0, 0 );244 cost = Cost::unsafe; 168 245 } // if 169 246 } … … 171 248 void ConversionCost::visit(PointerType *pointerType) { 172 249 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 173 if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 174 cost = Cost( 0, 0, 1 ); 175 } else { 250 // std::cerr << pointerType << " ===> " << destAsPtr; 251 Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(); 252 Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers(); 253 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 254 if ( tq1 == tq2 ) { 255 // types are the same 256 cost = Cost::zero; 257 } else { 258 // types are the same, except otherPointer has more qualifiers 259 // std::cerr << " :: compatible and good qualifiers" << std::endl; 260 cost = Cost::safe; 261 } 262 } else { // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 176 263 int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env ); 177 if ( assignResult < 0 ) { 178 cost = Cost( 0, 0, 1 ); 264 // std::cerr << " :: " << assignResult << std::endl; 265 if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) { 266 cost = Cost::safe; 179 267 } else if ( assignResult > 0 ) { 180 cost = Cost ( 1, 0, 0 );268 cost = Cost::unsafe; 181 269 } // if 270 // assignResult == 0 means Cost::Infinity 182 271 } // if 183 272 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) { 184 cost = Cost ( 1, 0, 0 );273 cost = Cost::unsafe; 185 274 } // if 186 275 } 187 276 188 277 void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {} 278 279 void ConversionCost::visit(ReferenceType *refType) { 280 // Note: dest can never be a reference, since it would have been caught in an earlier check 281 assert( ! dynamic_cast< ReferenceType * >( dest ) ); 282 // convert reference to rvalue: cv T1 & => T2 283 // recursively compute conversion cost from T1 to T2. 284 // cv can be safely dropped because of 'implicit dereference' behavior. 285 refType->get_base()->accept( *this ); 286 if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) { 287 cost.incReference(); // prefer exact qualifiers 288 } else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) { 289 cost.incSafe(); // then gaining qualifiers 290 } else { 291 cost.incUnsafe(); // lose qualifiers as last resort 292 } 293 // std::cerr << refType << " ==> " << dest << " " << cost << std::endl; 294 } 295 189 296 void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {} 190 297 … … 208 315 static Type::Qualifiers q; 209 316 static BasicType integer( q, BasicType::SignedInt ); 210 integer.accept( *this ); 211 if ( cost < Cost ( 1, 0, 0 )) {317 integer.accept( *this ); // safe if dest >= int 318 if ( cost < Cost::unsafe ) { 212 319 cost.incSafe(); 213 320 } // if … … 231 338 assert( type ); 232 339 if ( type->get_base() ) { 233 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost ( 0, 0, 1 );340 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe; 234 341 } // if 235 342 } // if … … 237 344 238 345 void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) { 239 Cost c ;346 Cost c = Cost::zero; 240 347 if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) { 241 348 std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin(); … … 269 376 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ]; 270 377 if ( tableResult == -1 ) { 271 cost = Cost( 1, 0, 0 ); 272 } else { 273 cost = Cost( 0, 0, tableResult + 1 ); 378 cost = Cost::unsafe; 379 } else { 380 cost = Cost::zero; 381 cost.incSafe( tableResult + 1 ); 274 382 } 275 383 } else if ( dynamic_cast< PointerType* >( dest ) ) { 276 cost = Cost ( 0, 0, 1 );384 cost = Cost::safe; 277 385 } 278 386 } … … 285 393 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ]; 286 394 if ( tableResult == -1 ) { 287 cost = Cost( 1, 0, 0 ); 288 } else { 289 cost = Cost( 0, 0, tableResult + 1 ); 395 cost = Cost::unsafe; 396 } else { 397 cost = Cost::zero; 398 cost.incSafe( tableResult + 1 ); 290 399 } 291 400 } -
src/ResolvExpr/ConversionCost.h
r54cd58b r9236060 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ConversionCost.h -- 7 // ConversionCost.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 25 25 public: 26 26 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 27 27 28 28 Cost get_cost() const { return cost; } 29 29 … … 32 32 virtual void visit(PointerType *pointerType); 33 33 virtual void visit(ArrayType *arrayType); 34 virtual void visit(ReferenceType *refType); 34 35 virtual void visit(FunctionType *functionType); 35 36 virtual void visit(StructInstType *aggregateUseType); … … 48 49 const TypeEnvironment &env; 49 50 }; 51 52 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 50 53 } // namespace ResolvExpr 51 54 -
src/ResolvExpr/Cost.h
r54cd58b r9236060 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/Unify.cc
r54cd58b r9236060 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); … … 376 377 } // if 377 378 } else { 379 common = type1->clone(); 380 common->get_qualifiers() = tq1 | tq2; 378 381 result = true; 379 382 } // if … … 425 428 markAssertions( haveAssertions, needAssertions, pointerType ); 426 429 markAssertions( haveAssertions, needAssertions, otherPointer ); 430 } // if 431 } 432 433 void Unify::visit(ReferenceType *refType) { 434 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 435 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 436 markAssertions( haveAssertions, needAssertions, refType ); 437 markAssertions( haveAssertions, needAssertions, otherRef ); 427 438 } // if 428 439 } -
src/ResolvExpr/typeops.h
r54cd58b r9236060 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
r54cd58b r9236060 13 13 // Update Count : 62 14 14 // 15 15 16 #include "Autogen.h" 16 17 … … 23 24 24 25 #include "AddVisit.h" // for addVisit 26 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 25 27 #include "Common/ScopedMap.h" // for ScopedMap<>::const_iterator, Scope... 26 28 #include "Common/utility.h" // for cloneAll, operator+ … … 28 30 #include "GenPoly/ScopedSet.h" // for ScopedSet, ScopedSet<>::iterator 29 31 #include "SymTab/Mangler.h" // for Mangler 32 #include "SynTree/Attribute.h" // For Attribute 30 33 #include "SynTree/Mutator.h" // for maybeMutate 31 34 #include "SynTree/Statement.h" // for CompoundStmt, ReturnStmt, ExprStmt … … 131 134 FunctionType * genDefaultType( Type * paramType ) { 132 135 FunctionType *ftype = new FunctionType( Type::Qualifiers(), false ); 133 ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), paramType->clone() ), nullptr );136 ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr ); 134 137 ftype->get_parameters().push_back( dstParam ); 135 138 … … 182 185 FunctionType * ftype = funcDecl->get_functionType(); 183 186 assert( ! ftype->get_parameters().empty() ); 184 Type * t = safe_dynamic_cast< PointerType * >( ftype->get_parameters().front()->get_type() )->get_base(); 187 Type * t = InitTweak::getPointerBase( ftype->get_parameters().front()->get_type() ); 188 assert( t ); 185 189 map.insert( Mangler::mangleType( t ), true ); 186 190 } … … 228 232 FunctionType * ftype = data.genType( refType ); 229 233 230 if(concurrent_type && InitTweak::isDestructor( data.fname )) {234 if(concurrent_type && CodeGen::isDestructor( data.fname )) { 231 235 ftype->get_parameters().front()->get_type()->set_mutex( true ); 232 236 } … … 280 284 FunctionType *copyCtorType = genCopyType( refType->clone() ); 281 285 286 // add unused attribute to parameters of default constructor and destructor 287 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 288 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 289 282 290 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)? 283 291 // right now these cases work, but that might change. … … 303 311 /// generates a single struct member operation (constructor call, destructor call, assignment call) 304 312 void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) { 305 ObjectDecl * returnVal = NULL;306 if ( ! func->get_functionType()->get_returnVals().empty() ) {307 returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );308 }309 310 313 InitTweak::InitExpander srcParam( src ); 311 314 312 // assign to destination (and return value if generic) 313 UntypedExpr *derefExpr = UntypedExpr::createDeref( new VariableExpr( dstParam ) ); 314 Expression *dstselect = new MemberExpr( field, derefExpr ); 315 // assign to destination 316 Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), safe_dynamic_cast< ReferenceType* >( dstParam->get_type() )->get_base()->clone() ) ); 315 317 genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward ); 316 317 if ( isDynamicLayout && returnVal ) {318 // xxx - there used to be a dereference on returnVal, but this seems to have been wrong?319 Expression *retselect = new MemberExpr( field, new VariableExpr( returnVal ) );320 genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );321 } // if322 318 } 323 319 … … 424 420 425 421 // field ctors are only generated if default constructor and copy constructor are both generated 426 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return InitTweak::isConstructor( dcl->get_name() ); } );422 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } ); 427 423 428 424 if ( functionNesting == 0 ) { … … 439 435 // generate appropriate calls to member ctor, assignment 440 436 // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor 441 if ( ! InitTweak::isDestructor( dcl->get_name() ) ) {437 if ( ! CodeGen::isDestructor( dcl->get_name() ) ) { 442 438 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl, isDynamicLayout ); 443 439 } else { 444 440 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, isDynamicLayout, false ); 445 441 } 446 if ( InitTweak::isAssignment( dcl->get_name() ) ) {442 if ( CodeGen::isAssignment( dcl->get_name() ) ) { 447 443 // assignment needs to return a value 448 444 FunctionType * assignType = dcl->get_functionType(); … … 473 469 // our inheritance model. I think the correct way to handle this is to 474 470 // cast the structure to the type of the member and let the resolver 475 // figure out whether it's valid and have a pass afterwards that fixes 476 // the assignment to use pointer arithmetic with the offset of the 477 // member, much like how generic type members are handled. 471 // figure out whether it's valid/choose the correct unnamed member 478 472 continue; 479 473 } … … 491 485 void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) { 492 486 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) ); 493 copy->get_args().push_back( new VariableExpr( dstParam) );487 copy->get_args().push_back( new AddressExpr( new VariableExpr( dstParam ) ) ); 494 488 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) ); 495 489 copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) ); … … 503 497 ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() ); 504 498 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() ); 505 ObjectDecl * returnVal = nullptr;506 if ( ! ftype->get_returnVals().empty() ) {507 returnVal = safe_dynamic_cast< ObjectDecl * >( ftype->get_returnVals().front() );508 }509 499 510 500 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) ); 511 if ( returnVal ) { 501 if ( CodeGen::isAssignment( funcDecl->get_name() ) ) { 502 // also generate return statement in assignment 512 503 funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 513 504 } … … 536 527 cloneAll( typeParams, copyCtorType->get_forall() ); 537 528 cloneAll( typeParams, assignType->get_forall() ); 529 530 // add unused attribute to parameters of default constructor and destructor 531 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 532 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) ); 538 533 539 534 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units -
src/SymTab/Autogen.h
r54cd58b r9236060 43 43 extern Type * SizeType; 44 44 45 /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations. 46 /// Useful for creating dereference ApplicationExprs without a full resolver pass. 47 extern FunctionDecl * dereferenceOperator; 48 49 // temporary 50 FunctionType * genAssignType( Type * paramType ); 51 45 52 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 46 53 template< typename OutputIterator > … … 51 58 template< typename OutputIterator > 52 59 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) { 53 // want to be able to generate assignment, ctor, and dtor generically,54 // so fname is either ?=?, ?{}, or ^?{}55 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );60 // want to be able to generate assignment, ctor, and dtor generically, 61 // so fname is either ?=?, ?{}, or ^?{} 62 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) ); 56 63 57 // do something special for unnamed members 58 dstParam = new AddressExpr( dstParam ); 59 if ( addCast ) { 60 // cast to T* with qualifiers removed, so that qualified objects can be constructed 61 // and destructed with the same functions as non-qualified objects. 62 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument 63 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 64 // remove lvalue as a qualifier, this can change to 65 // type->get_qualifiers() = Type::Qualifiers(); 66 assert( type ); 67 Type * castType = type->clone(); 68 castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 69 castType->set_lvalue( true ); // xxx - might not need this 70 dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) ); 71 } 72 fExpr->get_args().push_back( dstParam ); 64 if ( addCast ) { 65 // cast to T& with qualifiers removed, so that qualified objects can be constructed 66 // and destructed with the same functions as non-qualified objects. 67 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument 68 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 69 // remove lvalue as a qualifier, this can change to 70 // type->get_qualifiers() = Type::Qualifiers(); 71 assert( type ); 72 Type * castType = type->clone(); 73 castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 74 // castType->set_lvalue( true ); // xxx - might not need this 75 dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) ); 76 } 77 fExpr->get_args().push_back( dstParam ); 73 78 74 Statement * listInit = srcParam.buildListInit( fExpr );79 Statement * listInit = srcParam.buildListInit( fExpr ); 75 80 76 std::list< Expression * > args = *++srcParam;77 fExpr->get_args().splice( fExpr->get_args().end(), args );81 std::list< Expression * > args = *++srcParam; 82 fExpr->get_args().splice( fExpr->get_args().end(), args ); 78 83 79 *out++ = new ExprStmt( noLabels, fExpr );84 *out++ = new ExprStmt( noLabels, fExpr ); 80 85 81 srcParam.clearArrayIndices();86 srcParam.clearArrayIndices(); 82 87 83 return listInit;88 return listInit; 84 89 } 85 90 … … 117 122 118 123 UntypedExpr *inc = new UntypedExpr( update ); 119 inc->get_args().push_back( new AddressExpr( new VariableExpr( index )) );124 inc->get_args().push_back( new VariableExpr( index ) ); 120 125 121 126 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) ); -
src/SymTab/Indexer.cc
r54cd58b r9236060 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
r54cd58b r9236060 131 131 mangleName << "A0"; 132 132 maybeAccept( arrayType->get_base(), *this ); 133 } 134 135 void Mangler::visit( ReferenceType *refType ) { 136 printQualifiers( refType ); 137 mangleName << "R"; 138 maybeAccept( refType->get_base(), *this ); 133 139 } 134 140 … … 302 308 // Removed due to restrict not affecting function compatibility in GCC 303 309 // if ( type->get_isRestrict() ) { 304 // mangleName << " R";310 // mangleName << "E"; 305 311 // } // if 306 312 if ( type->get_lvalue() ) { -
src/SymTab/Mangler.h
r54cd58b r9236060 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
r54cd58b r9236060 54 54 #include "Autogen.h" // for SizeType, autogenerateRoutines 55 55 #include "CodeGen/CodeGenerator.h" // for genName 56 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 56 57 #include "Common/PassVisitor.h" // for PassVisitor, WithDeclsToAdd 57 58 #include "Common/ScopedMap.h" // for ScopedMap<>::const_iterator … … 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
r54cd58b r9236060 18 18 #include "Common/utility.h" 19 19 20 // Address expressions are typed based on the following inference rules: 21 // E : lvalue T &..& (n references) 22 // &E : T *&..& (n references) 23 // 24 // E : T &..& (m references) 25 // &E : T *&..& (m-1 references) 26 // 27 // That is, lvalues becomes 28 29 namespace { 30 Type * addrType( Type * type ) { 31 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) { 32 return new ReferenceType( refType->get_qualifiers(), addrType( refType->get_base() ) ); 33 } else { 34 return new PointerType( Type::Qualifiers(), type->clone() ); 35 } 36 } 37 } 38 20 39 AddressExpr::AddressExpr( Expression *arg, Expression *_aname ) : Expression( _aname ), arg( arg ) { 21 40 if ( arg->has_result() ) { 22 set_result( new PointerType( Type::Qualifiers(), arg->get_result()->clone() ) ); 41 if ( arg->get_result()->get_lvalue() ) { 42 // lvalue, retains all layers of reference and gains a pointer inside the references 43 set_result( addrType( arg->get_result() ) ); 44 } else { 45 // taking address of non-lvalue -- must be a reference, loses one layer of reference 46 ReferenceType * refType = safe_dynamic_cast< ReferenceType * >( arg->get_result() ); 47 set_result( addrType( refType->get_base() ) ); 48 } 49 // result of & is never an lvalue 50 get_result()->set_lvalue( false ); 23 51 } 24 52 } -
src/SynTree/ApplicationExpr.cc
r54cd58b r9236060 44 44 } 45 45 46 ApplicationExpr::ApplicationExpr( Expression *funcExpr, const std::list< Expression * > & argList ) : function( funcExpr ), args( argList) {46 ApplicationExpr::ApplicationExpr( Expression *funcExpr, const std::list<Expression *> & args ) : function( funcExpr ), args( args ) { 47 47 PointerType *pointer = safe_dynamic_cast< PointerType* >( funcExpr->get_result() ); 48 48 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); -
src/SynTree/Expression.cc
r54cd58b r9236060 34 34 #include "InitTweak/InitTweak.h" 35 35 36 #include "GenPoly/Lvalue.h" 36 37 37 38 Expression::Expression( Expression *_aname ) : result( 0 ), env( 0 ), argName( _aname ) {} … … 92 93 } 93 94 95 VariableExpr * VariableExpr::functionPointer( FunctionDecl * func ) { 96 VariableExpr * funcExpr = new VariableExpr( func ); 97 funcExpr->set_result( new PointerType( Type::Qualifiers(), funcExpr->get_result() ) ); 98 return funcExpr; 99 } 100 94 101 void VariableExpr::print( std::ostream &os, int indent ) const { 95 102 os << "Variable Expression: "; … … 152 159 153 160 void AlignofExpr::print( std::ostream &os, int indent) const { 154 os << std::string( indent, ' ' ) <<"Alignof Expression on: ";161 os << "Alignof Expression on: "; 155 162 156 163 if (isType) … … 261 268 262 269 void AttrExpr::print( std::ostream &os, int indent) const { 263 os << std::string( indent, ' ' ) <<"Attr ";270 os << "Attr "; 264 271 attr->print( os, indent + 2 ); 265 272 if ( isType || expr ) { … … 360 367 namespace { 361 368 TypeSubstitution makeSub( Type * t ) { 362 if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) { 369 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( t ) ) { 370 return makeSub( refType->get_base() ); 371 } else if ( StructInstType * aggInst = dynamic_cast< StructInstType * >( t ) ) { 363 372 return TypeSubstitution( aggInst->get_baseParameters()->begin(), aggInst->get_baseParameters()->end(), aggInst->get_parameters().begin() ); 364 373 } else if ( UnionInstType * aggInst = dynamic_cast< UnionInstType * >( t ) ) { … … 425 434 if ( Type * type = expr->get_result() ) { 426 435 Type * base = InitTweak::getPointerBase( type ); 427 if ( ! base ) { 428 std::cerr << type << std::endl; 436 assertf( base, "expected pointer type in dereference (type was %s)", toString( type ).c_str() ); 437 ret->set_result( base->clone() ); 438 if ( GenPoly::referencesPermissable() ) { 439 // if references are still allowed in the AST, dereference returns a reference 440 ret->set_result( new ReferenceType( Type::Qualifiers(), ret->get_result() ) ); 441 } else { 442 // references have been removed, in which case dereference returns an lvalue of the base type. 443 ret->get_result()->set_lvalue( true ); 429 444 } 430 assertf( base, "expected pointer type in dereference\n" );431 ret->set_result( maybeClone( base ) );432 445 } 433 446 return ret; … … 493 506 494 507 void LogicalExpr::print( std::ostream &os, int indent )const { 495 os << std::string( indent, ' ' ) <<"Short-circuited operation (" << (isAnd?"and":"or") << ") on: ";508 os << "Short-circuited operation (" << (isAnd?"and":"or") << ") on: "; 496 509 arg1->print(os); 497 510 os << " and "; -
src/SynTree/Expression.h
r54cd58b r9236060 280 280 void set_var( DeclarationWithType * newValue ) { var = newValue; } 281 281 282 static VariableExpr * functionPointer( FunctionDecl * decl ); 283 282 284 virtual VariableExpr * clone() const { return new VariableExpr( * this ); } 283 285 virtual void accept( Visitor & v ) { v.visit( this ); } -
src/SynTree/Mutator.cc
r54cd58b r9236060 480 480 } 481 481 482 Type *Mutator::mutate( ReferenceType *refType ) { 483 mutateAll( refType->get_forall(), *this ); 484 refType->set_base( maybeMutate( refType->get_base(), *this ) ); 485 return refType; 486 } 487 482 488 Type *Mutator::mutate( FunctionType *functionType ) { 483 489 mutateAll( functionType->get_forall(), *this ); -
src/SynTree/Mutator.h
r54cd58b r9236060 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
r54cd58b r9236060 101 101 class PointerType; 102 102 class ArrayType; 103 class ReferenceType; 103 104 class FunctionType; 104 105 class ReferenceToType; -
src/SynTree/Type.cc
r54cd58b r9236060 65 65 const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" }; 66 66 67 Type * Type::stripDeclarator() {67 Type * Type::stripDeclarator() { 68 68 Type * type = this; 69 69 while ( Type * at = InitTweak::getPointerBase( type ) ) { … … 72 72 return type; 73 73 } 74 75 Type * Type::stripReferences() { 76 Type * type = this; 77 while ( ReferenceType * ref = dynamic_cast<ReferenceType *>( type ) ) { 78 type = ref->get_base(); 79 } 80 return type; 81 } 82 83 int Type::referenceDepth() const { return 0; } 74 84 75 85 void Type::print( std::ostream &os, int indent ) const { -
src/SynTree/Type.h
r54cd58b r9236060 162 162 163 163 /// return type without outer pointers and arrays 164 Type *stripDeclarator(); 164 Type * stripDeclarator(); 165 166 /// return type without outer references 167 Type * stripReferences(); 168 169 /// return the number of references occuring consecutively on the outermost layer of this type (i.e. do not count references nested within other types) 170 virtual int referenceDepth() const; 165 171 166 172 virtual bool isComplete() const { return true; } … … 256 262 bool is_array() const { return isStatic || isVarLen || dimension; } 257 263 264 virtual bool isComplete() const { return ! isVarLen; } 265 258 266 virtual PointerType *clone() const { return new PointerType( *this ); } 259 267 virtual void accept( Visitor & v ) { v.visit( this ); } … … 290 298 }; 291 299 300 class ReferenceType : public Type { 301 public: 302 Type *base; 303 304 ReferenceType( const Type::Qualifiers & tq, Type *base, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 305 ReferenceType( const ReferenceType & ); 306 virtual ~ReferenceType(); 307 308 Type *get_base() { return base; } 309 void set_base( Type *newValue ) { base = newValue; } 310 311 virtual int referenceDepth() const; 312 313 virtual ReferenceType *clone() const { return new ReferenceType( *this ); } 314 virtual void accept( Visitor & v ) { v.visit( this ); } 315 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); } 316 virtual void print( std::ostream & os, int indent = 0 ) const; 317 }; 318 292 319 class FunctionType : public Type { 293 320 public: -
src/SynTree/TypeExpr.cc
r54cd58b r9236060 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/Visitor.cc
r54cd58b r9236060 368 368 void Visitor::visit( PointerType *pointerType ) { 369 369 acceptAll( pointerType->get_forall(), *this ); 370 // xxx - should PointerType visit/mutate dimension? 370 371 maybeAccept( pointerType->get_base(), *this ); 371 372 } … … 375 376 maybeAccept( arrayType->get_dimension(), *this ); 376 377 maybeAccept( arrayType->get_base(), *this ); 378 } 379 380 void Visitor::visit( ReferenceType *refType ) { 381 acceptAll( refType->get_forall(), *this ); 382 maybeAccept( refType->get_base(), *this ); 377 383 } 378 384 -
src/SynTree/Visitor.h
r54cd58b r9236060 95 95 virtual void visit( PointerType *pointerType ); 96 96 virtual void visit( ArrayType *arrayType ); 97 virtual void visit( ReferenceType *refType ); 97 98 virtual void visit( FunctionType *functionType ); 98 99 virtual void visit( StructInstType *aggregateUseType ); -
src/SynTree/module.mk
r54cd58b r9236060 20 20 SynTree/PointerType.cc \ 21 21 SynTree/ArrayType.cc \ 22 SynTree/ReferenceType.cc \ 22 23 SynTree/FunctionType.cc \ 23 24 SynTree/ReferenceToType.cc \ -
src/Tuples/Explode.h
r54cd58b r9236060 26 26 27 27 namespace Tuples { 28 /// helper function used by explode to properly distribute29 /// '&' across a tuple expression30 Expression * distributeAddr( Expression * expr );31 32 28 /// helper function used by explode 33 29 template< typename OutputIterator > 34 30 void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign ) { 35 if ( isTupleAssign ) { 36 // tuple assignment needs AddressExprs to be recursively exploded to easily get at all of the components 37 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) { 38 ResolvExpr::AltList alts; 39 explodeUnique( addrExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign ); 40 for ( ResolvExpr::Alternative & alt : alts ) { 41 // distribute '&' over all components 42 alt.expr = distributeAddr( alt.expr ); 43 *out++ = alt; 44 } 45 // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives) 46 return; 47 } 48 } 49 Type * res = expr->get_result(); 31 Type * res = expr->get_result()->stripReferences(); 50 32 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) { 51 33 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) { … … 55 37 } 56 38 } else { 57 // tuple type, but not tuple expr - recursively index into its components 39 // tuple type, but not tuple expr - recursively index into its components. 40 // if expr type is reference, convert to value type 58 41 Expression * arg = expr->clone(); 42 43 if ( dynamic_cast<ReferenceType *>( arg->get_result() ) ) { 44 // TODO: does this go here (inside uniqueexpr) or outside uniqueexpr? I'm guessing probably should go after... 45 arg = new CastExpr( arg, tupleType->clone() ); 46 } 59 47 if ( Tuples::maybeImpure( arg ) && ! dynamic_cast< UniqueExpr * >( arg ) ) { 60 48 // expressions which may contain side effects require a single unique instance of the expression. -
src/Tuples/TupleAssignment.cc
r54cd58b r9236060 22 22 #include "Explode.h" 23 23 #include "Common/SemanticError.h" 24 #include "CodeGen/OperatorTable.h" 24 25 #include "InitTweak/InitTweak.h" 25 26 #include "InitTweak/GenInit.h" … … 77 78 if ( ! expr ) return false; 78 79 assert( expr->has_result() ); 79 return dynamic_cast< TupleType * >( expr->get_result() );80 return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() ); 80 81 } 81 82 … … 89 90 } 90 91 91 bool pointsToTuple( Expression *expr ) { 92 bool refToTuple( Expression *expr ) { 93 assert( expr->get_result() ); 92 94 // also check for function returning tuple of reference types 93 95 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 94 return pointsToTuple( castExpr->get_arg() );95 } else if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ){96 return isTuple( addr->get_arg());96 return refToTuple( castExpr->get_arg() ); 97 } else { 98 return isTuple( expr ); 97 99 } 98 100 return false; … … 109 111 void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) { 110 112 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { 111 if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) {113 if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) { 112 114 fname = op->get_name(); 113 115 for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) { 114 116 if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal 115 if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) {117 if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) { 116 118 // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it 117 119 continue; … … 122 124 const ResolvExpr::Alternative & alt1 = ali->front(); 123 125 auto begin = std::next(ali->begin(), 1), end = ali->end(); 124 if ( pointsToTuple(alt1.expr) ) {126 if ( refToTuple(alt1.expr) ) { 125 127 if ( isMultAssign( begin, end ) ) { 126 128 matcher.reset( new MultipleAssignMatcher( *this, *ali ) ); … … 196 198 for ( ResolvExpr::Alternative & alt : lhs ) { 197 199 Expression *& expr = alt.expr; 198 Type * castType = expr->get_result()->clone(); 199 Type * type = InitTweak::getPointerBase( castType ); 200 assert( type ); 200 Type * type = expr->get_result()->clone(); 201 201 type->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 202 type->set_lvalue( true ); // xxx - might not need this 203 expr = new CastExpr( expr, castType ); 202 expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), type ) ); 203 } 204 } 205 206 for ( ResolvExpr::Alternative & alt : lhs ) { 207 // every LHS value must be a reference - some come in with a cast expression, if it doesn't just cast to reference here. 208 // TODO: can this somehow be merge with the cast code directly above? 209 if ( ! dynamic_cast< ReferenceType * >( alt.expr->get_result() ) ) { 210 alt.expr = new CastExpr( alt.expr, new ReferenceType( Type::Qualifiers(), alt.expr->get_result()->clone() ) ); 204 211 } 205 212 } … … 221 228 assert( left ); 222 229 std::list< Expression * > args; 223 args.push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( left ) )) );230 args.push_back( new VariableExpr( left ) ); 224 231 // args.push_back( new AddressExpr( new VariableExpr( left ) ) ); 225 232 if ( right ) args.push_back( new VariableExpr( right ) ); … … 241 248 assert( expr->has_result() && ! expr->get_result()->isVoid() ); 242 249 ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) ); 243 ConstructorInit * ctorInit = InitTweak::genCtorInit( ret ); 244 ret->set_init( ctorInit ); 245 ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object 246 EnvRemover rm; // remove environments from subexpressions of StmtExprs 247 ctorInit->accept( rm ); 250 // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient. 251 if ( ! dynamic_cast< ReferenceType * >( expr->get_result() ) ) { 252 ConstructorInit * ctorInit = InitTweak::genCtorInit( ret ); 253 ret->set_init( ctorInit ); 254 ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object 255 EnvRemover rm; // remove environments from subexpressions of StmtExprs 256 ctorInit->accept( rm ); 257 } 248 258 return ret; 249 259 } -
src/libcfa/concurrency/alarm.c
r54cd58b r9236060 40 40 __cfa_time_t zero_time = { 0 }; 41 41 42 void ?{}( __cfa_time_t * this ) { this->val = 0; }43 void ?{}( __cfa_time_t * this, zero_t zero ) { this->val = 0; }44 45 void ?{}( itimerval *this, __cfa_time_t * alarm ) {46 this ->it_value.tv_sec = alarm->val / one_second; // seconds47 this ->it_value.tv_usec = max( (alarm->val % one_second) / one_microsecond, 1000 ); // microseconds48 this ->it_interval.tv_sec = 0;49 this ->it_interval.tv_usec = 0;50 } 51 52 53 void ?{}( __cfa_time_t *this, timespec * curr ) {42 void ?{}( __cfa_time_t & this ) { this.val = 0; } 43 void ?{}( __cfa_time_t & this, zero_t zero ) { this.val = 0; } 44 45 void ?{}( itimerval & this, __cfa_time_t * alarm ) { 46 this.it_value.tv_sec = alarm->val / one_second; // seconds 47 this.it_value.tv_usec = max( (alarm->val % one_second) / one_microsecond, 1000 ); // microseconds 48 this.it_interval.tv_sec = 0; 49 this.it_interval.tv_usec = 0; 50 } 51 52 53 void ?{}( __cfa_time_t & this, timespec * curr ) { 54 54 uint64_t secs = curr->tv_sec; 55 55 uint64_t nsecs = curr->tv_nsec; 56 this ->val = (secs * one_second) + nsecs;57 } 58 59 __cfa_time_t ?=?( __cfa_time_t *this, zero_t rhs ) {60 this ->val = 0;61 return *this;56 this.val = (secs * one_second) + nsecs; 57 } 58 59 __cfa_time_t ?=?( __cfa_time_t & this, zero_t rhs ) { 60 this.val = 0; 61 return this; 62 62 } 63 63 … … 86 86 //============================================================================================= 87 87 88 void ?{}( alarm_node_t *this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) {89 this ->thrd = thrd;90 this ->alarm = alarm;91 this ->period = period;92 this ->next = 0;93 this ->set = false;94 this ->kernel_alarm = false;95 } 96 97 void ?{}( alarm_node_t *this, processor * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) {98 this ->proc = proc;99 this ->alarm = alarm;100 this ->period = period;101 this ->next = 0;102 this ->set = false;103 this ->kernel_alarm = true;104 } 105 106 void ^?{}( alarm_node_t *this ) {107 if( this ->set ) {108 unregister_self( this );88 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) { 89 this.thrd = thrd; 90 this.alarm = alarm; 91 this.period = period; 92 this.next = 0; 93 this.set = false; 94 this.kernel_alarm = false; 95 } 96 97 void ?{}( alarm_node_t & this, processor * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ) { 98 this.proc = proc; 99 this.alarm = alarm; 100 this.period = period; 101 this.next = 0; 102 this.set = false; 103 this.kernel_alarm = true; 104 } 105 106 void ^?{}( alarm_node_t & this ) { 107 if( this.set ) { 108 unregister_self( &this ); 109 109 } 110 110 } -
src/libcfa/concurrency/alarm.h
r54cd58b r9236060 36 36 37 37 // ctors 38 void ?{}( __cfa_time_t *this );39 void ?{}( __cfa_time_t *this, zero_t zero );40 void ?{}( __cfa_time_t *this, timespec * curr );41 void ?{}( itimerval *this, __cfa_time_t * alarm );38 void ?{}( __cfa_time_t & this ); 39 void ?{}( __cfa_time_t & this, zero_t zero ); 40 void ?{}( __cfa_time_t & this, timespec * curr ); 41 void ?{}( itimerval & this, __cfa_time_t * alarm ); 42 42 43 __cfa_time_t ?=?( __cfa_time_t *this, zero_t rhs );43 __cfa_time_t ?=?( __cfa_time_t & this, zero_t rhs ); 44 44 45 45 // logical ops … … 105 105 typedef alarm_node_t ** __alarm_it_t; 106 106 107 void ?{}( alarm_node_t *this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );108 void ?{}( alarm_node_t *this, processor * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time );109 void ^?{}( alarm_node_t *this );107 void ?{}( alarm_node_t & this, thread_desc * thrd, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ); 108 void ?{}( alarm_node_t & this, processor * proc, __cfa_time_t alarm = zero_time, __cfa_time_t period = zero_time ); 109 void ^?{}( alarm_node_t & this ); 110 110 111 111 struct alarm_list_t { … … 114 114 }; 115 115 116 static inline void ?{}( alarm_list_t *this ) {117 this ->head = 0;118 this ->tail = &this->head;116 static inline void ?{}( alarm_list_t & this ) { 117 this.head = 0; 118 this.tail = &this.head; 119 119 } 120 120 -
src/libcfa/concurrency/coroutine
r54cd58b r9236060 25 25 // Anything that is resumed is a coroutine. 26 26 trait is_coroutine(dtype T) { 27 void main(T *this);28 coroutine_desc * get_coroutine(T *this);27 void main(T & this); 28 coroutine_desc * get_coroutine(T & this); 29 29 }; 30 30 31 #define DECL_COROUTINE(X) static inline coroutine_desc* get_coroutine(X * this) { return &this->__cor; } void main(X*this)31 #define DECL_COROUTINE(X) static inline coroutine_desc* get_coroutine(X& this) { return &this.__cor; } void main(X& this) 32 32 33 33 //----------------------------------------------------------------------------- 34 34 // Ctors and dtors 35 void ?{}(coStack_t *this);36 void ?{}(coroutine_desc *this);37 void ?{}(coroutine_desc *this, const char * name);38 void ^?{}(coStack_t *this);39 void ^?{}(coroutine_desc *this);35 void ?{}(coStack_t & this); 36 void ?{}(coroutine_desc & this); 37 void ?{}(coroutine_desc & this, const char * name); 38 void ^?{}(coStack_t & this); 39 void ^?{}(coroutine_desc & this); 40 40 41 41 //----------------------------------------------------------------------------- … … 44 44 45 45 forall(dtype T | is_coroutine(T)) 46 static inline void resume(T *cor);46 static inline void resume(T & cor); 47 47 48 48 forall(dtype T | is_coroutine(T)) 49 void prime(T *cor);49 void prime(T & cor); 50 50 51 51 //----------------------------------------------------------------------------- … … 86 86 // Resume implementation inlined for performance 87 87 forall(dtype T | is_coroutine(T)) 88 static inline void resume(T *cor) {88 static inline void resume(T & cor) { 89 89 coroutine_desc * src = this_coroutine; // optimization 90 90 coroutine_desc * dst = get_coroutine(cor); … … 92 92 if( unlikely(!dst->stack.base) ) { 93 93 create_stack(&dst->stack, dst->stack.size); 94 CtxStart( cor, CtxInvokeCoroutine);94 CtxStart(&cor, CtxInvokeCoroutine); 95 95 } 96 96 -
src/libcfa/concurrency/coroutine.c
r54cd58b r9236060 40 40 //----------------------------------------------------------------------------- 41 41 // Coroutine ctors and dtors 42 void ?{}(coStack_t *this) {43 this ->size = 65000; // size of stack44 this ->storage = NULL; // pointer to stack45 this ->limit = NULL; // stack grows towards stack limit46 this ->base = NULL; // base of stack47 this ->context = NULL; // address of cfa_context_t48 this ->top = NULL; // address of top of storage49 this ->userStack = false;42 void ?{}(coStack_t& this) { 43 this.size = 65000; // size of stack 44 this.storage = NULL; // pointer to stack 45 this.limit = NULL; // stack grows towards stack limit 46 this.base = NULL; // base of stack 47 this.context = NULL; // address of cfa_context_t 48 this.top = NULL; // address of top of storage 49 this.userStack = false; 50 50 } 51 51 52 void ?{}(coStack_t *this, size_t size) {52 void ?{}(coStack_t& this, size_t size) { 53 53 this{}; 54 this ->size = size;54 this.size = size; 55 55 56 create_stack( this, this->size);56 create_stack(&this, this.size); 57 57 } 58 58 59 void ?{}(coroutine_desc *this) {59 void ?{}(coroutine_desc& this) { 60 60 this{ "Anonymous Coroutine" }; 61 61 } 62 62 63 void ?{}(coroutine_desc *this, const char * name) {64 this ->name = name;65 this ->errno_ = 0;66 this ->state = Start;67 this ->starter = NULL;68 this ->last = NULL;63 void ?{}(coroutine_desc& this, const char * name) { 64 this.name = name; 65 this.errno_ = 0; 66 this.state = Start; 67 this.starter = NULL; 68 this.last = NULL; 69 69 } 70 70 71 void ?{}(coroutine_desc *this, size_t size) {71 void ?{}(coroutine_desc& this, size_t size) { 72 72 this{}; 73 ( &this->stack){size};73 (this.stack){size}; 74 74 } 75 75 76 void ^?{}(coStack_t *this) {77 if ( ! this ->userStack ) {76 void ^?{}(coStack_t& this) { 77 if ( ! this.userStack ) { 78 78 LIB_DEBUG_DO( 79 if ( mprotect( this ->storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) {80 abortf( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", this, errno, strerror( errno ) );79 if ( mprotect( this.storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) { 80 abortf( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) ); 81 81 } 82 82 ); 83 free( this ->storage );83 free( this.storage ); 84 84 } 85 85 } 86 86 87 void ^?{}(coroutine_desc *this) {}87 void ^?{}(coroutine_desc& this) {} 88 88 89 89 // Part of the Public API 90 90 // Not inline since only ever called once per coroutine 91 91 forall(dtype T | is_coroutine(T)) 92 void prime(T *cor) {92 void prime(T& cor) { 93 93 coroutine_desc* this = get_coroutine(cor); 94 94 assert(this->state == Start); -
src/libcfa/concurrency/invoke.h
r54cd58b r9236060 47 47 #ifdef __CFORALL__ 48 48 extern "Cforall" { 49 void ?{}( struct __thread_queue_t *);49 void ?{}( struct __thread_queue_t & ); 50 50 void append( struct __thread_queue_t *, struct thread_desc * ); 51 51 struct thread_desc * pop_head( struct __thread_queue_t * ); 52 52 53 void ?{}( struct __condition_stack_t *);53 void ?{}( struct __condition_stack_t & ); 54 54 void push( struct __condition_stack_t *, struct __condition_criterion_t * ); 55 55 struct __condition_criterion_t * pop( struct __condition_stack_t * ); 56 56 57 void ?{}(spinlock *this);58 void ^?{}(spinlock *this);57 void ?{}(spinlock & this); 58 void ^?{}(spinlock & this); 59 59 } 60 60 #endif -
src/libcfa/concurrency/kernel
r54cd58b r9236060 37 37 }; 38 38 39 void ?{}(semaphore *this, int count = 1);40 void ^?{}(semaphore *this);39 void ?{}(semaphore & this, int count = 1); 40 void ^?{}(semaphore & this); 41 41 void P(semaphore * this); 42 42 void V(semaphore * this); … … 51 51 }; 52 52 53 void ?{}(cluster *this);54 void ^?{}(cluster *this);53 void ?{}(cluster & this); 54 void ^?{}(cluster & this); 55 55 56 56 //----------------------------------------------------------------------------- … … 68 68 unsigned short thrd_count; 69 69 }; 70 static inline void ?{}(FinishAction *this) {71 this ->action_code = No_Action;72 this ->thrd = NULL;73 this ->lock = NULL;70 static inline void ?{}(FinishAction & this) { 71 this.action_code = No_Action; 72 this.thrd = NULL; 73 this.lock = NULL; 74 74 } 75 static inline void ^?{}(FinishAction *this) {}75 static inline void ^?{}(FinishAction & this) {} 76 76 77 77 // Processor … … 99 99 }; 100 100 101 void ?{}(processor *this);102 void ?{}(processor *this, cluster * cltr);103 void ^?{}(processor *this);101 void ?{}(processor & this); 102 void ?{}(processor & this, cluster * cltr); 103 void ^?{}(processor & this); 104 104 105 105 // Local Variables: // -
src/libcfa/concurrency/kernel.c
r54cd58b r9236060 73 73 }; 74 74 75 void ?{}( current_stack_info_t *this ) {76 CtxGet( this ->ctx );77 this ->base = this->ctx.FP;78 this ->storage = this->ctx.SP;75 void ?{}( current_stack_info_t & this ) { 76 CtxGet( this.ctx ); 77 this.base = this.ctx.FP; 78 this.storage = this.ctx.SP; 79 79 80 80 rlimit r; 81 81 getrlimit( RLIMIT_STACK, &r); 82 this ->size = r.rlim_cur;83 84 this ->limit = (void *)(((intptr_t)this->base) - this->size);85 this ->context = &storage_mainThreadCtx;86 this ->top = this->base;87 } 88 89 void ?{}( coStack_t *this, current_stack_info_t * info) {90 this ->size = info->size;91 this ->storage = info->storage;92 this ->limit = info->limit;93 this ->base = info->base;94 this ->context = info->context;95 this ->top = info->top;96 this ->userStack = true;97 } 98 99 void ?{}( coroutine_desc *this, current_stack_info_t * info) {100 ( &this->stack){ info };101 this ->name = "Main Thread";102 this ->errno_ = 0;103 this ->state = Start;104 } 105 106 void ?{}( thread_desc *this, current_stack_info_t * info) {107 ( &this->cor){ info };82 this.size = r.rlim_cur; 83 84 this.limit = (void *)(((intptr_t)this.base) - this.size); 85 this.context = &storage_mainThreadCtx; 86 this.top = this.base; 87 } 88 89 void ?{}( coStack_t & this, current_stack_info_t * info) { 90 this.size = info->size; 91 this.storage = info->storage; 92 this.limit = info->limit; 93 this.base = info->base; 94 this.context = info->context; 95 this.top = info->top; 96 this.userStack = true; 97 } 98 99 void ?{}( coroutine_desc & this, current_stack_info_t * info) { 100 (this.stack){ info }; 101 this.name = "Main Thread"; 102 this.errno_ = 0; 103 this.state = Start; 104 } 105 106 void ?{}( thread_desc & this, current_stack_info_t * info) { 107 (this.cor){ info }; 108 108 } 109 109 110 110 //----------------------------------------------------------------------------- 111 111 // Processor coroutine 112 void ?{}(processorCtx_t *this, processor * proc) {113 ( &this->__cor){ "Processor" };114 this ->proc = proc;115 proc->runner = this;116 } 117 118 void ?{}(processorCtx_t *this, processor * proc, current_stack_info_t * info) {119 ( &this->__cor){ info };120 this ->proc = proc;121 proc->runner = this;122 } 123 124 void ?{}(processor *this) {112 void ?{}(processorCtx_t & this, processor * proc) {