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 boolean passStructOnStack( // PASS A STRUCT/CLASS ON STACK PTREE arg, // - argument (CO_LIST) unsigned warning ) // - internal-data warning { PTREE right; // - right operand TYPE type; // - class type right = NodeRvalue( arg->u.subtree[1] ); type = right->type; if( right->flags & PTF_CLASS_RVREF ) { if( right->op != PT_ERROR ) { PTREE temp = NodeTemporary( type ); right = ClassDefaultCopyDiag( temp, right, &diagEllConv ); if( right->op != PT_ERROR ) { right = NodeDtorExpr( right, temp->u.symcg.symbol ); if( right->op != PT_ERROR ) { right->type = type; right = NodeFetch( right ); right->flags &= ~PTF_LVALUE; } } } if( right->op == PT_ERROR ) { arg->u.subtree[1] = right; PTreeErrorNode( arg ); return FALSE; } } arg_finish( right, arg ); if( TypeHasSpecialFields( type ) ) { PTreeWarnExpr( arg, warning ); } return TRUE; }
// 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 ); }
static boolean convertEllipsisArg(// CONVERT AN ELLIPSIS (...) ARGUMENT PTREE arg ) // - argument { boolean retn; // - return: TRUE ==> ok PTREE right; // - argument PTREE afun; // - &[ function ] TYPE type; // - node type switch( NodeAddrOfFun( PTreeOpRight( arg ), &afun ) ) { case ADDR_FN_MANY : case ADDR_FN_MANY_USED : PTreeErrorExpr( arg->u.subtree[1], ERR_ELLIPSE_ADDR_OVERLOAD ); retn = FALSE; break; default : right = NodeRvalue( arg->u.subtree[1] ); arg->u.subtree[1] = right; type = TypedefModifierRemove( right->type ); switch( type->id ) { case TYP_CHAR : case TYP_SCHAR : case TYP_UCHAR : case TYP_SSHORT : case TYP_WCHAR : case TYP_USHORT : type = TypeUnArithResult( type ); right = NodeConvert( type, right ); arg_finish( right, arg ); retn = TRUE; break; case TYP_FLOAT : type = GetBasicType( TYP_DOUBLE ); right = NodeConvert( type, right ); arg_finish( right, arg ); retn = TRUE; break; case TYP_ARRAY : type = PointerTypeForArray( right->type ); right = NodeConvert( type, right ); arg_finish( right, arg ); retn = TRUE; break; case TYP_MEMBER_POINTER : ConvertMembPtrConst( &arg->u.subtree[1] ); arg_fillout( arg ); retn = TRUE; break; case TYP_POINTER : if( NULL == FunctionDeclarationType( type->of ) ) { type_flag def_flags; type_flag act_flags; type_flag arg_flags; TYPE base_type; PTREE cnv; base_type = TypeGetActualFlags( type->of, &arg_flags ); act_flags = arg_flags & TF1_MEM_MODEL; def_flags = DefaultMemoryFlag( type->of ); if( ( ( def_flags & TF1_FAR ) &&( act_flags != TF1_HUGE ) &&( act_flags != TF1_FAR ) ) ||( ( def_flags & TF1_HUGE ) &&( act_flags != TF1_HUGE ) ) ) { type = MakeModifiedType( base_type , ( arg_flags & ~TF1_MEM_MODEL ) | def_flags ); type = MakePointerTo( type ); cnv = CastImplicit( arg->u.subtree[1] , type , CNV_EXPR , NULL ); arg->u.subtree[1] = cnv; DbgVerify( PT_ERROR != cnv->op , "convertEllipsisArg -- failed ptr.cnv" ); arg_fillout( arg ); retn = TRUE; } else { arg_fillout( arg ); retn = TRUE; } } else { arg_fillout( arg ); retn = TRUE; } break; case TYP_CLASS : retn = passStructOnStack( arg, WARN_ELLIPSIS_CLASS_ARG ); break; default : arg_fillout( arg ); retn = TRUE; break; } break; } return retn; }