Esempio n. 1
0
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 ) );
    }
}
Esempio n. 2
0
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
}
Esempio n. 3
0
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
}
Esempio n. 4
0
/* 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 );
}
Esempio n. 5
0
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 );
    }
}
Esempio n. 6
0
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 );
}
Esempio n. 7
0
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;
    }
}
Esempio n. 8
0
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;
    }
}
Esempio n. 9
0
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 );
    }
}
Esempio n. 10
0
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 );
}
Esempio n. 11
0
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 );
}