cpragx86.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,054 行 · 第 1/3 页
C
1,054 行
SYM_INT1, /* TYPE_BOOL, */
0, /* TYPE_POINTER,*/
0, /* TYPE_ARRAY,*/
0, /* TYPE_STRUCT,*/
0, /* TYPE_UNION,*/
0, /* TYPE_FUNCTION,*/
0, /* TYPE_FIELD,*/
SYM_INT1, /* TYPE_VOID,*/
0, /* TYPE_ENUM,*/
0, /* TYPE_TYPEDEF,*/
0, /* TYPE_UFIELD,*/
0, /* TYPE_DOT_DOT_DOT,*/
SYM_INT1, /* TYPE_PLAIN_CHAR,*/
SYM_INT2, /* TYPE_WCHAR, */
0, /* TYPE_FCOMPLEX, */
0, /* TYPE_DCOMPLEX, */
0, /* TYPE_LDCOMPLEX, */
};
local int AsmType( TYPEPTR typ, type_modifiers flags )
/****************************************************/
{
SKIP_TYPEDEFS( typ );
switch( typ->decl_type ) {
case TYPE_STRUCT:
case TYPE_UNION:
return( SYM_INT1 );
case TYPE_ARRAY:
return( AsmType( typ->object, flags ) );
case TYPE_FIELD:
case TYPE_UFIELD:
return( AsmDataType[ typ->u.f.field_type ] );
case TYPE_FUNCTION:
return( AsmCodePtrType( flags ) );
case TYPE_POINTER:
return( AsmPtrType( typ->object, typ->u.p.decl_flags ) );
case TYPE_ENUM:
typ = typ->object;
/* fall through */
default:
return( AsmDataType[ typ->decl_type ] );
}
}
enum sym_type AsmQueryType( char *name )
/**************************************/
{
SYM_HANDLE sym_handle;
SYM_ENTRY sym;
sym_handle = SymLook( CalcHash( name, strlen( name ) ), name );
if( sym_handle == 0 ) return( SYM_INT1 );
SymGet( &sym, sym_handle );
return( AsmType( sym.sym_type, sym.attrib ) );
}
static int InsertFixups( unsigned char *buff, unsigned i, byte_seq **code )
/*************************************************************************/
{
/* additional slop in buffer to simplify the code */
unsigned char temp[ MAXIMUM_BYTESEQ + 1 + 2 * sizeof( long ) ];
struct asmfixup *fix;
struct asmfixup *head;
struct asmfixup *chk;
struct asmfixup *next;
struct asmfixup **owner;
unsigned char *dst;
unsigned char *src;
unsigned char *end;
byte_seq *seq;
byte_seq_len perform_fixups;
unsigned char cg_fix;
SYM_HANDLE sym_handle;
SYM_ENTRY sym;
char *name;
unsigned skip;
int mutate_to_segment;
int uses_auto;
#if _CPU == 8086
int fixup_padding;
#endif
uses_auto = 0;
perform_fixups = 0;
head = FixupHead;
if( head != NULL ) {
FixupHead = NULL;
/* sort the fixup list in increasing fixup_loc's */
for( fix = head; fix != NULL; fix = next ) {
owner = &FixupHead;
for( ;; ) {
chk = *owner;
if( chk == NULL ) break;
if( chk->fixup_loc > fix->fixup_loc ) break;
owner = &chk->next;
}
next = fix->next;
fix->next = *owner;
*owner = fix;
}
dst = temp;
src = buff;
end = src + i;
fix = FixupHead;
owner = &FixupHead;
/* insert fixup escape sequences */
while( src < end ) {
if( fix != NULL && fix->fixup_loc == (src - buff) ) {
name = fix->name;
if( name != NULL ) {
sym_handle = SymLook( CalcHash( name, strlen( name ) ),
name );
if( sym_handle == 0 ) {
CErr2p( ERR_UNDECLARED_SYM, name );
return( 0 );
}
SymGet( &sym, sym_handle );
sym.flags |= SYM_REFERENCED | SYM_ADDR_TAKEN;
switch( sym.stg_class ) {
case SC_REGISTER:
case SC_AUTO:
sym.flags |= SYM_USED_IN_PRAGMA;
CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE;
uses_auto = 1;
break;
}
SymReplace( &sym, sym_handle );
}
/* insert fixup information */
skip = 0;
*dst++ = FLOATING_FIXUP_BYTE;
mutate_to_segment = 0;
#if _CPU == 8086
fixup_padding = 0;
#endif
switch( fix->fixup_type ) {
case FIX_SEG:
if( name == NULL ) {
/* special case for floating point fixup */
if( src[0] == 0x9b ) {
// FWAIT instruction as first byte
} else if( ( src[0] == 0x90 ) && ( src[1] == 0x9B ) ) {
// inline assembler FWAIT instruction 0x90, 0x9b
} else if( ( src[0] & 0xd8 ) == 0xd8 ) {
// FPU instruction, add FWAIT before it
*dst++ = 0x9b;
} else {
// FIXME - probably wrong use of float !!!!
}
} else {
skip = 2;
cg_fix = FIX_SYM_SEGMENT;
}
break;
case FIX_RELOFF8:
CErr2p( ERR_UNREACHABLE_SYM, name );
break;
case FIX_RELOFF16:
skip = 2;
cg_fix = FIX_SYM_RELOFF;
break;
case FIX_RELOFF32:
skip = 4;
cg_fix = FIX_SYM_RELOFF;
#if _CPU == 8086
fixup_padding = 1;
#endif
break;
case FIX_PTR16:
mutate_to_segment = 1;
/* fall through */
case FIX_OFF16:
skip = 2;
cg_fix = FIX_SYM_OFFSET;
break;
case FIX_PTR32:
mutate_to_segment = 1;
/* fall through */
case FIX_OFF32:
skip = 4;
cg_fix = FIX_SYM_OFFSET;
#if _CPU == 8086
fixup_padding = 1;
#endif
break;
}
if( skip != 0 ) {
*dst++ = cg_fix;
*((CGSYM_HANDLE *)dst) = sym_handle;
dst += sizeof( CGSYM_HANDLE );
*((unsigned long *)dst) = fix->offset;
dst += sizeof( long );
src += skip;
}
#if _CPU == 8086
if( fixup_padding ) {
// add offset fixup padding to 32-bit
// cg create only 16-bit offset fixup
*dst++ = 0;
*dst++ = 0;
//
}
#endif
if( mutate_to_segment ) {
/*
Since the CG escape sequences don't allow for
FAR pointer fixups, we have to split them into two.
This is done by doing the offset fixup first, then
mutating the fixup structure to look like a segment
fixup one near pointer size later.
*/
fix->fixup_type = FIX_SEG;
fix->fixup_loc += skip;
fix->offset = 0;
} else {
head = fix;
fix = fix->next;
if( head->external ) {
*owner = fix;
if( head->name != NULL ) {
CMemFree( head->name );
}
CMemFree( head );
} else {
owner = &head->next;
}
}
} else {
if( *src == FLOATING_FIXUP_BYTE ) {
*dst++ = FLOATING_FIXUP_BYTE;
}
*dst++ = *src++;
}
if( dst > &temp[ MAXIMUM_BYTESEQ ] ) {
CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
return( 0 );
}
}
buff = temp;
i = dst - temp;
perform_fixups = DO_FLOATING_FIXUPS;
}
seq = (byte_seq *)CMemAlloc( sizeof( byte_seq ) + i );
seq->length = i | perform_fixups;
memcpy( &seq->data[0], buff, i );
*code = seq;
return( uses_auto );
}
local void AddAFix( unsigned i, char *name, unsigned type, unsigned long off )
/****************************************************************************/
{
struct asmfixup *fix;
fix = (struct asmfixup *)CMemAlloc( sizeof( *fix ) );
fix->external = 1;
fix->fixup_loc = i;
fix->name = name;
fix->offset = off;
fix->fixup_type = type;
fix->next = FixupHead;
FixupHead = fix;
}
local void FreeAsmFixups( void )
/******************************/
{
struct asmfixup *fix;
for( ;; ) {
fix = FixupHead;
if( fix == NULL ) break;
FixupHead = fix->next;
CMemFree( fix );
}
}
local int GetByteSeq( byte_seq **code )
/**************************/
{
unsigned char buff[ MAXIMUM_BYTESEQ + 32 ];
char *name;
unsigned long offset;
unsigned fixword;
int uses_auto;
char too_many_bytes;
AsmSysInit( buff );
CompFlags.pre_processing = 1; /* enable macros */
NextToken();
too_many_bytes = 0;
uses_auto = 0;
for( ;; ) {
if( CurToken == T_STRING ) { /* 06-sep-91 */
AsmLine( Buffer );
NextToken();
if( CurToken == T_COMMA ) {
NextToken();
}
} else if( CurToken == T_CONSTANT ) {
AsmCodeBuffer[AsmCodeAddress++] = Constant;
NextToken();
} else {
fixword = FixupKeyword();
if( fixword == FIXWORD_NONE )
break;
if( fixword == FIXWORD_FLOAT ) {
#if _CPU == 8086
if( GET_FPU_EMU( ProcRevision ) ) {
AddAFix( AsmCodeAddress, NULL, FIX_SEG, 0 );
}
#endif
} else { /* seg or offset */
if( CurToken != T_ID ) {
CErr1( ERR_EXPECTING_ID );
} else {
name = CStrSave( Buffer );
offset = 0;
NextToken();
if( CurToken == T_PLUS ) {
NextToken();
if( CurToken == T_CONSTANT ) {
offset = Constant;
NextToken();
}
} else if( CurToken == T_MINUS ) {
NextToken();
if( CurToken == T_CONSTANT ) {
offset = -Constant;
NextToken();
}
}
}
switch( fixword ) {
case FIXWORD_RELOFF:
#if _CPU == 8086
AddAFix( AsmCodeAddress, name, FIX_RELOFF16, offset );
AsmCodeAddress += 2;
#else
AddAFix( AsmCodeAddress, name, FIX_RELOFF32, offset );
AsmCodeAddress += 4;
#endif
break;
case FIXWORD_OFFSET:
#if _CPU == 8086
AddAFix( AsmCodeAddress, name, FIX_OFF16, offset );
AsmCodeAddress += 2;
#else
AddAFix( AsmCodeAddress, name, FIX_OFF32, offset );
AsmCodeAddress += 4;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?