jwasm/fastpass.c
2014-06-18 19:16:56 +04:00

232 lines
7.6 KiB
C

/****************************************************************************
*
* This code is Public Domain.
*
* ========================================================================
*
* Description: implements the "fastpass" handling.
* "fastpass" is an optimization which increases
* assembly time speed by storing preprocessed lines
* in memory during the first pass. In further passes,
* those lines are "read" instead of the original assembly
* source files.
* Speed increase is significant if there's a large include
* file at the top of an assembly source which contains
* just equates and type definitions, because there's no need
* to save such lines during pass one.
*
****************************************************************************/
#include <ctype.h>
#include "globals.h"
#include "memalloc.h"
#include "parser.h"
#include "input.h"
#include "segment.h"
#include "fastpass.h"
#if FASTPASS
extern uint_32 list_pos; /* current LST file position */
static struct mod_state modstate; /* struct to store assembly status */
static struct {
struct line_item *head;
struct line_item *tail;
} LineStore;
struct line_item *LineStoreCurr; /* must be global! */
bool StoreState;
bool UseSavedState;
/*
* save the current status (happens in pass one only) and
* switch to "save precompiled lines" mode.
* the status is then restored in further passes,
* and the precompiled lines are used for assembly then.
*/
static void SaveState( void )
/***************************/
{
DebugMsg1(("SaveState enter\n" ));
StoreState = TRUE;
UseSavedState = TRUE;
modstate.init = TRUE;
modstate.Equ.head = modstate.Equ.tail = NULL;
memcpy( &modstate.modinfo, (uint_8 *)&ModuleInfo + sizeof( struct module_vars ), sizeof( modstate.modinfo ) );
SegmentSaveState();
AssumeSaveState();
ContextSaveState(); /* save pushcontext/popcontext stack */
DebugMsg(( "SaveState exit\n" ));
}
void StoreLine( const char *srcline, int flags, uint_32 lst_position )
/********************************************************************/
{
int i,j;
char *p;
#ifdef DEBUG_OUT
if ( Options.nofastpass )
return;
#endif
if ( ModuleInfo.GeneratedCode ) /* don't store generated lines! */
return;
if ( StoreState == FALSE ) /* line store already started? */
SaveState();
i = strlen( srcline );
j = ( ( ( flags & 1 ) && ModuleInfo.CurrComment ) ? strlen( ModuleInfo.CurrComment ) : 0 );
LineStoreCurr = LclAlloc( i + j + sizeof( struct line_item ) );
LineStoreCurr->next = NULL;
LineStoreCurr->lineno = GetLineNumber();
if ( MacroLevel ) {
LineStoreCurr->srcfile = 0xfff;
} else {
LineStoreCurr->srcfile = get_curr_srcfile();
}
LineStoreCurr->list_pos = ( lst_position ? lst_position : list_pos );
if ( j ) {
memcpy( LineStoreCurr->line, srcline, i );
memcpy( LineStoreCurr->line + i, ModuleInfo.CurrComment, j + 1 );
} else
memcpy( LineStoreCurr->line, srcline, i + 1 );
DebugMsg1(("StoreLine(>%s<, lst_position=%u): cur=%X\n", LineStoreCurr->line, lst_position, LineStoreCurr ));
/* v2.08: don't store % operator at pos 0 */
for ( p = LineStoreCurr->line; *p && isspace(*p); p++ );
if (*p == '%' && ( _memicmp( p+1, "OUT", 3 ) || is_valid_id_char( *(p+4) ) ) )
*p = ' ';
#ifdef DEBUG_OUT
if ( Options.print_linestore )
printf("%s\n", LineStoreCurr->line );
#endif
if ( LineStore.head )
LineStore.tail->next = LineStoreCurr;
else
LineStore.head = LineStoreCurr;
LineStore.tail = LineStoreCurr;
}
/* an error has been detected in pass one. it should be
reported in pass 2, so ensure that a full source scan is done then
*/
void SkipSavedState( void )
/*************************/
{
DebugMsg(("SkipSavedState enter\n"));
UseSavedState = FALSE;
}
/* for FASTPASS, just pass 1 is a full pass, the other passes
don't start from scratch and they just assemble the preprocessed
source. To be able to restart the assembly process from a certain
location within the source, it's necessary to save the value of
assembly time variables.
However, to reduce the number of variables that are saved, an
assembly-time variable is only saved when
- it is changed
- it was defined when StoreState() is called
*/
void SaveVariableState( struct asym *sym )
/****************************************/
{
struct equ_item *p;
DebugMsg1(( "SaveVariableState(%s)=%d\n", sym->name, sym->value ));
sym->issaved = TRUE; /* don't try to save this symbol (anymore) */
p = LclAlloc( sizeof( struct equ_item ) );
p->next = NULL;
p->sym = sym;
p->lvalue = sym->value;
p->hvalue = sym->value3264; /* v2.05: added */
p->mem_type = sym->mem_type; /* v2.07: added */
p->isdefined = sym->isdefined;
if ( modstate.Equ.tail ) {
modstate.Equ.tail->next = p;
modstate.Equ.tail = p;
} else {
modstate.Equ.head = modstate.Equ.tail = p;
}
// printf("state of symbol >%s< saved, value=%u, defined=%u\n", sym->name, sym->value, sym->defined);
}
struct line_item *RestoreState( void )
/************************************/
{
DebugMsg1(("RestoreState enter\n"));
if ( modstate.init ) {
struct equ_item *curr;
/* restore values of assembly time variables */
for ( curr = modstate.Equ.head; curr; curr = curr->next ) {
DebugMsg1(("RestoreState: sym >%s<, value=%Xh (hvalue=%Xh), defined=%u\n", curr->sym->name, curr->lvalue, curr->hvalue, curr->isdefined ));
/* v2.07: MT_ABS is obsolete */
//if ( curr->sym->mem_type == MT_ABS ) {
curr->sym->value = curr->lvalue;
curr->sym->value3264 = curr->hvalue;
curr->sym->mem_type = curr->mem_type; /* v2.07: added */
curr->sym->isdefined = curr->isdefined;
//}
}
/* fields in module_vars are not to be restored.
* v2.10: the module_vars fields are not saved either.
*/
//memcpy( &modstate.modinfo.g, &ModuleInfo.g, sizeof( ModuleInfo.g ) );
memcpy( (char *)&ModuleInfo + sizeof( struct module_vars ), &modstate.modinfo, sizeof( modstate.modinfo ) );
SetOfssize();
SymSetCmpFunc();
}
#if 0
/* v2.05: AFAICS this can't happen anymore. */
if ( LineStore.head == NULL ) {
struct line_item *endl = LclAlloc( sizeof( struct line_item ) + 3 );
endl->next = NULL;
endl->srcfile = 0;
endl->lineno = GetLineNumber();
endl->list_pos = 0;
strcpy( endl->line, "END");
LineStore.head = endl;
DebugMsg(("RestoreState: LineStore.head was NULL !!!\n" ));
}
#endif
return( LineStore.head );
}
#if FASTMEM==0
/* this is debugging code only. Usually FASTPASS and FASTMEM
* are both either TRUE or FALSE.
* It's active if both DEBUG and TRMEM is set in Makefile.
*/
void FreeLineStore( void )
/************************/
{
struct line_item *next;
for ( LineStoreCurr = LineStore.head; LineStoreCurr; ) {
next = LineStoreCurr->next;
LclFree( LineStoreCurr );
LineStoreCurr = next;
}
}
#endif
void FastpassInit( void )
/***********************/
{
StoreState = FALSE;
modstate.init = FALSE;
LineStore.head = NULL;
LineStore.tail = NULL;
UseSavedState = FALSE;
}
#endif