2 /********************************************
4 copyright 1991, Michael D. Brennan
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
14 * Revision 1.4 1995/06/18 19:42:19 mike
15 * Remove some redundant declarations and add some prototypes
17 * Revision 1.3 1995/04/21 14:20:16 mike
18 * move_level variable to fix bug in arglist patching of moved code.
20 * Revision 1.2 1993/07/14 13:17:49 mike
21 * rm SIZE_T and run thru indent
23 * Revision 1.1.1.1 1993/07/03 18:58:15 mike
26 * Revision 5.3 1993/01/09 19:03:44 mike
27 * code_pop checks if the resolve_list needs relocation
29 * Revision 5.2 1993/01/07 02:50:33 mike
30 * relative vs absolute code
32 * Revision 5.1 1991/12/05 07:56:10 brennan
37 /* this module deals with back patching jumps, breaks and continues,
38 and with save and restoring code when we move code.
39 There are three stacks. If we encounter a compile error, the
40 stacks are frozen, i.e., we do not attempt error recovery
53 #define error_state (compile_error_count>0)
56 /*---------- back patching jumps ---------------*/
68 code_jmp(jtype, target)
72 if (error_state) return ;
74 /* WARNING: Don't emit any code before using target or
75 relocation might make it invalid */
77 if (target) code2op(jtype, target - (code_ptr + 1)) ;
80 register JMP *p = ZMALLOC(JMP) ;
82 /* stack for back patch */
84 p->source_offset = code_offset - 1 ;
91 patch_jmp(target) /* patch a jump on the jmp_stack */
95 register INST *source ; /* jmp starts here */
100 if (!jmp_top) bozo("jmp stack underflow") ;
103 p = jmp_top ; jmp_top = p->link ;
104 source = p->source_offset + code_base ;
105 source->op = target - source ;
112 /*-- break and continue -------*/
116 struct bc *link ; /* stack as linked list */
117 int type ; /* 'B' or 'C' or mark start with 0 */
118 int source_offset ; /* position of _JMP */
127 BC_new() /* mark the start of a loop */
129 BC_insert(0, (INST *) 0) ;
133 BC_insert(type, address)
134 int type ; INST *address ;
138 if (error_state) return ;
142 compile_error("%s statement outside of loop",
143 type == 'B' ? "break" : "continue") ;
151 p->source_offset = address - code_base ;
158 /* patch all break and continues for one loop */
160 BC_clear(B_address, C_address)
161 INST *B_address, *C_address ;
166 if (error_state) return ;
169 /* pop down to the mark node */
172 source = code_base + p->source_offset ;
173 source->op = (p->type == 'B' ? B_address : C_address)
176 q = p ; p = p->link ; ZFREE(q) ;
178 /* remove the mark node */
183 /*----- moving code --------------------------*/
185 /* a stack to hold some pieces of code while
190 { /* mc -- move code */
192 INST *code ; /* the save code */
193 unsigned len ; /* its length */
194 int scope ; /* its scope */
195 int move_level ; /* size of this stack when coded */
196 FBLOCK *fbp ; /* if scope FUNCT */
197 int offset ; /* distance from its code base */
202 int code_move_level = 0 ; /* see comment in jmp.h */
205 /* means relocation of resolve list not needed */
208 code_push(code, len, scope, fbp)
225 p->code = (INST *) zmalloc(sizeof(INST) * len) ;
226 memcpy(p->code, code, sizeof(INST) * len) ;
228 if (!resolve_list) p->scope = NO_SCOPE ;
232 p->move_level = code_move_level ;
234 p->offset = code - code_base ;
240 /* copy the code at the top of the mc stack to target.
241 return the number of INSTs moved */
251 if (error_state) return 0 ;
254 if (!mc_top) bozo("mc underflow") ;
257 p = mc_top ; mc_top = p->link ;
260 while (target + len >= code_warn)
262 target_offset = target - code_base ;
264 target = code_base + target_offset ;
269 memcpy(target, p->code, len * sizeof(INST)) ;
270 zfree(p->code, len * sizeof(INST)) ;
273 if (p->scope != NO_SCOPE)
275 target_offset = target - code_base ;
276 relocate_resolve_list(p->scope, p->move_level, p->fbp,
277 p->offset, len, target_offset - p->offset) ;