static boolean adjustForVirtualCall( // ADJUSTMENTS FOR POSSIBLE VIRTUAL CALL PTREE *this_node, // - addr[ "this" node ] PTREE *routine, // - routine to be called SEARCH_RESULT *result ) // - search result for routine { SYMBOL sym; // - symbol for call unsigned retn; // - return: TRUE ==> adjusted for virtual TYPE this_type; // - target type for "this" PTREE expr; // - transformed expression boolean exact_call; // - TRUE ==> this node is exact expr = *this_node; this_type = NodeType( expr ); this_type = StructType( this_type ); if( this_type != NULL ) { if( OMR_CLASS_VAL == ObjModelArgument( this_type ) ) { expr = NodeAssignTemporary( this_type, expr ); } else { expr = NodeConvert( MakePointerTo( expr->type ), expr ); } *this_node = expr; } sym = (*routine)->u.symcg.symbol; this_type = TypeThisForCall( expr, sym ); /* virtual calls don't have to check for NULL pointers when they convert */ expr->flags |= PTF_PTR_NONZERO; exact_call = expr->flags & PTF_MEMORY_EXACT; NodeConvertToBasePtr( this_node, this_type, result, TRUE ); sym = SymDefaultBase( sym ); if( ( SymIsVirtual( sym ) ) &&( ! ( (*routine)->flags & PTF_COLON_QUALED ) ) &&( ! exact_call ) ) { expr = AccessVirtualFnAddress( NodeDupExpr( this_node ) , result , sym ); expr->type = MakePointerTo( expr->type ); *routine = NodeReplace( *routine, expr ); retn = TRUE; } else { NodeFreeSearchResult( *routine ); retn = FALSE; } return( retn ); }
// This is kluge because of the lack of a code-generation interface to // signal a virtual function reference. // // This is accomplished by putting out a fake virtual call in dead-code. // void VfnReference( // EMIT VIRTUAL FUNCTION REFERENCE SYMBOL vfun ) // - a virtual function { CGLABEL around; // - label for jump around PTREE fake; // - fake call expression around = CgFrontLabelCs(); CgFrontGotoNear( IC_LABEL_CS, O_GOTO, around ); fake = NodeAssignTemporary( MakePointerTo( vfun->sym_type ) , NodeMakeCallee( vfun ) ); fake = NodeRvalue( fake ); fake = NodeUnaryCopy( CO_CALL_SETUP_IND, fake ); fake = VfnDecorateCall( fake, vfun ); fake = NodeBinary( CO_CALL_EXEC_IND, fake, NULL ); fake->type = SymFuncReturnType( vfun ); fake->flags |= PTF_MEANINGFUL | PTF_SIDE_EFF; fake = NodeDone( fake ); IcEmitExpr( fake ); CgFrontLabdefCs( around ); CgFrontLabfreeCs( 1 ); }