PTREE NodeConvertVirtualPtr( // EXECUTE A VIRTUAL BASE CAST PTREE expr, // - expr to cast TYPE final_type, // - final type after cast target_offset_t vb_offset, // - offset of vbptr vindex vb_index ) // - index in vbtable { PTREE offset; TYPE vbptr_type; TYPE adjust_type; PTREE dup; vbptr_type = MakeVBTableFieldType( true ); offset = NodeOffset( vb_offset ); expr = NodeBinary( CO_DOT, expr, offset ); expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO; expr->type = vbptr_type; dup = NodeDupExpr( &expr ); expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO; expr = NodeFetch( expr ); expr->type = vbptr_type; expr->flags &= ~ PTF_LVALUE; expr->flags |= PTF_PTR_NONZERO; adjust_type = TypePointedAtModified( vbptr_type ); offset = NodeOffset( vb_index * CgMemorySize( adjust_type ) ); expr = NodeBinary( CO_DOT, expr, offset ); expr->type = adjust_type; expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO; expr = NodeFetch( expr ); expr->type = adjust_type; expr->flags |= PTF_PTR_NONZERO; expr = NodeBinary( CO_DOT, dup, expr ); expr->type = final_type; expr->flags |= PTF_LVALUE | PTF_PTR_NONZERO; return( expr ); }
static PTREE genVfunCall( // DIRECTLY GENERATE VFUN CALL target_offset_t vf_offset, // - offset to VF table ptr PTREE node, // - original "this" expression target_offset_t vf_index, // - index into VF table SYMBOL sym ) // - symbol to access { TYPE vfptr_type; // - type[ ptr to VF table ] TYPE vfn_type; // - type[ ptr to VF ] node = NodeBinary( CO_DOT, node, NodeOffset( vf_offset ) ); vfptr_type = MakeVFTableFieldType( TRUE ); node->type = vfptr_type; node->flags |= PTF_LVALUE; node = PtdExprConst( node ); node = NodeRvalue( node ); vfn_type = TypePointedAtModified( vfptr_type ); node = NodeBinary( CO_DOT , node , NodeOffset( vf_index * CgMemorySize( vfn_type ) ) ); node->type = vfn_type; node->flags |= PTF_LVALUE; node = NodeRvalue( node ); node->type = sym->sym_type; return node; }
static PTREE adjust_base_ptr( // ADJUST BASE PTR AS true/TESTING CONVERSION PTREE orig, // - original node PTREE offset, // - offset calculation TYPE type ) // - type, after conversion { if( orig->flags & PTF_PTR_NONZERO ) { orig = NodeBinary( CO_DOT, orig, offset ); } else { orig = NodeBinary( CO_PTR_DELTA, orig, offset ); } orig->type = type; return( orig ); }
PTREE UdcCall // CALL UDC FUNCTION ( PTREE src // - source expression , TYPE udcf_type // - type for udcf , CALL_DIAG* diagnosis ) // - call diagnosis { PTREE node; // - node under construction SEARCH_RESULT* result; // - result for scope diagnosis TYPE class_type; // - class for UDCF class_type = ClassTypeForType( NodeType( src ) ); result = ScopeFindScopedMemberConversion ( class_type->u.c.scope , NULL , udcf_type , TF1_NULL ); node = NodeMakeCallee( result->sym ); node->u.symcg.result = result; node->cgop = CO_NAME_CONVERT; node = NodeDottedFunction( src, node ); node = PTreeCopySrcLocation( node, src ); node = NodeBinary( CO_CALL_NOOVLD, node, NULL ); node = PTreeCopySrcLocation( node, src ); node = AnalyseCall( node, diagnosis ); return node; }
static PTREE makeCall( // MAKE A CALL OR INDIRECT CALL PTREE proc, // - procedure TYPE type, // - return type PTREE args, // - arguments boolean direct_call ) // - TRUE ==> do a direct call { PTREE node; // - new node if( direct_call ) { node = NodeUnaryCopy( CO_CALL_SETUP, proc ); node = NodeBinary( CO_CALL_EXEC, node, args ); } else { node = VfunSetupCall( proc ); node = NodeBinary( CO_CALL_EXEC_IND, node, args ); } return NodeSetType( node, type, PTF_MEANINGFUL | PTF_SIDE_EFF ); }
PTREE VfnDecorateCall( // DECORATE VIRTUAL CALL PTREE expr, // - call-setup expression SYMBOL vfun ) // - virtual function { PTREE sym; // - node for virtual function call vfun = SymDefaultBase( vfun ); sym = NodeMakeCallee( vfun ); sym->cgop = CO_IGNORE; sym = NodeBinary( CO_VIRT_FUNC, expr, sym ); sym->flags = expr->flags; sym->type = expr->type; return( sym ); }
// 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 ); }
void NodeConvertToBasePtr( // CONVERT TO A BASE PTR, USING SEARCH_RESULT PTREE *a_expr, // - addr( ptr to be converted ) TYPE base, // - base type SEARCH_RESULT *result, // - search result bool positive ) // - true ==> use positive value { target_offset_t vb_offset; // - offset of vbptr vindex vb_index; // - index in vbtable target_offset_t delta; // - delta for class PTREE node; // - new node PTREE dup; // - node containing duplicate of original PTREE orig; // - original value TYPE ref_type; // - reference type for original value node = *a_expr; /* references can never be NULL by definition */ ref_type = TypeReference( NodeType( node ) ); if( ref_type != NULL ) { node->flags |= PTF_PTR_NONZERO; } if( node->flags & PTF_MEMORY_EXACT ) { adjust_by_delta( a_expr, base, result->exact_delta, positive ); } else if( result->non_virtual ) { adjust_by_delta( a_expr, base, result->delta, positive ); } else { PTF_FLAG orig_prop; // - flags propogated from original SYMBOL ibp; // - inline bound reference parameter target_offset_t offset; // - offset to ibp #if 0 orig_prop = ( node->flags & PTF_FETCH ) | PTF_LVALUE; #else orig_prop = node->flags & PTF_FETCH; if( NULL != ref_type ) { orig_prop |= PTF_LVALUE; } #endif if( NodeGetIbpSymbol( node, &ibp, &offset ) ) { PTREE expr; // - expression under construction unsigned vb_exact; // - exact offset for conversion vb_exact = result->exact_delta; if( ! positive ) { vb_exact = - vb_exact; } vb_exact += offset; if( NULL == ibp ) { expr = NULL; } else { expr = NodeMakeCallee( ibp ); expr->cgop = CO_IGNORE; } expr = NodeUnary( CO_VBASE_FETCH, expr ); expr = PtdVbaseFetch( expr , result->vb_offset , result->vb_index , result->delta + offset , vb_exact ); expr->type = base; expr->flags = orig_prop; node = NodeReplace( node, expr ); } else { dup = NULL; if( ! NodePtrNonZero( node ) ) { dup = NodeDupExpr( &node ); } vb_offset = result->vb_offset; vb_index = result->vb_index; node = NodeConvertVirtualPtr( node, base, vb_offset, vb_index ); delta = result->delta; if( delta != 0 ) { node = NodeBinary( CO_DOT, node, NodeOffset( delta ) ); node->type = base; node->flags |= orig_prop; } if( dup != NULL ) { orig = NodeDupExpr( &dup ); node = NodeTestExpr( NodeCompareToZero( orig ), node, dup ); } } *a_expr = node; } if( ref_type != NULL ) { (*a_expr)->flags |= PTF_LVALUE; } }
static PTREE transformVaStart // TRANSFORM TO CO_VASTART OPCODE ( PTREE expr ) // - va_start expression { SYMBOL pre_ellipsis_sym; SYMBOL stop; SYMBOL curr; SYMBOL fn; SCOPE caller_arg_scope; unsigned offset; target_size_t arg_size; PTREE arg1; PTREE arg2; PTREE arg3; PTREE valist; // second argument -- must be pre-... parameter arg1 = expr->u.subtree[1]; arg2 = arg1->u.subtree[0]; arg3 = arg2->u.subtree[0]; pre_ellipsis_sym = PTreeOp( &arg2->u.subtree[1] )->u.symcg.symbol; caller_arg_scope = ScopeFunctionScopeInProgress(); fn = ScopeFunction( caller_arg_scope ); offset = 0; if( ObjModelFunctionReturn( fn->sym_type ) == OMR_CLASS_VAL ) { offset += TARGET_PACKING; } if( SymIsThisMember( fn ) ) { offset += TARGET_PACKING; if( SymCDtorExtraParm( fn ) ) { offset += TARGET_PACKING; } } stop = ScopeOrderedStart( caller_arg_scope ); curr = NULL; for(;;) { curr = ScopeOrderedNext( stop, curr ); if( curr == NULL ) { PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL ); return( expr ); } if( ObjModelArgument( curr->sym_type ) == OMR_CLASS_REF ) { arg_size = TARGET_PACKING; } else { arg_size = CgMemorySize( curr->sym_type ); arg_size += TARGET_PACKING - 1; arg_size &= ~( TARGET_PACKING - 1 ); } offset += arg_size; if( curr == pre_ellipsis_sym ) break; } if( ScopeOrderedNext( stop, curr ) != NULL ) { PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL ); return( expr ); } // third argument -- va_list symbol valist = arg1->u.subtree[1]; arg1->u.subtree[1] = NULL; if( arg3->u.subtree[1]->u.int_constant == 0 ) { // compensate for "void *__alist;" arg in <varargs.h> offset -= TARGET_PACKING; } NodeFreeDupedExpr( expr ); expr = NodeBinary( CO_VASTART, valist, NodeOffset( offset ) ); return expr; }