can2td2.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 534 行 · 第 1/2 页
C
534 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <string.h>
#include "womp.h"
#include "turbodbg.h"
#include "queue.h"
#include "cansymb.h"
#include "cantype.h"
#include "objrec.h"
#include "genutil.h"
#include "fixup.h"
#include "canaddr.h"
#include "myassert.h"
STATIC uint_32 codeOffset;
STATIC uint_16 codeSeg;
STATIC uint blockIndent;
STATIC int skipALocal;
STATIC int inParms; /* TD_LOCAL_PARM_FLAG if in parms */
STATIC void symbChangeSeg( symb_handle symb ) {
addr_info *seg;
fixup *fix;
/**/myassert( symb != NULL && symb->class == CANS_CHANGE_SEG );
if( blockIndent > 0 ) {
Fatal( MSG_CHANGE_SEG_IN_BLOCK );
}
seg = CanAFind( symb->d.cseg.seg );
fix = seg->fixup;
/**/myassert( fix->self_relative == 0 ); /* no self-relative */
if( fix->lr.target != TARGET_SEGWD ) {
Fatal( MSG_INVALID_FIXUP );
}
switch( fix->loc_method ) {
case FIX_BASE:
codeOffset = 0;
codeSeg = fix->lr.target_datum + (int_16)ReadU16( seg->data );
break;
case FIX_POINTER:
codeSeg = fix->lr.target_datum + (int_16)ReadU16( seg->data + 2 );
codeOffset = fix->lr.target_offset + (int_32)ReadU16( seg->data );
break;
case FIX_POINTER386:
codeSeg = fix->lr.target_datum + (int_16)ReadU16( seg->data + 4 );
codeOffset = fix->lr.target_offset + (int_32)ReadU32( seg->data );
break;
default:
/**/ never_reach();
}
}
STATIC void blockBegin( uint_16 seg, uint_32 offset ) {
obj_rec *coment;
if( offset > 0xffff ) {
coment = Can2TDNewRec( TD_CMT_BEGIN_SCOPE_LARGE, 6 );
ObjPutIndex( coment, seg ); /* max 2 bytes */
ObjPut32( coment, offset ); /* plus 4 bytes = 6 bytes */
} else {
coment = Can2TDNewRec( TD_CMT_BEGIN_SCOPE, 4 );
ObjPutIndex( coment, seg ); /* max 2 bytes */
ObjPut16( coment, offset ); /* plus 2 bytes = 4 bytes */
}
Can2TDEndRec( coment );
}
STATIC void symbBlock( symb_handle symb ) {
symb_handle end;
/**/myassert( symb != NULL && symb->class == CANS_BLOCK );
/*
This is called on each block before any PUBDEFs have been processed.
can2td0 will set these to 1 if they are referenced by a PUBDEF.
*/
codeOffset += symb->d.block.start_offset;
++blockIndent;
if( blockIndent == 1 ) {
symb->extra = (uint_32)codeSeg;
end = symb->d.block.end;
/**/ myassert( end != NULL );
end->extra = codeOffset;
} else {
/* is an inner block, so we tell a little lie */
symb->extra = TD_HAS_A_PUBDEF;
}
blockBegin( codeSeg, codeOffset );
inParms = TD_LOCAL_PARM_FLAG;
}
STATIC void symbBPOffset( symb_handle symb ) {
cantype *type;
obj_rec *coment;
const char *name;
size_t name_len;
uint_16 type_idx;
int pasvar;
/**/myassert( symb != NULL && symb->class == CANS_BP_OFFSET );
if( skipALocal ) {
skipALocal = 0;
return;
}
name = NameGet( symb->d.nat.name_hdl );
name_len = strlen( name );
/**/myassert( name_len < 256 );
pasvar = 0;
type = CanTFind( symb->d.nat.type_hdl );
if( type == NULL ) {
type_idx = 0;
} else if( type->class == CANT_POINTER &&
( type->d.pointr.class & CANT_PTR_DEREF ) ) {
/* generate DEREFs as PASVAR locals */
pasvar = 1;
type = CanTFind( type->d.pointr.base_type );
if( type == NULL ) {
type_idx = 0;
} else {
type_idx = type->extra;
}
} else {
type_idx = type->extra;
}
if( symb->d.bpoff.offset > 0xffff ) {
/* 1 for name_len byte, 2 for type idx, 1 for class byte,
4 for offset word */
coment = Can2TDNewRec( TD_CMT_LOCAL_DEFN_LARGE, 1 + name_len + (2+1+4) );
} else {
/* 1 for name_len byte, 2 for type idx, 1 for class byte,
2 for offset word */
coment = Can2TDNewRec( TD_CMT_LOCAL_DEFN, 1 + name_len + (2+1+2) );
}
ObjPutName( coment, name, name_len );
ObjPutIndex( coment, type_idx );
ObjPut8( coment, inParms | ( pasvar ? TD_LOCAL_PASVAR : TD_LOCAL_AUTO ) );
if( symb->d.bpoff.offset > 0xffff ) {
ObjPut32( coment, symb->d.bpoff.offset );
} else {
ObjPut16( coment, symb->d.bpoff.offset );
}
Can2TDEndRec( coment );
}
STATIC void symbMemLoc( symb_handle symb ) {
cantype *type;
uint_16 type_idx;
size_t name_len;
const char *name;
fixup *fix;
addr_info *mem_loc;
obj_rec *coment;
uint_32 offset;
uint_16 grp_idx;
/**/myassert( symb != NULL && symb->class == CANS_MEM_LOC );
if( skipALocal ) {
skipALocal = 0;
return;
}
mem_loc = CanAFind( symb->d.memloc.mem_hdl );
fix = mem_loc->fixup;
switch( fix->lr.frame ) {
case FRAME_GRP:
grp_idx = fix->lr.frame_datum;
break;
default:
/* FIXME this heuristic is not quite accurate... it's ok for F_TARG */
grp_idx = 0;
break;
}
if( fix->lr.target != TARGET_SEGWD ) {
Fatal( MSG_INVALID_FIXUP );
}
type = CanTFind( symb->d.nat.type_hdl );
if( type == NULL ) {
type_idx = 0;
} else {
type_idx = type->extra;
}
name = NameGet( symb->d.nat.name_hdl );
name_len = strlen( name );
/**/myassert( name_len < 256 );
offset = fix->lr.target_offset;
switch( fix->loc_method ) {
case FIX_POINTER:
case FIX_OFFSET:
offset += (int_32)ReadS16( mem_loc->data );
break;
case FIX_POINTER386:
case FIX_OFFSET386:
offset += (int_32)ReadS32( mem_loc->data );
break;
}
if( offset > 0xffff ) {
/* 1 for name_len byte, 2 for type_idx, 1 for class byte, 2 for grp_idx,
2 for seg_idx, 4 for offset word */
coment = Can2TDNewRec( TD_CMT_LOCAL_DEFN_LARGE, name_len+(1+2+1+2+2+4));
} else {
/* 1 for name_len byte, 2 for type_idx, 1 for class byte, 2 for grp_idx,
2 for seg_idx, 2 for offset word */
coment = Can2TDNewRec( TD_CMT_LOCAL_DEFN, name_len + (1+2+1+2+2+2));
}
ObjPutName( coment, name, name_len );
ObjPutIndex( coment, type_idx );
ObjPut8( coment, inParms | TD_LOCAL_STATIC );
ObjPutIndex( coment, grp_idx );
ObjPutIndex( coment, fix->lr.target_datum );
if( offset > 0xffff ) {
ObjPut32( coment, offset );
} else {
ObjPut16( coment, offset );
}
Can2TDEndRec( coment );
}
STATIC const uint_8 tdRegs[] = {
/*CANS_REG_AL */ TD_REG_AL,
/*CANS_REG_AH */ TD_REG_AH,
/*CANS_REG_BL */ TD_REG_BL,
/*CANS_REG_BH */ TD_REG_BH,
/*CANS_REG_CL */ TD_REG_CL,
/*CANS_REG_CH */ TD_REG_CH,
/*CANS_REG_DL */ TD_REG_DL,
/*CANS_REG_DH */ TD_REG_DH,
/*CANS_REG_AX */ TD_REG_AX,
/*CANS_REG_BX */ TD_REG_BX,
/*CANS_REG_CX */ TD_REG_CX,
/*CANS_REG_DX */ TD_REG_DX,
/*CANS_REG_SI */ TD_REG_SI,
/*CANS_REG_DI */ TD_REG_DI,
/*CANS_REG_BP */ TD_REG_BP,
/*CANS_REG_SP */ TD_REG_SP,
/*CANS_REG_CS */ TD_REG_CS,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?