analcall.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,248 行 · 第 1/3 页
C
1,248 行
}
} else if( OMR_CLASS_VAL
== ObjModelArgument( cl_type ) ) {
passStructOnStack( arg, ERR_CALL_WATCOM );
}
}
}
}
TemporaryClass( old );
}
return( call_expr );
}
#if _CPU == _AXP
static boolean canCoaxVAStartSym( PTREE *parg )
{
PTREE orig_arg;
PTREE arg;
/*
The reason we need this complexity is that there exists C++ code
that uses class templates instantiated on reference types but the
class contains member functions that have ", T v0, ... )" so we
have to forge ahead generating (possibly incorrect code) because
the inline function must be compiled but will never be called!
see COOL\PROPERTY.CPP
*/
orig_arg = PTreeOp( parg );
arg = orig_arg;
if( NodeIsUnaryOp( arg, CO_FETCH ) ) {
arg = arg->u.subtree[0];
}
if( NodeIsUnaryOp( arg, CO_RARG_FETCH ) ) {
arg = arg->u.subtree[0];
}
if( arg->op != PT_SYMBOL ) {
return( FALSE );
}
*parg = NodeComma( orig_arg, PTreeAssign( NULL, arg ) );
return( TRUE );
}
static PTREE convertVaStart( // CONVERT va_start function call
PTREE expr, // - expression
arg_list *alist, // - arguments for caller
TYPE type ) // - function type
{
PTREE arg;
arg_list *plist; // - prototype arguments
PTREE right; // - right operand
if( alist->num_args != 3 ) {
return expr;
}
plist = TypeArgList( type );
// va_list symbol
arg = expr->u.subtree[1];
if( ! arg_convert( arg, plist->type_list[0] ) ) {
PTreeErrorNode( expr );
return expr;
}
// second argument -- must be parameter to current function
// - here we check for symbol
// - we check that it is a parameter in transformVaStart
arg = arg->u.subtree[0];
right = PTreeOp( &arg->u.subtree[1] );
if( right->op != PT_SYMBOL ) {
if( ! canCoaxVAStartSym( &arg->u.subtree[1] ) ) {
PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL );
return expr;
}
}
// third argument -- must be 0 or one
arg = arg->u.subtree[0];
right = PTreeOp( &arg->u.subtree[1] );
if( right->op != PT_INT_CONSTANT ) {
PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL );
return expr;
}
return expr;
}
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;
}
#endif
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 );
}
static intrinsic_mapping* intrinsicMapping // GET INTRINSIC MAPPING
( SYMBOL sym )
{
char *name;
intrinsic_mapping *curr;
name = sym->name->name;
for( curr = mapIntrinsic; ; ++curr ) {
const char* iname = curr->name;
if( iname == NULL ) {
curr = NULL;
break;
}
/* it would be nice to do a pointer compare but we would
need to convert the strings to NAMEs first (AFS) */
if( strcmp( name, iname ) == 0 ) break;
}
return curr;
}
static PTREE insertArg( // INSERT ARGUMENT BEFORE ARGUMENT SEQUENCE
PTREE seq, // - argument sequence
PTREE arg ) // - argument
{
if( seq == NULL ) {
seq = arg;
} else if( arg != NULL ) {
arg->u.subtree[0] = seq;
seq = arg;
}
return seq;
}
static PTREE appendArg( // APPEND ARGUMENT AFTER ARGUMENT SEQUENCE
PTREE seq, // - argument sequence
PTREE arg ) // - argument
{
PTREE last; // - last arg in sequence
if( seq == NULL ) {
seq = arg;
} else if( arg != NULL ) {
for( last = seq
; last->u.subtree[0] != NULL
; last = last->u.subtree[0] );
last->u.subtree[0] = arg;
}
return seq;
}
PC_CALLIMPL PcCallImpl( // OBTAIN PC CALL IMPLEMENTATION
TYPE ftype ) // - function type
{
PC_CALLIMPL retn; // - type of call implemented
ftype = TypedefModifierRemove( ftype );
if( TypeHasReverseArgs( ftype ) ) {
if( ftype->flag & TF1_PLUSPLUS ) {
retn = CALL_IMPL_REV_CPP;
} else {
retn = CALL_IMPL_REV_C;
}
} else if( TypeHasEllipsisArg( ftype ) ) {
if( ftype->flag & TF1_PLUSPLUS ) {
retn = CALL_IMPL_ELL_CPP;
} else {
retn = CALL_IMPL_ELL_C;
}
} else {
if( ftype->flag & TF1_PLUSPLUS ) {
retn = CALL_IMPL_CPP;
} else {
retn = CALL_IMPL_C;
}
}
return retn;
}
static PTREE insertRetnCopy( // INSERT COPY OF RETURN ON STACK
PTREE callexpr, // - call expression
PTREE temp ) // - optional temporary
{
if( temp != NULL ) {
PTreeOpLeft( callexpr )->flags |= PTF_MEMORY_EXACT;
callexpr->flags |= PTF_MEMORY_EXACT;
callexpr = NodeCopyClassObject( temp, callexpr );
}
return callexpr;
}
static PTREE insertCppRetnArg( // INSERT C++ RETURN ARGUMENT
PTREE arglist, // - argument list
PTREE retnnode, // - return node
OMR return_kind ) // - kind of return
{
if( return_kind == OMR_CLASS_REF ) {
retnnode->flags |= PTF_ARG_RETURN;
arglist = insertArg( arglist, NodeArg( retnnode ) );
}
return arglist;
}
static PTREE insertCppRetnCopy( // INSERT C++ RETURN COPY
PTREE callnode, // - node for call
PTREE retnnode, // - return node
OMR return_kind ) // - kind of return
{
switch( return_kind ) {
case OMR_CLASS_VAL :
callnode = insertRetnCopy( callnode, retnnode );
break;
case OMR_CLASS_REF :
callnode->flags |= PTF_CLASS_RVREF;
break;
}
return callnode;
}
static PTREE insertCDtor( // INSERT CDTOR NODE INTO CALL LIST
PTREE seq, // - argument sequence
PTREE arg ) // - argument
{
PTREE* r_val; // - reference[ arg value ]
PTREE val; // - arg value
if( arg != NULL ) {
r_val = PTreeRefRight( arg );
val = *r_val;
if( val->op == PT_INT_CONSTANT ) {
PTREE new_val = NodeIcUnsigned( IC_CDARG_VAL
, val->u.uint_constant );
new_val->type = val->type;
*r_val = new_val;
PTreeFree( val );
}
}
return insertArg( seq, arg );
}
PTREE CallArgsArrange( // ARRANGE CALL ARGUMENTS
TYPE ftype, // - function type
PTREE callnode, // - node for call
PTREE userargs, // - user arguments
PTREE thisnode, // - this node
PTREE cdtor, // - cdtor node (ignored when thisnode==NULL)
PTREE retnnode ) // - return node (for struct return)
{
PTREE arglist; // - argument list under construction
OMR return_kind; // - type of return
if( thisnode != NULL ) {
thisnode->flags |= PTF_ARG_THIS;
}
return_kind = ObjModelFunctionReturn( ftype );
switch( PcCallImpl( ftype ) ) {
case CALL_IMPL_REV_C :
return_kind = OMR_CLASS_VAL;
// drops thru
case CALL_IMPL_REV_CPP :
arglist = insertCDtor( thisnode, cdtor );
arglist = insertCppRetnArg( arglist, retnnode, return_kind );
arglist = appendArg( userargs, arglist );
break;
case CALL_IMPL_ELL_C :
case CALL_IMPL_C :
return_kind = OMR_CLASS_VAL;
// drops thru
case CALL_IMPL_ELL_CPP :
case CALL_IMPL_CPP :
arglist = insertCppRetnArg( userargs, retnnode, return_kind );
arglist = insertCDtor( arglist, cdtor );
arglist = insertArg( arglist, thisnode );
break;
}
callnode->u.subtree[1] = arglist;
callnode = insertCppRetnCopy( callnode, retnnode, return_kind );
return callnode;
}
static void outputCallTriggeredWarning( PTREE expr, SYMBOL sym )
{
MSG_NUM msg;
char *name;
msg = ERR_NULL;
name = sym->name->name;
if( name == CppSpecialName( SPECIAL_BEGINTHREAD ) ) {
msg = WARN_MUST_BE_MULTITHREADED;
} else if( name == CppSpecialName( SPECIAL_BEGINTHREADEX ) ) {
msg = WARN_MUST_BE_MULTITHREADED;
}
if( msg != ERR_NULL ) {
switch( msg ) {
case WARN_MUST_BE_MULTITHREADED:
if( !CompFlags.bm_switch_used ) {
PTreeErrorExprName( expr, msg, name );
}
break;
DbgDefault( "unexpected message number" );
}
}
}
PTREE AnalyseCall( // ANALYSIS FOR CALL
PTREE expr, // - call expression
CALL_DIAG *diagnostic ) // - diagnostics used for function problems
{
PTREE *r_args; // - reference( arguments )
PTREE *r_func; // - reference( function )
PTREE *ptlist; // - nodes for arguments
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?