Changeset d3e4d6c for src/InitTweak
- Timestamp:
- Aug 23, 2017, 6:22:07 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 87e08e24, cb811ac
- Parents:
- 9f07232 (diff), bd37119 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- src/InitTweak
- Files:
-
- 4 edited
-
FixInit.cc (modified) (15 diffs)
-
GenInit.cc (modified) (5 diffs)
-
InitTweak.cc (modified) (4 diffs)
-
InitTweak.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r9f07232 rd3e4d6c 29 29 30 30 #include "CodeGen/GenType.h" // for genPrettyType 31 #include "CodeGen/OperatorTable.h" 31 32 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 32 33 #include "Common/SemanticError.h" // for SemanticError … … 254 255 SemanticError errors; 255 256 private: 256 void handleFirstParam( Expression * firstParam );257 257 template< typename... Params > 258 258 void emit( CodeLocation, const Params &... params ); … … 379 379 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 380 380 assert( ftype ); 381 if ( isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {382 Type * t1 = ftype->get_parameters().front()->get_type();381 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) { 382 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); 383 383 Type * t2 = ftype->get_parameters().back()->get_type(); 384 PointerType * ptrType = safe_dynamic_cast< PointerType * >( t1 );385 386 if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {384 assert( t1 ); 385 386 if ( ResolvExpr::typesCompatible( t1, t2, SymTab::Indexer() ) ) { 387 387 // optimization: don't need to copy construct in order to call a copy constructor 388 388 return appExpr; 389 389 } // if 390 } else if ( isDestructor( funcDecl->get_name() ) ) {390 } else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) { 391 391 // correctness: never copy construct arguments to a destructor 392 392 return appExpr; … … 417 417 418 418 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { 419 return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );419 return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type ); 420 420 } 421 421 … … 505 505 impCpCtorExpr->get_returnDecls().push_back( ret ); 506 506 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 507 if ( ! result->get_lvalue() ) {507 if ( ! dynamic_cast< ReferenceType * >( result ) ) { 508 508 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 509 509 destructRet( ret, impCpCtorExpr ); … … 607 607 608 608 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 609 if ( callExpr->get_result()->get_lvalue() ) {610 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning611 // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the612 // type of the return temporary from T to T* to properly capture the return value. Then dereference613 // the result of the comma expression, since the lvalue returning call was originally wrapped with614 // an AddressExpr. Effectively, this turns615 // lvalue T f();616 // &*f();617 // into618 // T * f();619 // T * tmp_cp_retN;620 // &*(tmp_cp_retN = &*f(), tmp_cp_retN); // the first * and second & are generated here621 // which work out in terms of types, but is pretty messy. It would be nice to find a better way.622 assign->get_args().back() = new AddressExpr( assign->get_args().back() );623 624 returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );625 retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) );626 retExpr = UntypedExpr::createDeref( retExpr );627 } // if628 609 // move env from callExpr to retExpr 629 610 retExpr->set_env( callExpr->get_env() ); … … 991 972 if ( ! funcDecl ) return false; 992 973 if ( ! funcDecl->get_statements() ) return false; 993 return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );974 return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() ); 994 975 } 995 976 … … 1008 989 1009 990 function = funcDecl; 1010 isCtor = isConstructor( function->get_name() );991 isCtor = CodeGen::isConstructor( function->get_name() ); 1011 992 if ( checkWarnings( function ) ) { 1012 993 FunctionType * type = function->get_functionType(); 1013 994 assert( ! type->get_parameters().empty() ); 1014 995 thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() ); 1015 PointerType * ptrType = safe_dynamic_cast< PointerType * >( thisParam->get_type() );1016 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base());996 Type * thisType = getPointerBase( thisParam->get_type() ); 997 StructInstType * structType = dynamic_cast< StructInstType * >( thisType ); 1017 998 if ( structType ) { 1018 999 structDecl = structType->get_baseStruct(); … … 1047 1028 1048 1029 if ( ! unhandled.empty() ) { 1049 // need to explicitly re-add function parameters in order to resolve copy constructors1030 // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors 1050 1031 enterScope(); 1051 1032 maybeAccept( function->get_functionType(), *this ); … … 1062 1043 // insert and resolve default/copy constructor call for each field that's unhandled 1063 1044 std::list< Statement * > stmt; 1064 UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) );1065 1066 1045 Expression * arg2 = 0; 1067 1046 if ( isCopyConstructor( function ) ) { … … 1072 1051 } 1073 1052 InitExpander srcParam( arg2 ); 1074 SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor ); 1053 // cast away reference type and construct field. 1054 Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() ); 1055 Expression * memberDest = new MemberExpr( field, thisExpr ); 1056 SymTab::genImplicitCall( srcParam, memberDest, function->get_name(), back_inserter( stmt ), field, isCtor ); 1075 1057 1076 1058 assert( stmt.size() <= 1 ); … … 1099 1081 } 1100 1082 1083 /// true if expr is effectively just the 'this' parameter 1084 bool isThisExpression( Expression * expr, DeclarationWithType * thisParam ) { 1085 // TODO: there are more complicated ways to pass 'this' to a constructor, e.g. &*, *&, etc. 1086 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 1087 return varExpr->get_var() == thisParam; 1088 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( expr ) ) { 1089 return isThisExpression( castExpr->get_arg(), thisParam ); 1090 } 1091 return false; 1092 } 1093 1094 /// returns a MemberExpr if expr is effectively just member access on the 'this' parameter, else nullptr 1095 MemberExpr * isThisMemberExpr( Expression * expr, DeclarationWithType * thisParam ) { 1096 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) { 1097 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { 1098 return memberExpr; 1099 } 1100 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 1101 return isThisMemberExpr( castExpr->get_arg(), thisParam ); 1102 } 1103 return nullptr; 1104 } 1105 1101 1106 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) { 1102 1107 if ( ! checkWarnings( function ) ) return; … … 1107 1112 Expression * firstParam = appExpr->get_args().front(); 1108 1113 1109 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {1114 if ( isThisExpression( firstParam, thisParam ) ) { 1110 1115 // if calling another constructor on thisParam, assume that function handles 1111 1116 // all members - if it doesn't a warning will appear in that function. 1112 if ( varExpr->get_var() == thisParam ) { 1113 unhandled.clear(); 1114 } 1115 } else { 1116 // if first parameter is a member expression then 1117 // remove the member from unhandled set. 1118 handleFirstParam( firstParam ); 1119 } 1120 } 1121 1122 Parent::visit( appExpr ); 1123 } 1124 1125 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) { 1126 using namespace std; 1127 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) { 1128 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) { 1129 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 1130 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 1131 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 1132 if ( varExpr->get_var() == thisParam ) { 1133 unhandled.erase( memberExpr->get_member() ); 1134 } 1135 } 1136 } 1117 unhandled.clear(); 1118 } else if ( MemberExpr * memberExpr = isThisMemberExpr( firstParam, thisParam ) ) { 1119 // if first parameter is a member expression on the this parameter, 1120 // then remove the member from unhandled set. 1121 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { 1122 unhandled.erase( memberExpr->get_member() ); 1137 1123 } 1138 1124 } 1139 1125 } 1126 Parent::visit( appExpr ); 1140 1127 } 1141 1128 … … 1144 1131 if ( ! isCtor ) return; 1145 1132 1146 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 1147 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 1148 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 1149 if ( varExpr->get_var() == thisParam ) { 1150 if ( unhandled.count( memberExpr->get_member() ) ) { 1151 // emit a warning because a member was used before it was constructed 1152 usedUninit.insert( { memberExpr->get_member(), memberExpr->location } ); 1153 } 1154 } 1155 } 1133 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) { 1134 if ( unhandled.count( memberExpr->get_member() ) ) { 1135 // emit a warning because a member was used before it was constructed 1136 usedUninit.insert( { memberExpr->get_member(), memberExpr->location } ); 1156 1137 } 1157 1138 } … … 1199 1180 ctorExpr->set_callExpr( nullptr ); 1200 1181 ctorExpr->set_env( nullptr ); 1182 delete ctorExpr; 1201 1183 1202 1184 Expression *& firstArg = callExpr->get_args().front(); 1203 UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) ); 1204 assign->get_args().push_back( new VariableExpr( tmp ) ); 1205 assign->get_args().push_back( firstArg ); 1206 assign->set_result( ctorExpr->get_result()->clone() ); 1207 firstArg = assign; 1208 1209 CommaExpr * commaExpr = new CommaExpr( callExpr, new VariableExpr( tmp ) ); 1185 1186 // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away. 1187 1188 // generate the type of assignment operator using the type of tmp minus any reference types 1189 Type * type = tmp->get_type()->stripReferences(); 1190 FunctionType * ftype = SymTab::genAssignType( type ); 1191 1192 // generate fake assignment decl and call it using &tmp and &firstArg 1193 // since tmp is guaranteed to be a reference and we want to assign pointers 1194 FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr ); 1195 ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) ); 1196 assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) ); 1197 Expression * addrArg = new AddressExpr( firstArg ); 1198 // if firstArg has type T&&, then &firstArg has type T*&. 1199 // Cast away the reference to a value type so that the argument 1200 // matches the assignment's parameter types 1201 if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) { 1202 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() ); 1203 } 1204 assign->get_args().push_back( addrArg ); 1205 firstArg = new VariableExpr( tmp ); 1206 1207 // for constructor expr: 1208 // T x; 1209 // x{}; 1210 // results in: 1211 // T x; 1212 // T & tmp; 1213 // &tmp = &x, ?{}(tmp), tmp 1214 CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) ); 1210 1215 commaExpr->set_env( env ); 1211 delete ctorExpr;1212 1216 return commaExpr; 1213 1217 } -
src/InitTweak/GenInit.cc
r9f07232 rd3e4d6c 21 21 #include <list> // for _List_iterator, list 22 22 23 #include "CodeGen/OperatorTable.h" 23 24 #include "Common/PassVisitor.h" // for PassVisitor, WithGuards, WithShort... 24 25 #include "Common/SemanticError.h" // for SemanticError … … 57 58 58 59 protected: 59 FunctionType * ftype ;60 FunctionType * ftype = nullptr; 60 61 std::string funcName; 61 62 }; … … 140 141 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals(); 141 142 assert( returnVals.size() == 0 || returnVals.size() == 1 ); 142 // hands off if the function returns a n lvalue - we don't want to allocate a temporary if a variable's address143 // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address 143 144 // is being returned 144 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! returnVals.front()->get_type()->get_lvalue() ) {145 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) { 145 146 // explicitly construct the return value using the return expression and the retVal object 146 147 assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() ); 147 UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) ); 148 construct->get_args().push_back( new AddressExpr( new VariableExpr( returnVals.front() ) ) ); 149 construct->get_args().push_back( returnStmt->get_expr() ); 150 stmtsToAddBefore.push_back(new ExprStmt(noLabels, construct)); 148 149 stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) ); 151 150 152 151 // return the retVal object … … 215 214 216 215 bool CtorDtor::isManaged( Type * type ) const { 216 // at least for now, references are never constructed 217 if ( dynamic_cast< ReferenceType * >( type ) ) return false; 217 218 // need to clear and reset qualifiers when determining if a type is managed 218 219 ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() ); … … 238 239 void CtorDtor::handleDWT( DeclarationWithType * dwt ) { 239 240 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 240 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && isCtorDtor( dwt->get_name() ) ) {241 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) { 241 242 std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters(); 242 243 assert( ! params.empty() ); 243 PointerType * type = safe_dynamic_cast< PointerType * >( params.front()->get_type() ); 244 managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) ); 244 Type * type = InitTweak::getPointerBase( params.front()->get_type() ); 245 assert( type ); 246 managedTypes.insert( SymTab::Mangler::mangle( type ) ); 245 247 } 246 248 } -
src/InitTweak/InitTweak.cc
r9f07232 rd3e4d6c 187 187 188 188 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) ); 189 increment->get_args().push_back( new AddressExpr( index->clone()) );189 increment->get_args().push_back( index->clone() ); 190 190 *out++ = new ExprStmt( noLabels, increment ); 191 191 } … … 397 397 template<typename CallExpr> 398 398 Expression *& callArg( CallExpr * callExpr, unsigned int pos ) { 399 if ( pos >= callExpr->get_args().size() ) assertf( false, " asking for argument that doesn't exist. Return NULL/throw exception?");399 if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() ); 400 400 for ( Expression *& arg : callExpr->get_args() ) { 401 401 if ( pos == 0 ) return arg; … … 475 475 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 476 476 return arrayType->get_base(); 477 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) { 478 return refType->get_base(); 477 479 } else { 478 480 return NULL; … … 560 562 if ( ftype->get_parameters().size() != 2 ) return 0; 561 563 562 Type * t1 = ftype->get_parameters().front()->get_type();564 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); 563 565 Type * t2 = ftype->get_parameters().back()->get_type(); 564 PointerType * ptrType = dynamic_cast< PointerType * > ( t1 ); 565 assert( ptrType ); 566 567 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( ptrType->get_base(), t2, SymTab::Indexer() ) ) { 566 assert( t1 ); 567 568 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) { 568 569 return function; 569 570 } else { -
src/InitTweak/InitTweak.h
r9f07232 rd3e4d6c 24 24 // helper functions for initialization 25 25 namespace InitTweak { 26 bool isConstructor( const std::string & );27 bool isDestructor( const std::string & );28 bool isAssignment( const std::string & );29 bool isCtorDtor( const std::string & );30 bool isCtorDtorAssign( const std::string & );31 32 26 FunctionDecl * isAssignment( Declaration * decl ); 33 27 FunctionDecl * isDestructor( Declaration * decl );
Note:
See TracChangeset
for help on using the changeset viewer.