📄 cpragaxp.c
字号:
/****************************************************************************
*
* 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: Alpha AXP target specific pragma processing.
*
****************************************************************************/
#include "cvars.h"
#include "cgswitch.h"
#include "target.h"
#include "pragdefn.h"
#include "pdefn2.h"
#include "asinline.h"
#include "scan.h"
static hw_reg_set StackParms[] = { HW_D( HW_EMPTY ) };
static hw_reg_set AsmRegsSaved[] = { HW_D( HW_FULL ) };
static int AsmFuncNum;
#define MAX_NUM_INS 256
extern uint_32 *AsmCodeBuffer;
extern uint_32 AsmCodeAddress;
extern void *AsmAlloc( unsigned amount );
extern void AsmFree( void *ptr );
void AsmWarning( char *msg ) {
//****************************
// CC provides this
}
uint_32 AsmQuerySPOffsetOf( char *name ) {
//****************************************
// CC provides this
return( 0 );
}
enum sym_state AsmQueryExternal( char *name )
{
SYM_HANDLE sym_handle;
auto SYM_ENTRY sym;
sym_handle = SymLook( CalcHash( name, strlen( name ) ), name );
if( sym_handle == 0 ) return( SYM_UNDEFINED );
SymGet( &sym, sym_handle );
switch( sym.stg_class ) {
case SC_AUTO:
case SC_REGISTER:
return( SYM_STACK );
}
return( SYM_EXTERNAL );
}
local void FreeAsmFixups()
{
asmreloc *reloc, *next;
for( reloc = AsmRelocs; reloc; reloc = next ) {
next = reloc->next;
// AsmFree( reloc->name ); this routine should be in asm
// AsmFree( reloc );
}
// AsmRelocs = NULL;
}
static byte_seq_reloc *GetFixups( void ){
/****************************************/
asmreloc *reloc;
byte_seq_reloc *head,*new;
byte_seq_reloc **lnk;
SYM_HANDLE sym_handle;
head = NULL;
lnk = &head;
for( reloc = AsmRelocs; reloc; reloc = reloc->next ) {
new = CMemAlloc( sizeof( byte_seq_reloc ) );
sym_handle = SymLook( CalcHash( reloc->name, strlen( reloc->name ) ), reloc->name );
new->off = reloc->offset;
new->type = reloc->type;
new->sym = (void *)sym_handle;
new->next = NULL;
*lnk = new;
lnk = &new->next;
}
return( head );
}
static int EndOfAsmStmt( void )
{
if( CurToken == T_EOF ) return( TRUE );
if( CurToken == T_NULL ) return( TRUE );
if( CurToken == T___ASM ) return( TRUE );
if( CurToken == T_RIGHT_BRACE ) return( TRUE );
if( CurToken == T_SEMI_COLON ) return( TRUE );
return( FALSE );
}
static void AbsorbASMConstant( char *buff, unsigned size )
{
// 0a0b3h is a valid .ASM constant
for(;;) {
NextToken();
if( EndOfAsmStmt() || ( CharSet[ Buffer[0] ] & (C_AL|C_DI) ) == 0 ) {
return;
}
strncat( buff, Buffer, size );
}
}
static int IsId( unsigned token )
{
if( token == T_ID ) {
return( TRUE );
}
if( token >= FIRST_KEYWORD && token <= LAST_KEYWORD ) {
return( TRUE );
}
return( FALSE );
}
void GetAsmLine()
{
char buf[256];
CompFlags.pre_processing = 1; // cause T_NULL token at end of line
if( strcmp( Buffer, "_emit" ) == 0 ) {
NextToken(); // get numeric constant
if( CurToken != T_CONSTANT ) {
ExpectConstant();
} else {
AsmCodeBuffer[AsmCodeAddress++] = Constant;
NextToken();
}
} else {
buf[0] = '\0';
for(;;) {
if( EndOfAsmStmt() ) break;
strncat( buf, Buffer, 255 );
if( CurToken == T_CONSTANT ) {
AbsorbASMConstant( buf, 255 );
strncat( buf, " ", 255 );
} else {
if( IsId( CurToken ) ) {
NextToken();
if( CurToken != T_XOR ) {
strncat( buf, " ", 255 );
}
} else {
NextToken();
}
}
}
if( buf[0] != '\0' ){
AsmLine( buf );
}
}
}
void AsmStmt()
{
int i;
SYM_HANDLE sym_handle;
TREEPTR tree;
int too_many_bytes;
int uses_auto;
uint_32 buff[MAX_NUM_INS];
auto char name[8];
// indicate that we are inside an __asm statement so scanner will
// allow tokens unique to the assembler. e.g. 21h
CompFlags.inside_asm_stmt = 1;
NextToken();
AsmInit();
AsmCodeBuffer = &buff[0];
AsmCodeAddress = 0;
if( CurToken == T_LEFT_BRACE ) {
NextToken();
too_many_bytes = 0;
for(;;) { // grab assembler lines
GetAsmLine();
if( AsmCodeAddress >= sizeof( buff ) ) {
if( ! too_many_bytes ) {
CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
too_many_bytes = 1;
}
AsmCodeAddress = 0; // reset index to we don't overrun buffer
}
if( CurToken == T_RIGHT_BRACE ) break;
if( CurToken == T_EOF ) break;
if( CurToken == T_NULL ){ //skip over NL
CompFlags.pre_processing = 0;
}
NextToken();
}
CompFlags.pre_processing = 0;
CompFlags.inside_asm_stmt = 0;
NextToken();
} else {
GetAsmLine(); // grab single assembler instruction
CompFlags.pre_processing = 0;
CompFlags.inside_asm_stmt = 0;
if( CurToken == T_NULL ) {
NextToken();
}
}
i = AsmCodeAddress;
if( i != 0 ) {
sprintf( name, "F.%d", AsmFuncNum );
++AsmFuncNum;
CreateAux( name );
*CurrInfo = DefaultInfo;
CurrInfo->use = 1;
CurrInfo->save = AsmRegsSaved[0]; // indicate no registers saved
if( too_many_bytes ) {
uses_auto = 0;
}else{
risc_byte_seq *seq;
seq = (risc_byte_seq *) CMemAlloc( sizeof(risc_byte_seq)+i );
seq->relocs = GetFixups();
seq->length = i;
memcpy( &seq->data[0], buff, i );
CurrInfo->code = seq;
}
FreeAsmFixups();
if( uses_auto ) {
/*
We want to force the calling routine to set up a [E]BP frame
for the use of this pragma. This is done by saying the pragma
modifies the [E]SP register. A kludge, but it works.
*/
// HW_CTurnOff( CurrInfo->save, HW_SP );
}
CurrEntry->info = CurrInfo;
CurrEntry->next = AuxList;
AuxList = CurrEntry;
CurrEntry = NULL;
sym_handle = MakeFunction( CStrSave( name ),
FuncNode( GetType( TYPE_VOID ), 0, NULL ) );
tree = LeafNode( OPR_FUNCNAME );
tree->op.sym_handle = sym_handle;
tree = ExprNode( tree, OPR_CALL, NULL );
tree->expr_type = GetType( TYPE_VOID );
AddStmt( tree );
}
AsmFini();
}
local int GetByteSeq()
{
uint_32 buff[MAX_NUM_INS];
int i;
int uses_auto;
char too_many_bytes;
AsmInit();
CompFlags.pre_processing = 1; /* enable macros */
NextToken();
too_many_bytes = 0;
i = 0;
for(;;) {
if( CurToken == T_STRING ) { /* 06-sep-91 */
AsmCodeBuffer = buff;
AsmCodeAddress = i;
AsmLine( Buffer );
i = AsmCodeAddress;
if( i >= sizeof( buff ) ) {
if( ! too_many_bytes ) {
CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
too_many_bytes = 1;
}
i = 0; // reset index to we don't overrun buffer
}
NextToken();
if( CurToken == T_COMMA ) NextToken();
} else if( CurToken == T_CONSTANT ) {
if( i < sizeof( buff ) ) {
buff[ i++ ] = Constant;
} else {
if( ! too_many_bytes ) {
CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
too_many_bytes = 1;
}
}
NextToken();
}else{
break;
}
}
if( too_many_bytes ) {
uses_auto = 0;
}else{
risc_byte_seq *seq;
seq = (risc_byte_seq *) CMemAlloc( sizeof(risc_byte_seq)+i );
seq->relocs = GetFixups();
seq->length = i;
memcpy( &seq->data[0], buff, i );
CurrInfo->code = seq;
}
FreeAsmFixups();
CompFlags.pre_processing = 2;
AsmFini();
return( uses_auto );
}
void PragmaInit(void ){
/****************/
AsmFuncNum = 0;
PragInit();
}
static int GetAliasInfo( void ){
/*************************/
auto char buff[256];
CurrAlias = &DefaultInfo;
if( CurToken != T_LEFT_PAREN ) return( 1 );
NextToken();
if( CurToken != T_ID ) return( 0 );
PragCurrAlias();
strcpy( buff, Buffer );
NextToken();
if( CurToken == T_RIGHT_PAREN ) {
NextToken();
return( 1 );
} else if( CurToken == T_COMMA ) {
NextToken();
if( CurToken != T_ID ) return( 0 );
CreateAux( buff );
PragCurrAlias();
NextToken();
if( CurToken == T_RIGHT_PAREN ) {
*CurrInfo = *CurrAlias;
NextToken();
}
PragEnding();
return( 0 ); /* process no more! */
} else {
return( 0 ); // shut up the compiler
}
}
static void GetPdata( void ){
/***************************/
char *name;
if( CurToken != T_ID ) {
CErr1( ERR_EXPECTING_ID );
} else {
name = CStrSave( Buffer );
CurrInfo->except_rtn = name;
NextToken();
}
}
void PragAux( void ){
/*************/
struct {
unsigned f_export : 1;
unsigned f_parm : 1;
unsigned f_value : 1;
unsigned f_modify : 1;
unsigned f_frame : 1;
unsigned f_except : 1;
unsigned uses_auto: 1;
} have;
if( !GetAliasInfo() ) return;
CurrEntry = NULL;
if( CurToken != T_ID ) return;
SetCurrInfo();
NextToken();
*CurrInfo = *CurrAlias;
PragObjNameInfo();
have.f_export = 0;
have.f_parm = 0;
have.f_value = 0;
have.f_modify = 0;
have.f_frame = 0;
have.f_except = 0;
have.uses_auto = 0; /* BBB - Jan 26, 1994 */
for( ;; ) {
if( CurToken == T_EQUAL ) {
have.uses_auto = GetByteSeq();
} else if( !have.f_export && PragRecog( "export" ) ) {
CurrInfo->class |= DLL_EXPORT;
have.f_export = 1;
} else if( !have.f_parm && PragRecog( "parm" ) ) {
// GetParmInfo();
have.f_parm = 1;
} else if( !have.f_value && PragRecog( "value" ) ) {
// GetRetInfo();
have.f_value = 1;
} else if( !have.f_value && PragRecog( "aborts" ) ) {
CurrInfo->class |= SUICIDAL;
have.f_value = 1;
} else if( !have.f_modify && PragRecog( "modify" ) ) {
// GetSaveInfo();
have.f_modify = 1;
} else if( !have.f_frame && PragRecog( "frame" ) ) {
// CurrInfo->class |= GENERATE_STACK_FRAME;
have.f_frame = 1;
} else if( !have.f_except && PragRecog( "pdata_exception" ) ) {
GetPdata();
have.f_except = 1;
} else {
break;
}
}
if( have.uses_auto ) {
/*
We want to force the calling routine to set up a [E]BP frame
for the use of this pragma. This is done by saying the pragma
modifies the [E]SP register. A kludge, but it works.
*/
// HW_CTurnOff( CurrInfo->save, HW_SP );
}
PragEnding();
}
hw_reg_set PragRegName( char *str )
{
return( StackParms[ 0 ] );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -