static TYPE canonicalPtrType( // GET CANONICAL PTR TYPE TYPE type ) // - type { TYPE test; // - used to test type test = PointerTypeEquivalent( type ); if( test == NULL ) { type = canonicalBaseType( type ); } else if( FunctionDeclarationType( test ) ) { type = MakePointerTo( canonicalBaseType( test ) ); } else { type = MakePointerTo( canonicalBaseType( test->of ) ); } return type; }
static TYPE makePointerToModType( // MAKE POINTER TO [OPTIONALLY MODIFIED] TYPE TYPE type, // - base type type_flag flags ) // - flags { if( flags != 0 ) { type = MakeModifiedType( type, flags ); } return( MakePointerTo( type ) ); }
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 void throwBasePtrCnv( // CONVERSION TO A PTR. TO BASE CLASS SCOPE base, // - scope for base class void *dat ) // - control area { THROW_CNV_CTL *ctl; // - control area ctl = dat; if( validateBase( base, ctl ) ) { makeThrowCnv( ctl, MakePointerTo( ScopeClass( base ) ), ctl->offset ); } }
TYPE TypeThisForCall( // GET "THIS" TYPE FOR A CALL PTREE this_node, // - this node SYMBOL sym ) // - function being called { TYPE this_type; // - target type for "this" this_type = SymClass( sym ); if( ExprIsLvalue( this_node ) ) { this_type = MakeReferenceTo( this_type ); } else { this_type = MakePointerTo( this_type ); } return( this_type ); }
static void genInitFiniReference( // GENERATE INIT/FINI REFERENCE TO FUNCTION SYMBOL func, // - function to be called unsigned priority, // - priority NAME name, // - name for reference fe_seg_id tgt_seg ) // - segment # of target segment { SYMBOL init_ref; // - reference to mod-init. function TYPE type; // - used to build type SegmentMarkUsed( tgt_seg ); type = MakePointerTo( func->sym_type ); init_ref = SymCreateFileScope( type , SC_STATIC , SF_INITIALIZED | SF_REFERENCED , name ); init_ref->segid = tgt_seg; if( tgt_seg == SEG_INIT_REF ) { CgFrontInitRef(); } else { CgFrontFiniRef(); } CgFrontDataPtr( IC_DATA_LABEL, init_ref ); #if _INTEL_CPU CgFrontDataPtr( IC_SET_TYPE, GetBasicType( TYP_UCHAR ) ); if( IsBigCode() ) { CgFrontDataInt( IC_DATA_INT, 1 ); } else { CgFrontDataInt( IC_DATA_INT, 0 ); } CgFrontDataInt( IC_DATA_INT, priority ); #elif _CPU == _AXP CgFrontDataPtr( IC_SET_TYPE, GetBasicType( TYP_UINT ) ); CgFrontDataInt( IC_DATA_INT, 0 ); CgFrontDataInt( IC_DATA_INT, priority ); #else #error BAD _CPU #endif CgFrontDataPtr( IC_SET_TYPE, type ); CgFrontDataInt( IC_DATA_PTR_OFFSET, 0 ); CgFrontDataPtr( IC_DATA_PTR_SYM, func ); #if _CPU == 8086 if( !IsBigCode() ) { CgFrontDataInt( IC_DATA_INT, 0 ); } #elif COMP_CFG_COFF == 1 CgFrontDataPtr( IC_SET_TYPE, GetBasicType( TYP_USHORT ) ); CgFrontDataInt( IC_DATA_INT, 0 ); #endif }
static void moduleInitVar( // GENERATE REFERENCE TO MODULE-INIT VAR. SYMBOL var, // - variable bool base_type ) // - base_type or pointer to it { unsigned offset; // - offset to be tested TYPE type; // - type for flags variable type = var->sym_type; offset = type->u.a.array_size - 1; if( offset != 0 ) { CgSetType( GetBasicType( TYP_UINT ) ); CgFrontCodeUint( IC_LEAF_CONST_INT, offset ); CgFrontSymbol( var ); CgSetType( MakePointerTo( type->of ) ); CgFrontCodeUint( IC_OPR_BINARY, CO_PLUS ); } else { CgFrontSymbol( var ); } if( base_type ) { CgSetType( type->of ); } else { CgSetType( MakePointerTo( type->of ) ); } }
TYPE TypeThisSymbol( // GET TYPE OF THIS FOR SYMBOL MEMBER SYMBOL sym, // - symbol bool reference ) // - use reference? { TYPE base; // - return: NULL or TYPE of "this" for symbol type_flag flags; // - flags for "this" pointer base = getThisBaseType( sym ); if( base != NULL ) { flags = FunctionThisFlags( sym ); base = MakeModifiedType( base, flags ); if( reference ) { base = MakeReferenceTo( base ); } else { base = MakePointerTo( base ); } base = MakeModifiedType( base, TF1_CONST ); } return( base ); }
// 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 ); }
bool TypeCompareExclude( TYPE type1, TYPE type2, type_exclude mask ) /******************************************************************/ { TC_STATE state; type_flag flag1; type_flag flag2; void *base1; void *base2; TC_DATA *stack; if( type1 == type2 ) { return( true ); } stack = NULL; state = FOLLOW_OF; for(;;) { if( type1 == NULL || type2 == NULL ) break; // tweak type1 and type2 to ignore minor distinctions type1 = TypeModExtract( type1, &flag1, &base1, mask|TC1_NOT_MEM_MODEL ); type2 = TypeModExtract( type2, &flag2, &base2, mask|TC1_NOT_MEM_MODEL ); if( type1 == NULL || type2 == NULL ) break; if( mask & TC1_PTR_FUN ) { type_flag extra; // tweak type1 and type2 to ignore more major distinction if( ( type1->id == TYP_POINTER ) &&( type2->id == TYP_FUNCTION ) ) { type2 = TypeModFlagsEC( MakePointerTo( type2 ), &extra ); flag2 |= extra; } else if( ( type2->id == TYP_POINTER ) &&( type1->id == TYP_FUNCTION ) ) { type1 = TypeModFlagsEC( MakePointerTo( type1 ), &extra ); flag1 |= extra; } } if( ( type1->id == TYP_CLASS ) && ( type1->flag & TF1_UNBOUND ) && ( type1->of != NULL ) ) { type1 = type1->of; } if( ( type2->id == TYP_CLASS ) && ( type2->flag & TF1_UNBOUND ) && ( type2->of != NULL ) ) { type2 = type2->of; } // compare type1 and type2 flag1 &= ~TF1_MOD_IGNORE; flag2 &= ~TF1_MOD_IGNORE; if( flag1 != flag2 ) { break; } else if( (flag1 & TF1_BASED) && !TypeBasesEqual( flag1, base1, base2 ) ) { break; } else if( type1 == type2 ) { state = FOLLOW_STACK; } else { if( !typeCompareCurrent( &stack, type1, type2, mask ) ) { break; } } // advance the type pointers for( ; ; ) { TC_DATA *top; unsigned arg_index; switch( state ) { case FOLLOW_OF: type1 = type1->of; type2 = type2->of; break; case FOLLOW_STACK: top = stack; if( top == NULL ) { return( true ); } state = FOLLOW_OF; switch( top->flavour ) { case FUNCTION: arg_index = --top->arg_index; type1 = top->type1->u.f.args->type_list[arg_index]; type2 = top->type2->u.f.args->type_list[arg_index]; mask = top->mask; if( arg_index == 0 ) { popTC_DATA( &stack ); } break; case MEMBER_POINTER: type1 = top->type1->u.mp.host; type2 = top->type2->u.mp.host; mask = top->mask; popTC_DATA( &stack ); break; } break; } if( type1 == type2 ) { state = FOLLOW_STACK; continue; } break; } } while( stack != NULL ) { popTC_DATA( &stack ); } return( false ); }
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; }