local void InitArray( TYPEPTR typ, TYPEPTR ctyp ) { unsigned long n; unsigned long m; unsigned long *pm; unsigned long array_size; unsigned long elem_size; array_size = TypeSize( typ ); n = 0; pm = &m; for( ;; ) { m = n; pm = DesignatedInit( typ, ctyp, pm ); if( pm == NULL ) break; if( m != n ) { elem_size = SizeOfArg( typ->object ); if( typ->u.array->unspecified_dim && m > array_size ) { RelSeekBytes( ( array_size - n ) * elem_size ); ZeroBytes( (m - array_size) * elem_size ); } else { RelSeekBytes( ( m - n ) * elem_size ); } n = m; } n++; if( n > array_size ) { if( !typ->u.array->unspecified_dim ) break; array_size = n; /* clear out the new element just in case */ elem_size = SizeOfArg( typ->object ); ZeroBytes( elem_size ); RelSeekBytes( -elem_size ); } InitSymData( typ->object, ctyp, 1 ); if( CurToken == T_EOF ) break; if( CurToken == T_RIGHT_BRACE ) break; if( DesignatedInSubAggregate( typ->object->decl_type ) ) continue; if( n < array_size || typ == ctyp || typ->u.array->unspecified_dim ) { MustRecog( T_COMMA ); } if( CurToken == T_RIGHT_BRACE ) break; } if( typ->u.array->unspecified_dim ) { typ->u.array->dimension = array_size; } if( array_size > n ) { RelSeekBytes( ( array_size - n ) * SizeOfArg( typ->object ) ); } }
void SetFarHuge( SYMPTR sym, bool report ) { TYPEPTR typ; type_modifiers attrib; target_size size; #if _CPU != 8086 /* unused parameters */ (void)report; #endif #if _CPU == 8086 if( sym->attribs.declspec == DECLSPEC_DLLIMPORT || sym->attribs.declspec == DECLSPEC_DLLEXPORT ) { sym->mods |= FLAG_FAR; } else if( sym->mods & FLAG_EXPORT ) { sym->mods |= FLAG_FAR; } #endif size = SizeOfArg( sym->sym_type ); if( TargetSwitches & BIG_DATA ) { attrib = sym->mods; if( (attrib & MASK_ALL_MEM_MODELS) == 0 ) { if( size == 0 ) { /* unspecified array size */ if( sym->attribs.stg_class == SC_EXTERN ) { typ = sym->sym_type; if( typ->decl_type == TYPE_ARRAY ) { attrib |= FLAG_FAR; } } } else if( size > DataThreshold ) { attrib |= FLAG_FAR; } else if( CompFlags.strings_in_code_segment && ( sym->mods & FLAG_CONST ) ) { attrib |= FLAG_FAR; } #if _CPU == 8086 if( (attrib & FLAG_FAR) && size > 0x10000 ) { attrib &= ~FLAG_FAR; attrib |= FLAG_HUGE; } #endif sym->mods = attrib; } } #if _CPU == 8086 if( report && size > 0x10000 && (sym->mods & FLAG_HUGE) == 0 ) { SetErrLoc( &sym->src_loc ); CErr1( ERR_VAR_TOO_LARGE ); InitErrLoc(); } #endif }
void SetFarHuge( SYMPTR sym, int report ) { TYPEPTR typ; type_modifiers attrib; unsigned long size; report = report; /* in case not used */ #if _CPU == 8086 if( sym->declspec == DECLSPEC_DLLIMPORT || sym->declspec == DECLSPEC_DLLEXPORT ) { /* 16-dec-94 */ sym->attrib |= FLAG_FAR; } else if( sym->attrib & FLAG_EXPORT ) { sym->attrib |= FLAG_FAR; } #endif size = SizeOfArg( sym->sym_type ); if( TargetSwitches & BIG_DATA ) { attrib = sym->attrib; if( (attrib & MASK_ALL_MEM_MODELS) == 0 ) { if( size == 0 ) { /* unspecified array size */ if( sym->stg_class == SC_EXTERN ) { typ = sym->sym_type; if( typ->decl_type == TYPE_ARRAY ) { attrib |= FLAG_FAR; } } } else if( size > DataThreshold ) { attrib |= FLAG_FAR; } else if( CompFlags.strings_in_code_segment && ( sym->attrib & FLAG_CONST ) ) { attrib |= FLAG_FAR; } #if _CPU == 8086 if( (attrib & FLAG_FAR) && size > 0x10000 ) { attrib &= ~FLAG_FAR; attrib |= FLAG_HUGE; } #endif sym->attrib = attrib; } } #if _CPU == 8086 if( report && size > 0x10000 && !(sym->attrib & FLAG_HUGE) ) { SetErrLoc( &sym->src_loc ); CErr1( ERR_VAR_TOO_LARGE ); InitErrLoc(); } #endif }
/* Initialize struct or union fields */ local void InitStructUnion( TYPEPTR typ, TYPEPTR ctyp, FIELDPTR field ) { TYPEPTR ftyp; unsigned long n; unsigned long offset; n = typ->u.tag->size; /* get full size of the struct or union */ offset = 0; for( ;; ) { field = DesignatedInit( typ, ctyp, field ); if( field == NULL ) break; /* The first field might not start at offset 0; 19-mar-91 */ if( field->offset != offset ) { /* 14-dec-88 */ RelSeekBytes( field->offset - offset ); } ftyp = field->field_type; offset = field->offset + SizeOfArg( ftyp ); /* 19-dec-88 */ if( ftyp->decl_type == TYPE_FIELD || ftyp->decl_type == TYPE_UFIELD ) { field = InitBitField( field ); } else { InitSymData( ftyp, ctyp, 1 ); field = field->next_field; } if( typ->decl_type == TYPE_UNION ) { if( offset != n ) { ZeroBytes( n - offset ); /* pad the rest */ } offset = n; /* designated initializers may still override this field */ field = NULL; } if( CurToken == T_EOF ) break; if( CurToken == T_RIGHT_BRACE ) break; if( DesignatedInSubAggregate( ftyp->decl_type ) ) continue; if( field != NULL || typ == ctyp ) { MustRecog( T_COMMA ); } if( CurToken == T_RIGHT_BRACE ) break; } RelSeekBytes( (unsigned)n - offset ); }
void InitSymData( TYPEPTR typ, TYPEPTR ctyp, int level ) { TOKEN token; unsigned long size; SKIP_TYPEDEFS( typ ); if( typ->decl_type == TYPE_ENUM ) typ = typ->object; /* 07-nov-90 */ token = CurToken; if( CurToken == T_LEFT_BRACE ) { NextToken(); if( CurToken == T_RIGHT_BRACE || CurToken == T_COMMA ) { CErr1( ERR_EMPTY_INITIALIZER_LIST ); } } size = SizeOfArg( typ ); switch( typ->decl_type ) { case TYPE_ARRAY: if( CharArray( typ->object ) ) { InitCharArray( typ ); } else if( WCharArray( typ->object ) ) { InitWCharArray( typ ); } else { if( token == T_LEFT_BRACE ) { ctyp = typ; } else if( level == 0 ) { CErr1( ERR_NEED_BRACES ); } if( typ == ctyp ) { /* initialize new current type */ /* first zero out the whole array; otherwise overlapping fields caused by designated initializers will make life very difficult */ ZeroBytes( size ); RelSeekBytes( -size ); } InitArray( typ, ctyp ); } break; case TYPE_FCOMPLEX: case TYPE_DCOMPLEX: case TYPE_LDCOMPLEX: case TYPE_STRUCT: if( token == T_LEFT_BRACE ) { ctyp = typ; } else if( level == 0 ) { CErr1( ERR_NEED_BRACES ); } if( typ == ctyp ) { /* initialize new current type */ /* zero out all fields; otherwise overlapping fields caused by designated initializers will make life very difficult */ ZeroBytes( size ); RelSeekBytes( -size ); } InitStruct( typ, ctyp ); break; case TYPE_UNION: if( token == T_LEFT_BRACE ) { ctyp = typ; } else if( level == 0 ) { CErr1( ERR_NEED_BRACES ); } InitUnion( typ, ctyp ); break; case TYPE_CHAR: case TYPE_UCHAR: case TYPE_BOOL: case TYPE_SHORT: case TYPE_USHORT: case TYPE_INT: case TYPE_UINT: case TYPE_LONG: case TYPE_ULONG: case TYPE_POINTER: StorePointer( typ, size ); break; case TYPE_LONG64: case TYPE_ULONG64: StoreInt64( typ ); break; case TYPE_FLOAT: case TYPE_DOUBLE: case TYPE_FIMAGINARY: case TYPE_DIMAGINARY: StoreFloat( typ->decl_type, size ); break; case TYPE_LONG_DOUBLE: case TYPE_LDIMAGINARY: //StoreFloat( typ->decl_type, size ); StoreFloat( TYPE_DOUBLE, size ); break; default: break; } if( token == T_LEFT_BRACE ) { if( CurToken == T_COMMA ) { NextToken(); } if( CurToken != T_RIGHT_BRACE ) { CErr1( ERR_TOO_MANY_INITS ); } while( CurToken != T_RIGHT_BRACE ) { if( CurToken == T_EOF ) break; if( CurToken == T_SEMI_COLON )break; if( CurToken == T_LEFT_BRACE )break; NextToken(); } MustRecog( T_RIGHT_BRACE ); } }
local FIELDPTR InitBitField( FIELDPTR field ) { TYPEPTR typ; unsigned long value; unsigned long size; uint64 value64; unsigned long bit_value; unsigned long offset; TOKEN token; int is64bit; token = CurToken; if( CurToken == T_LEFT_BRACE ) NextToken(); typ = field->field_type; size = SizeOfArg( typ ); is64bit = ( typ->u.f.field_type == TYPE_LONG64 ) || ( typ->u.f.field_type == TYPE_ULONG64 ); if( is64bit ) U32ToU64( 0, &value64 ); offset = field->offset; value = 0; while( typ->decl_type == TYPE_FIELD || typ->decl_type == TYPE_UFIELD ) { bit_value = 0; if( CurToken != T_RIGHT_BRACE ) bit_value = ConstExpr(); if( typ->u.f.field_type == TYPE_BOOL ) { if( bit_value != 0 ) { bit_value = 1; } } else { ChkConstant( bit_value, BitMask[typ->u.f.field_width - 1] ); bit_value &= BitMask[typ->u.f.field_width - 1]; } if( is64bit ) { uint64 tmp; U32ToU64( bit_value, &tmp ); U64ShiftL( &tmp, typ->u.f.field_start, &tmp ); value64.u._32[L] |= tmp.u._32[L]; value64.u._32[H] |= tmp.u._32[H]; } else { value |= bit_value << typ->u.f.field_start; } field = field->next_field; if( field == NULL ) break; if( field->offset != offset ) break; /* bit field done */ typ = field->field_type; if( CurToken == T_EOF ) break; if( CurToken != T_RIGHT_BRACE ) { MustRecog( T_COMMA ); } } if( is64bit ) { StoreIValue64( typ->u.f.field_type, value64 ); } else { StoreIValue( typ->u.f.field_type, value, size ); } if( token == T_LEFT_BRACE ) { if( CurToken == T_COMMA ) NextToken(); MustRecog( T_RIGHT_BRACE ); } return( field ); }
local void AddrFold( TREEPTR tree, addrfold_info *info ) { // Assume tree has been const folded SYM_ENTRY sym; long offset = 0; switch( tree->op.opr ) { case OPR_PUSHINT: info->state = IS_ADDR; info->offset = tree->op.long_value; if( info->offset != 0 ) CompFlags.non_zero_data = 1; break; case OPR_PUSHFLOAT: info->state = IS_ADDR; if( tree->op.float_value->len != 0 ) { info->offset = (long)atof( tree->op.float_value->string ); } else { #ifdef _LONG_DOUBLE_ long_double ld; double d; ld = tree->op.float_value->ld; __LDFD( (long_double near *)&ld, (double near *)&d ); info->offset = (long)d; #else info->offset = (long)tree->op.float_value->ld.value; #endif } if( info->offset != 0 ) CompFlags.non_zero_data = 1; break; case OPR_PUSHSTRING: info->state = IS_ADDR; if( info->addr_set ) { info->is_error = TRUE; } info->addr_set = TRUE; info->is_str = TRUE; info->str_h = tree->op.string_handle; tree->op.string_handle->ref_count++; CompFlags.non_zero_data = 1; break; case OPR_PUSHADDR: info->state = IS_ADDR; case OPR_PUSHSYM: if( info->addr_set ) { info->is_error = TRUE; } info->addr_set = TRUE; info->is_str = FALSE; SymGet( &sym, tree->op.sym_handle ); info->sym_h = tree->op.sym_handle; CompFlags.non_zero_data = 1; if( sym.stg_class == SC_AUTO ) { info->is_error = TRUE; } break; case OPR_INDEX: if( tree->right->op.opr == OPR_PUSHINT ) { AddrFold( tree->left, info ); offset = tree->right->op.long_value; } else if( tree->left->op.opr == OPR_PUSHINT ) { AddrFold( tree->right, info ); offset = tree->left->op.long_value; } else { info->is_error = TRUE; } if( info->state == IS_VALUE ) { // must be foldable info->is_error = TRUE; } info->offset += offset * SizeOfArg( tree->expr_type ); if( tree->op.flags & OPFLAG_RVALUE ) { info->state = IS_VALUE; } break; case OPR_ADD: case OPR_SUB: if( tree->right->op.opr == OPR_PUSHINT ) { AddrFold( tree->left, info ); if( tree->op.opr == OPR_ADD ) { info->offset = info->offset+tree->right->op.long_value; } else { info->offset = info->offset-tree->right->op.long_value; } } else if( tree->left->op.opr == OPR_PUSHINT ) { AddrFold( tree->right, info ); if( tree->op.opr == OPR_ADD ) { info->offset = tree->left->op.long_value+info->offset; } else { info->offset = tree->left->op.long_value-info->offset; } } else { info->is_error = TRUE; } if( info->state == IS_VALUE ) { // must be foldable info->is_error = TRUE; } break; case OPR_ADDROF: AddrFold( tree->right, info ); info->state = IS_ADDR; CompFlags.non_zero_data = 1; break; case OPR_ARROW: AddrFold( tree->left, info ); if( info->state == IS_VALUE ) { // must be foldable info->is_error = TRUE; } info->offset += tree->right->op.long_value; if( tree->op.flags & OPFLAG_RVALUE ) { info->state = IS_VALUE; } break; case OPR_POINTS: AddrFold( tree->left, info ); if( info->state == IS_VALUE ) { // must be foldable info->is_error = TRUE; } if( tree->op.flags & OPFLAG_RVALUE ) { info->state = IS_VALUE; } break; case OPR_DOT: AddrFold( tree->left, info ); info->offset += tree->right->op.long_value; CompFlags.non_zero_data = 1; if( tree->op.flags & OPFLAG_RVALUE ) { info->state = IS_VALUE; } break; case OPR_CONVERT: //should check for pointer to smaller case OPR_CONVERT_PTR: AddrFold( tree->right, info ); break; case OPR_ERROR: // error has already been issued break; default: info->is_error = TRUE; break; } }
local void InitArrayVar( SYMPTR sym, SYM_HANDLE sym_handle, TYPEPTR typ ) { unsigned i; unsigned n; TYPEPTR typ2; SYM_HANDLE sym2_handle; SYM_ENTRY sym2; TREEPTR opnd; TREEPTR value; TOKEN token; typ2 = typ->object; SKIP_TYPEDEFS( typ2 ); switch( typ2->decl_type ) { case TYPE_CHAR: case TYPE_UCHAR: case TYPE_SHORT: case TYPE_USHORT: case TYPE_INT: case TYPE_UINT: case TYPE_LONG: case TYPE_ULONG: case TYPE_LONG64: case TYPE_ULONG64: case TYPE_FLOAT: case TYPE_DOUBLE: case TYPE_POINTER: case TYPE_LONG_DOUBLE: case TYPE_FIMAGINARY: case TYPE_DIMAGINARY: case TYPE_LDIMAGINARY: case TYPE_BOOL: NextToken(); // skip over T_LEFT_BRACE if( CharArray( typ->object ) ) { sym2_handle = MakeNewSym( &sym2, 'X', typ, SC_STATIC ); sym2.flags |= SYM_INITIALIZED; if( sym2.u.var.segment == 0 ) { /* 01-dec-91 */ SetFarHuge( &sym2, 0 ); SetSegment( &sym2 ); SetSegAlign( &sym2 ); /* 02-feb-92 */ } SymReplace( &sym2, sym2_handle ); GenStaticDataQuad( sym2_handle ); InitCharArray( typ ); AssignAggregate( VarLeaf( sym, sym_handle ), VarLeaf( &sym2, sym2_handle ), typ ); } else if( WCharArray( typ->object ) ) { sym2_handle = MakeNewSym( &sym2, 'X', typ, SC_STATIC ); sym2.flags |= SYM_INITIALIZED; if( sym2.u.var.segment == 0 ) { /* 01-dec-91 */ SetFarHuge( &sym2, 0 ); SetSegment( &sym2 ); SetSegAlign( &sym2 ); /* 02-feb-92 */ } SymReplace( &sym2, sym2_handle ); GenStaticDataQuad( sym2_handle ); InitWCharArray( typ ); AssignAggregate( VarLeaf( sym, sym_handle ), VarLeaf( &sym2, sym2_handle ), typ ); } else { n = typ->u.array->dimension; i = 0; for( ;; ) { // accept some C++ { {1},.. } token = CurToken; if( token == T_LEFT_BRACE ) NextToken(); opnd = VarLeaf( sym, sym_handle ); value = CommaExpr(); opnd = ExprNode( opnd, OPR_INDEX, IntLeaf( i ) ); opnd->expr_type = typ2; opnd->op.result_type = typ2; AddStmt( AsgnOp( opnd, T_ASSIGN_LAST, value ) ); if( token == T_LEFT_BRACE ) MustRecog( T_RIGHT_BRACE ); ++i; if( CurToken == T_EOF ) break; if( CurToken == T_RIGHT_BRACE )break; MustRecog( T_COMMA ); if( CurToken == T_RIGHT_BRACE )break; if( i == n ) { CErr1( ERR_TOO_MANY_INITS ); } } if( typ->u.array->unspecified_dim ) { typ->u.array->dimension = i; } else { while( i < n ) { value = IntLeaf( 0 ); opnd = VarLeaf( sym, sym_handle ); opnd = ExprNode( opnd, OPR_INDEX, IntLeaf( i ) ); opnd->expr_type = typ2; opnd->op.result_type = typ2; AddStmt( AsgnOp( opnd, T_ASSIGN_LAST, value ) ); ++i; } } } MustRecog( T_RIGHT_BRACE ); break; case TYPE_FCOMPLEX: case TYPE_DCOMPLEX: case TYPE_LDCOMPLEX: case TYPE_STRUCT: case TYPE_UNION: if( SimpleStruct( typ2 ) ) { unsigned base; unsigned size; NextToken(); // skip over T_LEFT_BRACE n = typ->u.array->dimension; i = 0; base = 0; size = SizeOfArg( typ2 ); for( ;; ) { token = CurToken; if( token == T_LEFT_BRACE ) { NextToken(); } InitStructVar( base, sym, sym_handle, typ2 ); if( token == T_LEFT_BRACE ) { MustRecog( T_RIGHT_BRACE ); } ++i; if( CurToken == T_EOF ) break; if( CurToken == T_RIGHT_BRACE ) break; MustRecog( T_COMMA ); if( CurToken == T_RIGHT_BRACE ) break; if( i == n ) { CErr1( ERR_TOO_MANY_INITS ); } base += size; } if( typ->u.array->unspecified_dim ) { typ->u.array->dimension = i; } else { while( i < n ) { // mop up base += size; InitStructVar( base, sym, sym_handle, typ2 ); ++i; } } NextToken(); // skip over T_RIGHT_BRACE break; } default: AggregateVarDeclEquals( sym, sym_handle ); break; } }
void SetSegment( SYMPTR sym ) { segment_list *seg; target_size size; #if _CPU == 8086 if( (sym->mods & FLAG_FAR) && CompFlags.zc_switch_used ) { if( CONSTANT( sym->mods ) || (sym->attribs.stg_class == SC_STATIC && (sym->flags & SYM_TEMP)) ) { sym->u.var.segid = SEG_CODE; return; } } #elif _CPU == 386 if( !CompFlags.rent ) { if( (sym->mods & FLAG_FAR) || (TargetSwitches & FLAT_MODEL) ) { if( CONSTANT( sym->mods ) && CompFlags.zc_switch_used ) { sym->u.var.segid = SEG_CODE; return; } if( (sym->attribs.stg_class == SC_STATIC) && (sym->flags & SYM_TEMP) ) { sym->u.var.segid = SEG_CODE; return; } } } #endif if( sym->mods & ( FLAG_FAR | FLAG_HUGE ) ) { size = SizeOfArg( sym->sym_type ); seg = NULL; #if _CPU == 8086 if( size < 0x10000 ) { for( seg = SegListHead; seg != NULL; seg = seg->next_segment ) { if( seg->size_left >= size ) { break; } } } #else seg = SegListHead; #endif if( seg == NULL ) { if( SegListHead == NULL ) { SegListHead = CMemAlloc( sizeof( segment_list ) ); seg = SegListHead; } else { for( seg = SegListHead; seg->next_segment; ) { seg = seg->next_segment; } seg->next_segment = CMemAlloc( sizeof( segment_list ) ); seg = seg->next_segment; } seg->segid = SegmentNum++; #if _CPU == 8086 if( size > 0xFFFF ) { while( size > 0x0FFFF ) { /* while >= 64K */ ++SegmentNum; size -= 0x10000; } seg->size_left = 0; } else { seg->size_left = 0x10000 - size; } #endif } else { seg->size_left -= size; } sym->u.var.segid = seg->segid; } else { sym->u.var.segid = SymSegId( sym ); } }
static aux_info *InfoLookup( SYMPTR sym ) { char *name; aux_info *inf; aux_entry *ent; name = sym->name; inf = &DefaultInfo; /* assume default */ if( name == NULL ) return( inf ); ent = AuxLookup( name ); if( ent != NULL ) inf = ent->info; if( ( ent == NULL ) || (sym->flags & SYM_INTRINSIC) ) { if( sym->flags & SYM_DEFINED ) return( inf ); if( (sym->flags & SYM_INTRINSIC) == 0 ) { if( memcmp( name, "_inline_", 8 ) != 0 ) return( inf ); name += 8; } #if ( _CPU == 8086 ) || ( _CPU == 386 ) { const inline_funcs *ifunc; ifunc = IF_Lookup( name ); if( ifunc == NULL ) return( inf ); #if ( _CPU == 8086 ) if( HW_CEqual( ifunc->returns, HW_DX_AX ) || HW_CEqual( ifunc->returns, HW_DS_SI ) || HW_CEqual( ifunc->returns, HW_ES_DI ) || HW_CEqual( ifunc->returns, HW_CX_DI ) ) { if( SizeOfArg( sym->sym_type->object ) != 4 ) { #else if( HW_CEqual( ifunc->returns, HW_DX_AX ) || HW_CEqual( ifunc->returns, HW_DS_ESI ) || HW_CEqual( ifunc->returns, HW_ES_EDI ) || HW_CEqual( ifunc->returns, HW_CX_DI ) ) { if( SizeOfArg( sym->sym_type->object ) != 6 ) { #endif return( inf ); } } inf = &InlineInfo; inf->cclass = (WatcallInfo.cclass & FAR_CALL) | MODIFY_EXACT; if( (sym->flags & SYM_INTRINSIC) && ( ent != NULL ) ) inf->cclass |= ent->info->cclass; inf->code = ifunc->code; inf->parms = ifunc->parms; inf->returns = ifunc->returns; #if ( _CPU == 8086 ) if( !HW_CEqual( inf->returns, HW_AX ) && !HW_CEqual( inf->returns, HW_EMPTY ) ) { #else if( !HW_CEqual( inf->returns, HW_EAX ) && !HW_CEqual( inf->returns, HW_EMPTY ) ) { #endif inf->cclass |= SPECIAL_RETURN; } HW_CAsgn( inf->streturn, HW_EMPTY ); inf->save = ifunc->save; inf->objname = WatcallInfo.objname; inf->use = 1; } #endif } return( inf ); } aux_info *FindInfo( SYMPTR sym, SYM_HANDLE sym_handle ) { SYM_ENTRY sym_typedef; aux_entry *ent; TYPEPTR typ; aux_info *inf; inf = &DefaultInfo; /* assume default */ if( sym_handle == SYM_NULL ) return( inf ); SymGet( sym, sym_handle ); #if _CPU == 386 if( (sym_handle == SymSTOSB) || (sym_handle == SymSTOSD) ) { return( &STOSBInfo ); } else if( sym_handle == SymFinally ) { InlineInfo = WatcallInfo; InlineInfo.code = (byte_seq *)&FinallyCode; return( &InlineInfo ); } else if( sym_handle == SymTryFini ) { InlineInfo = WatcallInfo; InlineInfo.parms = TryFiniParms; InlineInfo.code = (byte_seq *)&TryFiniCode; return( &InlineInfo ); } #endif if( (sym->flags & SYM_TEMP) == 0 ) { /* not an indirect func call*/ inf = InfoLookup( sym ); } if( inf == &DefaultInfo ) { typ = sym->sym_type; SKIP_DUMMY_TYPEDEFS( typ ); if( typ->decl_type == TYPE_TYPEDEF ) { SymGet( &sym_typedef, typ->u.typedefn ); if( sym_typedef.name != NULL ) { ent = AuxLookup( sym_typedef.name ); if( ent != NULL ) { inf = ent->info; } } } } #if _CPU == 386 if( (inf->flags & AUX_FLAG_FAR16) || (sym->mods & FLAG_FAR16) ) { if( (sym->mods & MASK_LANGUAGES) == LANG_PASCAL || (inf->cclass & REVERSE_PARMS) ) { return( &Far16PascalInfo ); } else { return( &Far16CdeclInfo ); } } #endif return( inf ); } bool FunctionAborts( SYMPTR sym, SYM_HANDLE sym_handle ) { aux_entry *ent; if( sym_handle != SYM_NULL ) { SymGet( sym, sym_handle ); ent = AuxLookup( SymName( sym, sym_handle ) ); if( ent != NULL ) { if( ent->info->cclass & SUICIDAL ) { return( TRUE ); } } } return( FALSE ); } call_class GetCallClass( SYM_HANDLE sym_handle ) { aux_info *inf; SYM_ENTRY sym; call_class cclass; cclass = DefaultInfo.cclass; if( sym_handle != SYM_NULL ) { inf = FindInfo( &sym, sym_handle ); if( sym.flags & SYM_FUNCTION ) { if( inf != &DefaultInfo ) { cclass = inf->cclass; } else { cclass = GetLangInfo( sym.mods )->cclass; #if _CPU == 8086 if( TargSys == TS_WINDOWS ) { if( sym.mods & (LANG_CDECL | LANG_PASCAL) ) { cclass |= FAT_WINDOWS_PROLOG; } } #endif } #if ( _CPU == 8086 ) || ( _CPU == 386 ) if( CompFlags.emit_names ) { cclass |= EMIT_FUNCTION_NAME; } if( sym.mods & FLAG_FAR ) { cclass |= FAR_CALL; if( sym.mods & FLAG_NEAR ) { cclass |= INTERRUPT; } } else if( sym.mods & FLAG_NEAR ) { cclass &= ~ FAR_CALL; } #endif #ifdef DLL_EXPORT if( sym.mods & FLAG_EXPORT ) { cclass |= DLL_EXPORT; } #endif #ifdef LOAD_DS_ON_ENTRY if( sym.mods & FLAG_LOADDS ) { #if 0 if( TargSys == TS_WINDOWS ) { cclass |= FAT_WINDOWS_PROLOG; } else { cclass |= LOAD_DS_ON_ENTRY; } #else cclass |= LOAD_DS_ON_ENTRY; #endif } #endif #ifdef MAKE_CALL_INLINE if( IsInLineFunc( sym_handle ) ) { cclass |= MAKE_CALL_INLINE; } #endif if( VarFunc( &sym ) ) { cclass |= CALLER_POPS | HAS_VARARGS; } } #if ( _CPU == 8086 ) || ( _CPU == 386 ) if( sym.flags & SYM_FUNC_NEEDS_THUNK ) { cclass |= THUNK_PROLOG; } #endif } #ifdef REVERSE cclass &= ~ REVERSE_PARMS; #endif #ifdef PROLOG_HOOKS if( CompFlags.ep_switch_used != 0 ) { cclass |= PROLOG_HOOKS; } #endif #ifdef EPILOG_HOOKS if( CompFlags.ee_switch_used != 0 ) { cclass |= EPILOG_HOOKS; } #endif #ifdef GROW_STACK if( CompFlags.sg_switch_used ) { cclass |= GROW_STACK; } #endif #ifdef TOUCH_STACK if( CompFlags.st_switch_used ) { cclass |= TOUCH_STACK; } #endif return( cclass ); }
struct aux_info *InfoLookup( SYMPTR sym ) { char *name; struct aux_info *inf; struct aux_entry *ent; name = sym->name; inf = &DefaultInfo; /* assume default */ if( name == NULL ) return( inf ); /* 01-jun-90 */ ent = AuxLookup( name ); if( ent != NULL ) inf = ent->info; if( ( ent == NULL ) || (sym->flags & SYM_INTRINSIC) ) { if( sym->flags & SYM_DEFINED ) return( inf ); if( !(sym->flags & SYM_INTRINSIC) ) { if( memcmp( name, "_inline_", 8 ) != 0 ) return( inf ); name += 8; } #if ( _CPU == 8086 ) || ( _CPU == 386 ) { struct inline_funcs *ifunc; ifunc = IF_Lookup( name ); if( ifunc == NULL ) return( inf ); #if ( _CPU == 8086 ) if( HW_CEqual( ifunc->returns, HW_DX_AX ) || HW_CEqual( ifunc->returns, HW_DS_SI ) || HW_CEqual( ifunc->returns, HW_ES_DI ) || HW_CEqual( ifunc->returns, HW_CX_DI ) ) { if( SizeOfArg( sym->sym_type->object ) != 4 ) { #else if( HW_CEqual( ifunc->returns, HW_DX_AX ) || HW_CEqual( ifunc->returns, HW_DS_ESI ) || HW_CEqual( ifunc->returns, HW_ES_EDI ) || HW_CEqual( ifunc->returns, HW_CX_DI ) ) { if( SizeOfArg( sym->sym_type->object ) != 6 ) { #endif return( inf ); } } inf = &InlineInfo; inf->cclass = (WatcallInfo.cclass & FAR) | MODIFY_EXACT; if( (sym->flags & SYM_INTRINSIC) && ( ent != NULL ) ) inf->cclass |= ent->info->cclass; inf->code = ifunc->code; inf->parms = ifunc->parms; inf->returns = ifunc->returns; #if ( _CPU == 8086 ) if( !HW_CEqual( inf->returns, HW_AX ) && !HW_CEqual( inf->returns, HW_EMPTY ) ) { #else if( !HW_CEqual( inf->returns, HW_EAX ) && !HW_CEqual( inf->returns, HW_EMPTY ) ) { #endif inf->cclass |= SPECIAL_RETURN; } HW_CAsgn( inf->streturn, HW_EMPTY ); inf->save = ifunc->save; inf->objname = WatcallInfo.objname; /* 26-jan-93 */ inf->use = 1; } #endif } return( inf ); } struct aux_info *FindInfo( SYM_ENTRY *sym, SYM_HANDLE sym_handle ) { SYM_ENTRY sym_typedef; struct aux_entry *ent; TYPEPTR typ; struct aux_info *inf; inf = &DefaultInfo; /* assume default */ if( sym_handle == 0 ) return( inf ); SymGet( sym, sym_handle ); #if _CPU == 386 if( (sym_handle == SymSTOSB) || (sym_handle == SymSTOSD) ) { return( &STOSBInfo ); } else if( sym_handle == SymFinally ) { static byte_seq FinallyCode = { 1, { 0xc3 } }; /* ret */ InlineInfo = WatcallInfo; InlineInfo.code = &FinallyCode; return( &InlineInfo ); } else if( sym_handle == SymTryFini ) { static hw_reg_set TryFiniParms[] = { HW_D( HW_EAX ), HW_D( HW_EMPTY ) }; static byte_seq TryFiniCode = { 6, { 0x64, 0xA3, 0, 0, 0, 0 } }; /* mov fs:[0],eax */ InlineInfo = WatcallInfo; InlineInfo.parms = TryFiniParms; InlineInfo.code = &TryFiniCode; return( &InlineInfo ); } #endif if( !(sym->flags & SYM_TEMP) ) { /* not an indirect func call*/ inf = InfoLookup( sym ); } if( inf == &DefaultInfo ) { typ = SkipDummyTypedef( sym->sym_type ); if( typ->decl_type == TYPE_TYPEDEF ) { SymGet( &sym_typedef, typ->u.typedefn ); if( sym_typedef.name != NULL ) { ent = AuxLookup( sym_typedef.name ); if( ent != NULL ) { inf = ent->info; } } } } #if _CPU == 386 if( ( inf->flags & AUX_FLAG_FAR16 ) || ( sym->attrib & FLAG_FAR16 ) ) { if( ( (sym->attrib & FLAG_LANGUAGES) == LANG_PASCAL ) || ( inf->cclass & REVERSE_PARMS ) ) { return( &Far16PascalInfo ); } else { return( &Far16CdeclInfo ); } } #endif return( inf ); } int FunctionAborts( SYM_ENTRY *sym, SYM_HANDLE sym_handle ) /* 09-apr-93 */ { struct aux_entry *ent; if( sym_handle != 0 ) { /* 19-apr-93 */ SymGet( sym, sym_handle ); ent = AuxLookup( SymName( sym, sym_handle ) ); if( ent != NULL ) { if( ent->info->cclass & SUICIDAL ) { return( 1 ); } } } return( 0 ); } void GetCallClass( SYM_HANDLE sym_handle ) { struct aux_info *inf; SYM_ENTRY sym; CallClass = DefaultInfo.cclass; if( sym_handle != 0 ) { inf = FindInfo( &sym, sym_handle ); if( sym.flags & SYM_FUNCTION ) { if( inf != &DefaultInfo ) { CallClass = inf->cclass; } else { CallClass = GetLangInfo( sym.attrib )->cclass; #if _CPU == 8086 if( TargSys == TS_WINDOWS ) { if( sym.attrib & (LANG_CDECL | LANG_PASCAL) ) { CallClass |= FAT_WINDOWS_PROLOG; } } #endif } #if ( _CPU == 8086 ) || ( _CPU == 386 ) if( CompFlags.emit_names ) { CallClass |= EMIT_FUNCTION_NAME; } if( sym.attrib & FLAG_FAR ) { CallClass |= FAR; if( sym.attrib & FLAG_NEAR ) { CallClass |= INTERRUPT; } } else if( sym.attrib & FLAG_NEAR ) { CallClass &= ~ FAR; } #endif #ifdef DLL_EXPORT if( sym.attrib & FLAG_EXPORT ) { /* 12-mar-90 */ CallClass |= DLL_EXPORT; } #endif #ifdef LOAD_DS_ON_ENTRY if( sym.attrib & FLAG_LOADDS ) { /* 26-apr-90 */ #if 0 /* John - 11-mar-93 */ /* 21-feb-93 */ if( TargSys == TS_WINDOWS ) { CallClass |= FAT_WINDOWS_PROLOG; } else { CallClass |= LOAD_DS_ON_ENTRY; } #else CallClass |= LOAD_DS_ON_ENTRY; #endif } #endif #ifdef MAKE_CALL_INLINE if( IsInLineFunc( sym_handle ) ) { CallClass |= MAKE_CALL_INLINE; } #endif if( VarFunc( &sym ) ) { CallClass |= CALLER_POPS | HAS_VARARGS; } } } #ifdef REVERSE CallClass &= ~ REVERSE_PARMS; /* 28-may-89 */ #endif #if ( _CPU == 8086 ) || ( _CPU == 386 ) if( sym_handle != 0 && sym.flags & SYM_FUNC_NEEDS_THUNK ) { CallClass |= THUNK_PROLOG; } #endif #ifdef PROLOG_HOOKS if( CompFlags.ep_switch_used != 0 ) { CallClass |= PROLOG_HOOKS; } #endif #ifdef EPILOG_HOOKS if( CompFlags.ee_switch_used != 0 ) { CallClass |= EPILOG_HOOKS; } #endif #ifdef GROW_STACK if( CompFlags.sg_switch_used ) { CallClass |= GROW_STACK; } #endif #ifdef TOUCH_STACK if( CompFlags.st_switch_used ) { CallClass |= TOUCH_STACK; } #endif } static time_t *getFileDepTimeStamp( FNAMEPTR flist ) { static time_t stamp; #if ( ( _CPU == 8086 ) || ( _CPU == 386 ) ) && ( COMP_CFG_COFF == 0 ) stamp = _timet2dos( flist->mtime ); #else stamp = flist->mtime; #endif return( &stamp ); } /* // NextLibrary // Called (indirectly) from the code generator to inject automagically defined symbols. // Inputs: // index (n-1) // Usually called from a loop until we return 0/NULL to show no more libraries // request // NEXT_LIBRARY // examines the current flags to see if any libraries should be // automagically referenced and returns the relevant index if so. // LIBRARY_NAME // returns the requested name. // */ static VOIDPTR NextLibrary( int index, aux_class request ) { struct library_list *liblist; char *name = NULL; int i; i = 0; if( request == NEXT_LIBRARY ) ++index; for( liblist = HeadLibs; liblist; liblist = liblist->next ) { name = &liblist->prio; ++i; if( i == index ) { break; } } if( liblist == NULL ) { switch( index - i ) { case 1: /* return 1 for CLIB */ name = CLIB_Name; if( CompFlags.emit_library_any ) break; if( CompFlags.emit_library_with_main ) { if( CompFlags.has_main ) break; if( CompFlags.has_winmain ) break; if( CompFlags.bd_switch_used ) break; if( CompFlags.has_libmain ) break; if( CompFlags.bm_switch_used ) break; /* JBS */ ++index; } else { name = NULL; index = 0; // indicate all done } break; /* // MATHLIB is always referenced as a default library because // the linker wont include anything without a 'real' referenced // symbol */ case 2: /* return 2 for MATHLIB */ name = MATHLIB_Name; break; case 3: /* return 3 for EMULIB */ name = EmuLib_Name; if( EmuLib_Name != NULL ) break; // fall through case 4: /* used to be PCODE */ name = NULL; index = 0; // indicate all done break; default: break; } } /* // return library name, or */ if( request == LIBRARY_NAME ) return( name ); /* // library index */ return( (char *)index ); } // NextAlias // Called (indirectly) from the code generator to go through the list of // linker aliases. // Inputs: // index (n-1) // Called from a loop until we return 0/NULL to show no more aliases // request // NEXT_ALIAS // returns the index of next alias in the list, or zero if none. // ALIAS_NAME // returns the alias name, or NULL if alias refers to a symbol. // ALIAS_SYMBOL // returns the alias symbol, or NULL if alias refers to a name. // ALIAS_SUBSTITUTE // returns the name to be substituted for the alias. // // Note: One of ALIAS_NAME and ALIAS_SYMBOL will always be 0/NULL and the other // will be valid, depending on which form of the pragma was used. static VOIDPTR NextAlias( int index, aux_class request ) { struct alias_list *aliaslist; SYM_HANDLE alias_sym = NULL; SYM_HANDLE subst_sym = NULL; const char *alias_name = NULL; const char *subst_name = NULL; int i; if( request == NEXT_ALIAS ) ++index; for( i = 1, aliaslist = AliasHead; aliaslist; aliaslist = aliaslist->next, ++i ) { alias_name = aliaslist->name; alias_sym = aliaslist->a_sym; subst_name = aliaslist->subst; subst_sym = aliaslist->s_sym; if( i == index ) { break; } } if( aliaslist == NULL ) index = 0; /* no (more) aliases */ if( request == ALIAS_NAME ) { return( (VOIDPTR)alias_name ); } else if( request == ALIAS_SYMBOL ) { return( (VOIDPTR)alias_sym ); } else if( request == ALIAS_SUBST_NAME ) { return( (VOIDPTR)subst_name ); } else if( request == ALIAS_SUBST_SYMBOL ) { return( (VOIDPTR)subst_sym ); } else { // this had better be a NEXT_ALIAS request return( (VOIDPTR)index ); } } /* Return the size of function parameters or -1 if size could * not be determined (symbol isn't a function or is variadic) */ static int GetParmsSize( CGSYM_HANDLE sym_handle ) { int total_parm_size = 0; int parm_size; TYPEPTR fn_typ; TYPEPTR *parm; TYPEPTR typ; SYM_ENTRY sym; SymGet( &sym, sym_handle ); fn_typ = sym.sym_type; SKIP_TYPEDEFS( fn_typ ); if( fn_typ->decl_type == TYPE_FUNCTION ) { parm = fn_typ->u.fn.parms; if( parm != NULL ) { for( ; (typ = *parm); ++parm ) { if( typ->decl_type == TYPE_DOT_DOT_DOT ) { total_parm_size = -1; break; } SKIP_TYPEDEFS( typ ); if( typ->decl_type == TYPE_VOID ) break; parm_size = TypeSize( typ ); parm_size = (parm_size + sizeof( target_int ) - 1) & -sizeof( target_int ); total_parm_size += parm_size; } } } else { total_parm_size = -1; } return( total_parm_size ); } /* // Return name pattern manipulator string */ static char *GetNamePattern( CGSYM_HANDLE sym_handle ) { char *pattern; SYM_ENTRY sym; struct aux_info *inf; inf = FindInfo( &sym, sym_handle ); #ifdef __SEH__ if(( sym_handle == SymTryInit ) || ( sym_handle == SymTryFini ) || ( sym_handle == SymTryUnwind ) || ( sym_handle == SymExcept )) { pattern = "*"; } else { #endif inf = LangInfo( sym.attrib, inf ); if( sym.flags & SYM_FUNCTION ) { pattern = inf->objname; #if ( _CPU == 386 ) || ( _CPU == 8086 ) if( VarFunc( &sym ) ) { if( inf == &DefaultInfo ) inf = DftCallConv; if( inf == &StdcallInfo ) { pattern = CdeclInfo.objname; } else if( inf == &FastcallInfo ) { pattern = CdeclInfo.objname; } } #endif if( pattern == NULL ) { pattern = TS_CODE_MANGLE; } } else { pattern = VarNamePattern( inf ); if( pattern == NULL ) { pattern = TS_DATA_MANGLE; } } #ifdef __SEH__ } // close that else #endif return( pattern ); }