1 /****************************************************************************
2 *
3 * This code is Public Domain.
4 *
5 * ========================================================================
6 *
7 * Description: implements the "fastpass" handling.
8 * "fastpass" is an optimization which increases
9 * assembly time speed by storing preprocessed lines
10 * in memory during the first pass. In further passes,
11 * those lines are "read" instead of the original assembly
12 * source files.
13 * Speed increase is significant if there's a large include
14 * file at the top of an assembly source which contains
15 * just equates and type definitions, because there's no need
16 * to save such lines during pass one.
17 *
18 ****************************************************************************/
19
20 #include <ctype.h>
21
22 #include "globals.h"
23 #include "memalloc.h"
24 #include "parser.h"
25 #include "input.h"
26 #include "segment.h"
27 #include "fastpass.h"
28
29 #if FASTPASS
30
31 extern uint_32 list_pos; /* current LST file position */
32
33 static struct mod_state modstate; /* struct to store assembly status */
34 static struct {
35 struct line_item *head;
36 struct line_item *tail;
37 } LineStore;
38 struct line_item *LineStoreCurr; /* must be global! */
39 bool StoreState;
40 bool UseSavedState;
41
42 /*
43 * save the current status (happens in pass one only) and
44 * switch to "save precompiled lines" mode.
45 * the status is then restored in further passes,
46 * and the precompiled lines are used for assembly then.
47 */
48
SaveState(void)49 static void SaveState( void )
50 /***************************/
51 {
52 DebugMsg1(("SaveState enter\n" ));
53 StoreState = TRUE;
54 UseSavedState = TRUE;
55 modstate.init = TRUE;
56 modstate.Equ.head = modstate.Equ.tail = NULL;
57
58 /* v2.13: save the current source file */
59 modstate.saved_src = get_curr_srcfile();
60 /* save the part of ModuleInfo that is NOT in module_vars */
61 memcpy( &modstate.modinfo, (uint_8 *)&ModuleInfo + sizeof( struct module_vars ), sizeof( modstate.modinfo ) );
62
63 SegmentSaveState();
64 AssumeSaveState();
65 ContextSaveState(); /* save pushcontext/popcontext stack */
66
67 DebugMsg(( "SaveState exit\n" ));
68 }
69
StoreLine(const char * srcline,int flags,uint_32 lst_position)70 void StoreLine( const char *srcline, int flags, uint_32 lst_position )
71 /********************************************************************/
72 {
73 int i,j;
74 char *p;
75
76 #ifdef DEBUG_OUT
77 if ( Options.nofastpass )
78 return;
79 #endif
80 if ( ModuleInfo.GeneratedCode ) /* don't store generated lines! */
81 return;
82 if ( StoreState == FALSE ) /* line store already started? */
83 SaveState();
84
85 i = strlen( srcline );
86 j = ( ( ( flags & 1 ) && ModuleInfo.CurrComment ) ? strlen( ModuleInfo.CurrComment ) : 0 );
87 LineStoreCurr = LclAlloc( i + j + sizeof( struct line_item ) );
88 LineStoreCurr->next = NULL;
89 LineStoreCurr->lineno = GetLineNumber();
90 if ( MacroLevel ) {
91 LineStoreCurr->srcfile = 0xfff;
92 } else {
93 LineStoreCurr->srcfile = get_curr_srcfile();
94 }
95 LineStoreCurr->list_pos = ( lst_position ? lst_position : list_pos );
96 if ( j ) {
97 memcpy( LineStoreCurr->line, srcline, i );
98 memcpy( LineStoreCurr->line + i, ModuleInfo.CurrComment, j + 1 );
99 } else
100 memcpy( LineStoreCurr->line, srcline, i + 1 );
101
102 DebugMsg1(("StoreLine(>%s<, lst_position=%u): cur=%X\n", LineStoreCurr->line, lst_position, LineStoreCurr ));
103
104 /* v2.08: don't store % operator at pos 0 */
105 for ( p = LineStoreCurr->line; *p && isspace(*p); p++ );
106 if (*p == '%' && ( _memicmp( p+1, "OUT", 3 ) || is_valid_id_char( *(p+4) ) ) )
107 *p = ' ';
108
109 #ifdef DEBUG_OUT
110 if ( Options.print_linestore )
111 printf("%s\n", LineStoreCurr->line );
112 #endif
113 if ( LineStore.head )
114 LineStore.tail->next = LineStoreCurr;
115 else
116 LineStore.head = LineStoreCurr;
117 LineStore.tail = LineStoreCurr;
118 }
119
120 /* an error has been detected in pass one. it should be
121 reported in pass 2, so ensure that a full source scan is done then
122 */
123
SkipSavedState(void)124 void SkipSavedState( void )
125 /*************************/
126 {
127 DebugMsg(("SkipSavedState called\n"));
128 UseSavedState = FALSE;
129 }
130
131 /* for FASTPASS, just pass 1 is a full pass, the other passes
132 don't start from scratch and they just assemble the preprocessed
133 source. To be able to restart the assembly process from a certain
134 location within the source, it's necessary to save the value of
135 assembly time variables.
136 However, to reduce the number of variables that are saved, an
137 assembly-time variable is only saved when
138 - it is changed
139 - it was defined when StoreState() is called
140 */
141
SaveVariableState(struct asym * sym)142 void SaveVariableState( struct asym *sym )
143 /****************************************/
144 {
145 struct equ_item *p;
146
147 DebugMsg1(( "SaveVariableState(%s)=%d\n", sym->name, sym->value ));
148 sym->issaved = TRUE; /* don't try to save this symbol (anymore) */
149 p = LclAlloc( sizeof( struct equ_item ) );
150 p->next = NULL;
151 p->sym = sym;
152 p->lvalue = sym->value;
153 p->hvalue = sym->value3264; /* v2.05: added */
154 p->mem_type = sym->mem_type; /* v2.07: added */
155 p->isdefined = sym->isdefined;
156 if ( modstate.Equ.tail ) {
157 modstate.Equ.tail->next = p;
158 modstate.Equ.tail = p;
159 } else {
160 modstate.Equ.head = modstate.Equ.tail = p;
161 }
162 // printf("state of symbol >%s< saved, value=%u, defined=%u\n", sym->name, sym->value, sym->defined);
163 }
164
RestoreState(void)165 struct line_item *RestoreState( void )
166 /************************************/
167 {
168 DebugMsg1(("RestoreState enter\n"));
169 if ( modstate.init ) {
170 struct equ_item *curr;
171 /* restore values of assembly time variables */
172 for ( curr = modstate.Equ.head; curr; curr = curr->next ) {
173 DebugMsg1(("RestoreState: sym >%s<, value=%Xh (hvalue=%Xh), defined=%u\n", curr->sym->name, curr->lvalue, curr->hvalue, curr->isdefined ));
174 /* v2.07: MT_ABS is obsolete */
175 //if ( curr->sym->mem_type == MT_ABS ) {
176 curr->sym->value = curr->lvalue;
177 curr->sym->value3264 = curr->hvalue;
178 curr->sym->mem_type = curr->mem_type; /* v2.07: added */
179 curr->sym->isdefined = curr->isdefined;
180 //}
181 }
182 /* fields in module_vars are not to be restored.
183 * v2.10: the module_vars fields are not saved either.
184 */
185 //memcpy( &modstate.modinfo.g, &ModuleInfo.g, sizeof( ModuleInfo.g ) );
186 memcpy( (char *)&ModuleInfo + sizeof( struct module_vars ), &modstate.modinfo, sizeof( modstate.modinfo ) );
187 /* v2.13: restore the current source file */
188 set_curr_srcfile( modstate.saved_src, 0 );
189 SetOfssize();
190 SymSetCmpFunc();
191 }
192
193 #if 0
194 /* v2.05: AFAICS this can't happen anymore. */
195 if ( LineStore.head == NULL ) {
196 struct line_item *endl = LclAlloc( sizeof( struct line_item ) + 3 );
197 endl->next = NULL;
198 endl->srcfile = 0;
199 endl->lineno = GetLineNumber();
200 endl->list_pos = 0;
201 strcpy( endl->line, "END");
202 LineStore.head = endl;
203 DebugMsg(("RestoreState: LineStore.head was NULL !!!\n" ));
204 }
205 #endif
206 return( LineStore.head );
207 }
208
209 #if FASTMEM==0
210 /* this is debugging code only. Usually FASTPASS and FASTMEM
211 * are both either TRUE or FALSE.
212 * It's active if both DEBUG and TRMEM is set in Makefile.
213 */
FreeLineStore(void)214 void FreeLineStore( void )
215 /************************/
216 {
217 struct line_item *next;
218 for ( LineStoreCurr = LineStore.head; LineStoreCurr; ) {
219 next = LineStoreCurr->next;
220 LclFree( LineStoreCurr );
221 LineStoreCurr = next;
222 }
223 }
224 #endif
225
FastpassInit(void)226 void FastpassInit( void )
227 /***********************/
228 {
229 StoreState = FALSE;
230 modstate.init = FALSE;
231 LineStore.head = NULL;
232 LineStore.tail = NULL;
233 UseSavedState = FALSE;
234 }
235
236 #endif
237