1
/* ------------------------------------------------------------------------- */
2
/* "expressc" : The expression code generator */
4
/* Part of Inform 6.31 */
5
/* copyright (c) Graham Nelson 1993 - 2006 */
7
/* ------------------------------------------------------------------------- */
11
int vivc_flag; /* TRUE if the last code-generated
12
expression produced a "value in void
13
context" error: used to help the syntax
14
analyser recover from unknown-keyword
15
errors, since unknown keywords are
16
treated as yet-to-be-defined constants
17
and thus as values in void context */
19
/* ###- I'm making these global, because they're too useful to be
21
assembly_operand stack_pointer, temp_var1, temp_var2, temp_var3,
22
temp_var4, zero_operand, one_operand, two_operand, three_operand,
25
static void make_operands(void)
28
stack_pointer.type = VARIABLE_OT;
29
stack_pointer.value = 0;
30
stack_pointer.marker = 0;
31
temp_var1.type = VARIABLE_OT;
32
temp_var1.value = 255;
34
temp_var2.type = VARIABLE_OT;
35
temp_var2.value = 254;
37
temp_var3.type = VARIABLE_OT;
38
temp_var3.value = 253;
40
temp_var4.type = VARIABLE_OT;
41
temp_var4.value = 252;
43
zero_operand.type = SHORT_CONSTANT_OT;
44
zero_operand.value = 0;
45
zero_operand.marker = 0;
46
one_operand.type = SHORT_CONSTANT_OT;
47
one_operand.value = 1;
48
one_operand.marker = 0;
49
two_operand.type = SHORT_CONSTANT_OT;
50
two_operand.value = 2;
51
two_operand.marker = 0;
52
three_operand.type = SHORT_CONSTANT_OT;
53
three_operand.value = 3;
54
three_operand.marker = 0;
55
valueless_operand.type = OMITTED_OT;
56
valueless_operand.value = 0;
57
valueless_operand.marker = 0;
60
stack_pointer.type = LOCALVAR_OT;
61
stack_pointer.value = 0;
62
stack_pointer.marker = 0;
63
temp_var1.type = GLOBALVAR_OT;
64
temp_var1.value = MAX_LOCAL_VARIABLES+0;
66
temp_var2.type = GLOBALVAR_OT;
67
temp_var2.value = MAX_LOCAL_VARIABLES+1;
69
temp_var3.type = GLOBALVAR_OT;
70
temp_var3.value = MAX_LOCAL_VARIABLES+2;
72
temp_var4.type = GLOBALVAR_OT;
73
temp_var4.value = MAX_LOCAL_VARIABLES+3;
75
zero_operand.type = ZEROCONSTANT_OT;
76
zero_operand.value = 0;
77
zero_operand.marker = 0;
78
one_operand.type = BYTECONSTANT_OT;
79
one_operand.value = 1;
80
one_operand.marker = 0;
81
two_operand.type = BYTECONSTANT_OT;
82
two_operand.value = 2;
83
two_operand.marker = 0;
84
three_operand.type = BYTECONSTANT_OT;
85
three_operand.value = 3;
86
three_operand.marker = 0;
87
valueless_operand.type = OMITTED_OT;
88
valueless_operand.value = 0;
89
valueless_operand.marker = 0;
93
/* ------------------------------------------------------------------------- */
94
/* The table of conditionals. (Only used in Glulx) */
97
#define EQUAL_CC (502)
102
#define OFCLASS_CC (512)
103
#define PROVIDES_CC (514)
105
#define FIRST_CC (500)
106
#define LAST_CC (515)
108
typedef struct condclass_s {
109
int32 posform; /* Opcode for the conditional in its positive form. */
110
int32 negform; /* Opcode for the conditional in its negated form. */
113
condclass condclasses[] = {
124
/* ------------------------------------------------------------------------- */
125
/* The table of operators.
127
The ordering in this table is not significant except that it must match
128
the #define's in "header.h" */
130
operator operators[NUM_OPERATORS] =
132
/* ------------------------ */
134
/* ------------------------ */
136
{ 0, SEP_TT, COMMA_SEP, IN_U, L_A, 0, -1, -1, 0, 0, "comma" },
138
/* ------------------------ */
140
/* ------------------------ */
142
{ 1, SEP_TT, SETEQUALS_SEP, IN_U, R_A, 1, -1, -1, 1, 0,
143
"assignment operator '='" },
145
/* ------------------------ */
146
/* Level 2: ~~ && || */
147
/* ------------------------ */
149
{ 2, SEP_TT, LOGAND_SEP, IN_U, L_A, 0, -1, -1, 0, LOGOR_OP,
150
"logical conjunction '&&'" },
151
{ 2, SEP_TT, LOGOR_SEP, IN_U, L_A, 0, -1, -1, 0, LOGAND_OP,
152
"logical disjunction '||'" },
153
{ 2, SEP_TT, LOGNOT_SEP, PRE_U, R_A, 0, -1, -1, 0, LOGNOT_OP,
154
"logical negation '~~'" },
156
/* ------------------------ */
163
/* ------------------------ */
165
{ 3, -1, -1, -1, 0, 0, 400 + jz_zc, ZERO_CC+0, 0, NONZERO_OP,
166
"expression used as condition then negated" },
167
{ 3, -1, -1, -1, 0, 0, 800 + jz_zc, ZERO_CC+1, 0, ZERO_OP,
168
"expression used as condition" },
169
{ 3, SEP_TT, CONDEQUALS_SEP, IN_U, 0, 0, 400 + je_zc, EQUAL_CC+0, 0, NOTEQUAL_OP,
171
{ 3, SEP_TT, NOTEQUAL_SEP, IN_U, 0, 0, 800 + je_zc, EQUAL_CC+1, 0, CONDEQUALS_OP,
173
{ 3, SEP_TT, GE_SEP, IN_U, 0, 0, 800 + jl_zc, LT_CC+1, 0, LESS_OP,
175
{ 3, SEP_TT, GREATER_SEP, IN_U, 0, 0, 400 + jg_zc, GT_CC+0, 0, LE_OP,
177
{ 3, SEP_TT, LE_SEP, IN_U, 0, 0, 800 + jg_zc, GT_CC+1, 0, GREATER_OP,
179
{ 3, SEP_TT, LESS_SEP, IN_U, 0, 0, 400 + jl_zc, LT_CC+0, 0, GE_OP,
181
{ 3, CND_TT, HAS_COND, IN_U, 0, 0, 400 + test_attr_zc, HAS_CC+0, 0, HASNT_OP,
183
{ 3, CND_TT, HASNT_COND, IN_U, 0, 0, 800 + test_attr_zc, HAS_CC+1, 0, HAS_OP,
184
"'hasnt' condition" },
185
{ 3, CND_TT, IN_COND, IN_U, 0, 0, 400 + jin_zc, IN_CC+0, 0, NOTIN_OP,
187
{ 3, CND_TT, NOTIN_COND, IN_U, 0, 0, 800 + jin_zc, IN_CC+1, 0, IN_OP,
188
"'notin' condition" },
189
{ 3, CND_TT, OFCLASS_COND, IN_U, 0, 0, 600, OFCLASS_CC+0, 0, NOTOFCLASS_OP,
190
"'ofclass' condition" },
191
{ 3, CND_TT, PROVIDES_COND, IN_U, 0, 0, 601, PROVIDES_CC+0, 0, NOTPROVIDES_OP,
192
"'provides' condition" },
193
{ 3, -1, -1, -1, 0, 0, 1000, OFCLASS_CC+1, 0, OFCLASS_OP,
194
"negated 'ofclass' condition" },
195
{ 3, -1, -1, -1, 0, 0, 1001, PROVIDES_CC+1, 0, PROVIDES_OP,
196
"negated 'provides' condition" },
198
/* ------------------------ */
200
/* ------------------------ */
202
{ 4, CND_TT, OR_COND, IN_U, L_A, 0, -1, -1, 0, 0, "'or'" },
204
/* ------------------------ */
205
/* Level 5: + binary - */
206
/* ------------------------ */
208
{ 5, SEP_TT, PLUS_SEP, IN_U, L_A, 0, add_zc, add_gc, 0, 0, "'+'" },
209
{ 5, SEP_TT, MINUS_SEP, IN_U, L_A, 0, sub_zc, sub_gc, 0, 0, "'-'" },
211
/* ------------------------ */
214
/* ------------------------ */
216
{ 6, SEP_TT, TIMES_SEP, IN_U, L_A, 0, mul_zc, mul_gc, 0, 0, "'*'" },
217
{ 6, SEP_TT, DIVIDE_SEP, IN_U, L_A, 0, div_zc, div_gc, 0, 0, "'/'" },
218
{ 6, SEP_TT, REMAINDER_SEP, IN_U, L_A, 0, mod_zc, mod_gc, 0, 0,
219
"remainder after division '%'" },
220
{ 6, SEP_TT, ARTAND_SEP, IN_U, L_A, 0, and_zc, bitand_gc, 0, 0,
222
{ 6, SEP_TT, ARTOR_SEP, IN_U, L_A, 0, or_zc, bitor_gc, 0, 0,
224
{ 6, SEP_TT, ARTNOT_SEP, PRE_U, R_A, 0, -1, bitnot_gc, 0, 0,
227
/* ------------------------ */
228
/* Level 7: -> --> */
229
/* ------------------------ */
231
{ 7, SEP_TT, ARROW_SEP, IN_U, L_A, 0, -1, -1, 0, 0,
232
"byte array operator '->'" },
233
{ 7, SEP_TT, DARROW_SEP, IN_U, L_A, 0, -1, -1, 0, 0,
234
"word array operator '-->'" },
236
/* ------------------------ */
237
/* Level 8: unary - */
238
/* ------------------------ */
240
{ 8, SEP_TT, UNARY_MINUS_SEP, PRE_U, R_A, 0, -1, neg_gc, 0, 0,
243
/* ------------------------ */
245
/* (prefix or postfix) */
246
/* ------------------------ */
248
{ 9, SEP_TT, INC_SEP, PRE_U, R_A, 2, -1, -1, 1, 0,
249
"pre-increment operator '++'" },
250
{ 9, SEP_TT, POST_INC_SEP, POST_U, R_A, 3, -1, -1, 1, 0,
251
"post-increment operator '++'" },
252
{ 9, SEP_TT, DEC_SEP, PRE_U, R_A, 4, -1, -1, 1, 0,
253
"pre-decrement operator '--'" },
254
{ 9, SEP_TT, POST_DEC_SEP, POST_U, R_A, 5, -1, -1, 1, 0,
255
"post-decrement operator '--'" },
257
/* ------------------------ */
258
/* Level 10: .& .# */
260
/* ------------------------ */
262
{10, SEP_TT, PROPADD_SEP, IN_U, L_A, 0, -1, -1, 0, 0,
263
"property address operator '.&'" },
264
{10, SEP_TT, PROPNUM_SEP, IN_U, L_A, 0, -1, -1, 0, 0,
265
"property length operator '.#'" },
266
{10, SEP_TT, MPROPADD_SEP, IN_U, L_A, 0, -1, -1, 0, 0,
267
"individual property address operator '..&'" },
268
{10, SEP_TT, MPROPNUM_SEP, IN_U, L_A, 0, -1, -1, 0, 0,
269
"individual property length operator '..#'" },
271
/* ------------------------ */
272
/* Level 11: function ( */
273
/* ------------------------ */
275
{11, SEP_TT, OPENB_SEP, IN_U, L_A, 0, -1, -1, 1, 0,
278
/* ------------------------ */
280
/* ------------------------ */
282
{12, SEP_TT, MESSAGE_SEP, IN_U, L_A, 0, -1, -1, 0, 0,
283
"individual property selector '..'" },
284
{12, SEP_TT, PROPERTY_SEP, IN_U, L_A, 0, -1, -1, 0, 0,
285
"property selector '.'" },
287
/* ------------------------ */
289
/* ------------------------ */
291
{13, SEP_TT, SUPERCLASS_SEP, IN_U, L_A, 0, -1, -1, 0, 0,
292
"superclass operator '::'" },
294
/* ------------------------ */
295
/* Miscellaneous operators */
296
/* generated at lvalue */
298
/* ------------------------ */
300
{ 1, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* -> = */
301
"byte array entry assignment" },
302
{ 1, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* --> = */
303
"word array entry assignment" },
304
{ 1, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* .. = */
305
"individual property assignment" },
306
{ 1, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* . = */
307
"common property assignment" },
309
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* ++ -> */
310
"byte array entry preincrement" },
311
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* ++ --> */
312
"word array entry preincrement" },
313
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* ++ .. */
314
"individual property preincrement" },
315
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* ++ . */
316
"common property preincrement" },
318
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* -- -> */
319
"byte array entry predecrement" },
320
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* -- --> */
321
"word array entry predecrement" },
322
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* -- .. */
323
"individual property predecrement" },
324
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* -- . */
325
"common property predecrement" },
327
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* -> ++ */
328
"byte array entry postincrement" },
329
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* --> ++ */
330
"word array entry postincrement" },
331
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* .. ++ */
332
"individual property postincrement" },
333
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* . ++ */
334
"common property postincrement" },
336
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* -> -- */
337
"byte array entry postdecrement" },
338
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* --> -- */
339
"word array entry postdecrement" },
340
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* .. -- */
341
"individual property postdecrement" },
342
{ 9, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* . -- */
343
"common property postdecrement" },
345
{11, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* x.y(args) */
346
"call to common property" },
347
{11, -1, -1, -1, -1, 0, -1, -1, 1, 0, /* x..y(args) */
348
"call to individual property" },
350
/* ------------------------ */
351
/* And one Glulx-only op */
352
/* which just pushes its */
353
/* argument on the stack, */
355
/* ------------------------ */
357
{14, -1, -1, -1, -1, 0, -1, -1, 1, 0,
361
/* --- Condition annotater ------------------------------------------------- */
363
static void annotate_for_conditions(int n, int a, int b)
364
{ int i, opnum = ET[n].operator_number;
366
ET[n].label_after = -1;
367
ET[n].to_expression = FALSE;
368
ET[n].true_label = a;
369
ET[n].false_label = b;
371
if (ET[n].down == -1) return;
373
if ((operators[opnum].precedence == 2)
374
|| (operators[opnum].precedence == 3))
375
{ if ((a == -1) && (b == -1))
376
{ if (opnum == LOGAND_OP)
378
ET[n].false_label = b;
379
ET[n].to_expression = TRUE;
383
ET[n].true_label = a;
384
ET[n].to_expression = TRUE;
393
ET[n].false_label = b;
394
ET[n].label_after = b;
396
annotate_for_conditions(ET[n].down, -1, b);
397
if (b == ET[n].label_after)
398
annotate_for_conditions(ET[ET[n].down].right, a, -1);
399
else annotate_for_conditions(ET[ET[n].down].right, a, b);
404
ET[n].true_label = a;
405
ET[n].label_after = a;
407
annotate_for_conditions(ET[n].down, a, -1);
408
if (a == ET[n].label_after)
409
annotate_for_conditions(ET[ET[n].down].right, -1, b);
410
else annotate_for_conditions(ET[ET[n].down].right, a, b);
416
{ annotate_for_conditions(i, -1, -1); i = ET[i].right; }
419
/* --- Code generator ------------------------------------------------------ */
421
static void value_in_void_context_z(assembly_operand AO)
427
{ case LONG_CONSTANT_OT:
428
case SHORT_CONSTANT_OT:
430
if (AO.marker == SYMBOL_MV)
431
t = (char *) (symbs[AO.value]);
434
t = (char *) (symbs[variable_tokens[AO.value]]);
439
if (strcmp(t, "print_paddr") == 0)
440
obsolete_warning("ignoring 'print_paddr': use 'print (string)' instead");
442
if (strcmp(t, "print_addr") == 0)
443
obsolete_warning("ignoring 'print_addr': use 'print (address)' instead");
445
if (strcmp(t, "print_char") == 0)
446
obsolete_warning("ignoring 'print_char': use 'print (char)' instead");
448
ebf_error("assignment or statement", t);
451
static void write_result_z(assembly_operand to, assembly_operand from)
452
{ if (to.value == from.value) return;
453
if (to.value == 0) assemblez_1(push_zc, from);
454
else assemblez_store(to, from);
457
static void pop_zm_stack(void)
458
{ assembly_operand st;
459
if (version_number < 5) assemblez_0(pop_zc);
461
{ st.marker = 0; st.type = VARIABLE_OT; st.value = 0;
462
assemblez_1_branch(jz_zc, st, -2, TRUE);
466
static void access_memory_z(int oc, assembly_operand AO1, assembly_operand AO2,
467
assembly_operand AO3)
470
assembly_operand zero_ao, max_ao, size_ao, en_ao, type_ao, an_ao,
472
int x, y, byte_flag, read_flag, from_module;
474
if (AO1.marker == ARRAY_MV)
476
if ((oc == loadb_zc) || (oc == storeb_zc)) byte_flag=TRUE;
477
else byte_flag = FALSE;
478
if ((oc == loadb_zc) || (oc == loadw_zc)) read_flag=TRUE;
479
else read_flag = FALSE;
481
zero_ao.type = SHORT_CONSTANT_OT;
482
zero_ao.value = 0; zero_ao.marker = 0;
484
size_ao = zero_ao; size_ao.value = -1;
485
for (x=0; x<no_arrays; x++)
486
{ if (AO1.value == svals[array_symbols[x]])
487
{ size_ao.value = array_sizes[x]; y=x;
490
if (size_ao.value==-1)
491
from_module=TRUE; /*compiler_error("Array size can't be found");*/
494
type_ao = zero_ao; type_ao.value = array_types[y];
496
if ((!is_systemfile()))
499
if ((array_types[y] == WORD_ARRAY)
500
|| (array_types[y] == TABLE_ARRAY))
501
warning("Using '->' to access a --> or table array");
505
if ((array_types[y] == BYTE_ARRAY)
506
|| (array_types[y] == STRING_ARRAY))
507
warning("Using '-->' to access a -> or string array");
513
if ((!runtime_error_checking_switch) || (veneer_mode))
514
{ if ((oc == loadb_zc) || (oc == loadw_zc))
515
assemblez_2_to(oc, AO1, AO2, AO3);
517
assemblez_3(oc, AO1, AO2, AO3);
521
/* If we recognise AO1 as arising textually from a declared
522
array, we can check bounds explicitly. */
524
if ((AO1.marker == ARRAY_MV) && (!from_module))
526
int passed_label = next_label++, failed_label = next_label++,
527
final_label = next_label++;
528
/* Calculate the largest permitted array entry + 1
529
Here "size_ao.value" = largest permitted entry of its own kind */
533
&& ((array_types[y] == WORD_ARRAY)
534
|| (array_types[y] == TABLE_ARRAY)))
535
{ max_ao.value = size_ao.value*2 + 1;
539
&& ((array_types[y] == BYTE_ARRAY)
540
|| (array_types[y] == STRING_ARRAY)
541
|| (array_types[y] == BUFFER_ARRAY)))
542
{ if ((size_ao.value % 2) == 0)
543
max_ao.value = size_ao.value/2 - 1;
544
else max_ao.value = (size_ao.value-1)/2;
549
if (size_ao.value >= 256) size_ao.type = LONG_CONSTANT_OT;
550
if (max_ao.value >= 256) max_ao.type = LONG_CONSTANT_OT;
552
/* Can't write to the size entry in a string or table */
553
if (((array_types[y] == STRING_ARRAY)
554
|| (array_types[y] == TABLE_ARRAY))
556
{ if ((array_types[y] == TABLE_ARRAY) && byte_flag)
558
else zero_ao.value = 1;
561
en_ao = zero_ao; en_ao.value = ABOUNDS_RTE;
562
switch(oc) { case loadb_zc: en_ao.value = ABOUNDS_RTE; break;
563
case loadw_zc: en_ao.value = ABOUNDS_RTE+1; break;
564
case storeb_zc: en_ao.value = ABOUNDS_RTE+2; break;
565
case storew_zc: en_ao.value = ABOUNDS_RTE+3; break; }
568
if ((AO2.type == VARIABLE_OT)&&(AO2.value == 0))
569
{ assemblez_store(temp_var2, AO2);
570
assemblez_store(AO2, temp_var2);
571
index_ao = temp_var2;
573
assemblez_2_branch(jl_zc, index_ao, zero_ao, failed_label, TRUE);
574
assemblez_2_branch(jl_zc, index_ao, max_ao, passed_label, TRUE);
575
assemble_label_no(failed_label);
576
an_ao = zero_ao; an_ao.value = y;
577
assemblez_6(call_vn2_zc, veneer_routine(RT__Err_VR), en_ao,
578
index_ao, size_ao, type_ao, an_ao);
580
/* We have to clear any of AO1, AO2, AO3 off the stack if
581
present, so that we can achieve the same effect on the stack
582
that executing the opcode would have had */
584
if ((AO1.type == VARIABLE_OT) && (AO1.value == 0)) pop_zm_stack();
585
if ((AO2.type == VARIABLE_OT) && (AO2.value == 0)) pop_zm_stack();
586
if ((AO3.type == VARIABLE_OT) && (AO3.value == 0))
587
{ if ((oc == loadb_zc) || (oc == loadw_zc))
588
{ assemblez_store(AO3, zero_ao);
592
assemblez_jump(final_label);
594
assemble_label_no(passed_label);
595
if ((oc == loadb_zc) || (oc == loadw_zc))
596
assemblez_2_to(oc, AO1, AO2, AO3);
598
assemblez_3(oc, AO1, AO2, AO3);
599
assemble_label_no(final_label);
603
/* Otherwise, compile a call to the veneer which verifies that
604
the proposed read/write is within dynamic Z-machine memory. */
606
switch(oc) { case loadb_zc: vr = RT__ChLDB_VR; break;
607
case loadw_zc: vr = RT__ChLDW_VR; break;
608
case storeb_zc: vr = RT__ChSTB_VR; break;
609
case storew_zc: vr = RT__ChSTW_VR; break; }
611
if ((oc == loadb_zc) || (oc == loadw_zc))
612
assemblez_3_to(call_vs_zc, veneer_routine(vr), AO1, AO2, AO3);
614
assemblez_4(call_vn_zc, veneer_routine(vr), AO1, AO2, AO3);
617
static assembly_operand check_nonzero_at_runtime_z(assembly_operand AO1,
618
int error_label, int rte_number)
619
{ assembly_operand AO2, AO3;
620
int check_sp = FALSE, passed_label, failed_label, last_label;
621
if (veneer_mode) return AO1;
623
/* Assemble to code to check that the operand AO1 is ofclass Object:
624
if it is, execution should continue and the stack should be
625
unchanged. Otherwise, call the veneer's run-time-error routine
626
with the given error number, and then: if the label isn't -1,
627
switch execution to this label, with the value popped from
628
the stack if it was on the stack in the first place;
629
if the label is -1, either replace the top of the stack with
630
the constant 2, or return the operand (short constant) 2.
632
The point of 2 is that object 2 is the class-object Object
633
and therefore has no parent, child or sibling, so that the
634
built-in tree functions will safely return 0 on this object. */
636
/* Sometimes we can already see that the object number is valid. */
637
if (((AO1.type == LONG_CONSTANT_OT) || (AO1.type == SHORT_CONSTANT_OT))
638
&& (AO1.marker == 0) && (AO1.value >= 1) && (AO1.value < no_objects))
641
passed_label = next_label++;
642
failed_label = next_label++;
643
AO2.type = LONG_CONSTANT_OT;
644
AO2.value = actual_largest_object_SC;
645
AO2.marker = INCON_MV;
646
AO3.value = 5; AO3.type = SHORT_CONSTANT_OT; AO3.marker = 0;
648
if ((rte_number == IN_RTE) || (rte_number == HAS_RTE)
649
|| (rte_number == PROPERTY_RTE) || (rte_number == PROP_NUM_RTE)
650
|| (rte_number == PROP_ADD_RTE))
651
{ /* Allow classes */
653
if ((AO1.type == VARIABLE_OT) && (AO1.value == 0))
654
{ /* That is, if AO1 is the stack pointer */
656
assemblez_store(temp_var2, AO1);
657
assemblez_store(AO1, temp_var2);
658
assemblez_2_branch(jg_zc, AO3, temp_var2, failed_label, TRUE);
659
assemblez_2_branch(jg_zc, temp_var2, AO2, passed_label, FALSE);
662
{ assemblez_2_branch(jg_zc, AO3, AO1, failed_label, TRUE);
663
assemblez_2_branch(jg_zc, AO1, AO2, passed_label, FALSE);
667
{ if ((AO1.type == VARIABLE_OT) && (AO1.value == 0))
668
{ /* That is, if AO1 is the stack pointer */
670
assemblez_store(temp_var2, AO1);
671
assemblez_store(AO1, temp_var2);
672
assemblez_2_branch(jg_zc, AO3, temp_var2, failed_label, TRUE);
673
assemblez_2_branch(jg_zc, temp_var2, AO2, failed_label, TRUE);
675
assemblez_2_branch(jin_zc, temp_var2, AO3, passed_label, FALSE);
678
{ assemblez_2_branch(jg_zc, AO3, AO1, failed_label, TRUE);
679
assemblez_2_branch(jg_zc, AO1, AO2, failed_label, TRUE);
681
assemblez_2_branch(jin_zc, AO1, AO3, passed_label, FALSE);
685
assemble_label_no(failed_label);
686
AO2.type = SHORT_CONSTANT_OT; AO2.value = rte_number; AO2.marker = 0;
687
if (version_number >= 5)
688
assemblez_3(call_vn_zc, veneer_routine(RT__Err_VR), AO2, AO1);
690
assemblez_3_to(call_zc, veneer_routine(RT__Err_VR), AO2, AO1, temp_var2);
692
if (error_label != -1)
693
{ /* Jump to the error label */
694
if (error_label == -3) assemblez_0(rfalse_zc);
695
else if (error_label == -4) assemblez_0(rtrue_zc);
696
else assemblez_jump(error_label);
700
{ /* Push the short constant 2 */
701
AO2.type = SHORT_CONSTANT_OT; AO2.value = 2; AO2.marker = 0;
702
assemblez_store(AO1, AO2);
705
{ /* Store either short constant 2 or the operand's value in
706
the temporary variable */
707
AO2.type = SHORT_CONSTANT_OT; AO2.value = 2; AO2.marker = 0;
708
AO3 = temp_var2; assemblez_store(AO3, AO2);
709
last_label = next_label++;
710
assemblez_jump(last_label);
711
assemble_label_no(passed_label);
712
assemblez_store(AO3, AO1);
713
assemble_label_no(last_label);
717
assemble_label_no(passed_label);
721
static void compile_conditional_z(int oc,
722
assembly_operand AO1, assembly_operand AO2, int label, int flag)
723
{ assembly_operand AO3; int the_zc, error_label = label,
724
va_flag = FALSE, va_label;
729
{ if ((runtime_error_checking_switch) && (oc == jin_zc))
730
{ if (flag) error_label = next_label++;
731
AO1 = check_nonzero_at_runtime(AO1, error_label, IN_RTE);
733
if ((runtime_error_checking_switch) && (oc == test_attr_zc))
734
{ if (flag) error_label = next_label++;
735
AO1 = check_nonzero_at_runtime(AO1, error_label, HAS_RTE);
737
{ case SHORT_CONSTANT_OT:
738
case LONG_CONSTANT_OT:
740
{ if ((AO2.value < 0) || (AO2.value > 47))
741
error("'has'/'hasnt' applied to illegal attribute number");
745
{ int pa_label = next_label++, fa_label = next_label++;
746
assembly_operand en_ao, zero_ao, max_ao;
747
assemblez_store(temp_var1, AO1);
748
if ((AO1.type == VARIABLE_OT)&&(AO1.value == 0))
749
assemblez_store(AO1, temp_var1);
750
assemblez_store(temp_var2, AO2);
751
if ((AO2.type == VARIABLE_OT)&&(AO2.value == 0))
752
assemblez_store(AO2, temp_var2);
753
zero_ao.type = SHORT_CONSTANT_OT; zero_ao.marker = 0;
754
zero_ao.value = 0; max_ao = zero_ao; max_ao.value = 48;
755
assemblez_2_branch(jl_zc,temp_var2,zero_ao,fa_label,TRUE);
756
assemblez_2_branch(jl_zc,temp_var2,max_ao,pa_label,TRUE);
757
assemble_label_no(fa_label);
758
en_ao = zero_ao; en_ao.value = 19;
759
assemblez_4(call_vn_zc, veneer_routine(RT__Err_VR),
760
en_ao, temp_var1, temp_var2);
761
va_flag = TRUE; va_label = next_label++;
762
assemblez_jump(va_label);
763
assemble_label_no(pa_label);
767
assemblez_2_branch(oc, AO1, AO2, label, flag);
768
if (error_label != label) assemble_label_no(error_label);
769
if (va_flag) assemble_label_no(va_label);
773
AO3.type = VARIABLE_OT; AO3.value = 0; AO3.marker = 0;
775
the_zc = (version_number == 3)?call_zc:call_vs_zc;
777
assemblez_3_to(the_zc, veneer_routine(OP__Pr_VR), AO1, AO2, AO3);
779
assemblez_3_to(the_zc, veneer_routine(OC__Cl_VR), AO1, AO2, AO3);
781
assemblez_1_branch(jz_zc, AO3, label, !flag);
784
static void value_in_void_context_g(assembly_operand AO)
791
case HALFCONSTANT_OT:
792
case BYTECONSTANT_OT:
793
case ZEROCONSTANT_OT:
795
if (AO.marker == SYMBOL_MV)
796
t = (char *) (symbs[AO.value]);
799
t = (char *) (symbs[variable_tokens[AO.value]]);
804
ebf_error("assignment or statement", t);
807
static void write_result_g(assembly_operand to, assembly_operand from)
808
{ if (to.value == from.value && to.type == from.type) return;
809
assembleg_store(to, from);
812
static void access_memory_g(int oc, assembly_operand AO1, assembly_operand AO2,
813
assembly_operand AO3)
815
int data_len, read_flag;
816
assembly_operand zero_ao, max_ao, size_ao, en_ao, type_ao, an_ao,
818
int passed_label, failed_label, final_label, x, y;
820
if ((oc == aloadb_gc) || (oc == astoreb_gc)) data_len = 1;
821
else if ((oc == aloads_gc) || (oc == astores_gc)) data_len = 2;
824
if ((oc == aloadb_gc) || (oc == aloads_gc) || (oc == aload_gc))
829
if (AO1.marker == ARRAY_MV)
831
zero_ao.value = 0; zero_ao.marker = 0;
833
size_ao = zero_ao; size_ao.value = -1;
834
for (x=0; x<no_arrays; x++)
835
{ if (AO1.value == svals[array_symbols[x]])
836
{ size_ao.value = array_sizes[x]; y=x;
839
if (size_ao.value==-1) compiler_error("Array size can't be found");
841
type_ao = zero_ao; type_ao.value = array_types[y];
843
if ((!is_systemfile()))
846
if ((array_types[y] == WORD_ARRAY)
847
|| (array_types[y] == TABLE_ARRAY))
848
warning("Using '->' to access a --> or table array");
852
if ((array_types[y] == BYTE_ARRAY)
853
|| (array_types[y] == STRING_ARRAY))
854
warning("Using '-->' to access a -> or string array");
859
if ((!runtime_error_checking_switch) || (veneer_mode))
861
assembleg_3(oc, AO1, AO2, AO3);
865
/* If we recognise AO1 as arising textually from a declared
866
array, we can check bounds explicitly. */
868
if (AO1.marker == ARRAY_MV)
870
/* Calculate the largest permitted array entry + 1
871
Here "size_ao.value" = largest permitted entry of its own kind */
874
&& ((array_types[y] == WORD_ARRAY)
875
|| (array_types[y] == TABLE_ARRAY)))
876
{ max_ao.value = size_ao.value*4 + 3;
880
&& ((array_types[y] == BYTE_ARRAY)
881
|| (array_types[y] == STRING_ARRAY)
882
|| (array_types[y] == BUFFER_ARRAY)))
883
{ max_ao.value = (size_ao.value-3)/4;
888
/* Can't write to the size entry in a string or table */
889
if (((array_types[y] == STRING_ARRAY)
890
|| (array_types[y] == TABLE_ARRAY))
892
{ if ((array_types[y] == TABLE_ARRAY) && data_len == 1)
894
else zero_ao.value = 1;
897
en_ao = zero_ao; en_ao.value = ABOUNDS_RTE;
899
switch(oc) { case aloadb_gc: en_ao.value = ABOUNDS_RTE; break;
900
case aload_gc: en_ao.value = ABOUNDS_RTE+1; break;
901
case astoreb_gc: en_ao.value = ABOUNDS_RTE+2; break;
902
case astore_gc: en_ao.value = ABOUNDS_RTE+3; break; }
904
set_constant_ot(&zero_ao);
905
set_constant_ot(&size_ao);
906
set_constant_ot(&max_ao);
907
set_constant_ot(&type_ao);
908
set_constant_ot(&en_ao);
910
/* If we recognize A02 as a constant, we can do the test right
912
if (is_constant_ot(AO2.type) && AO2.marker == 0) {
913
if (AO2.value < zero_ao.value || AO2.value >= max_ao.value) {
914
error("Array reference is out-of-bounds");
916
assembleg_3(oc, AO1, AO2, AO3);
920
passed_label = next_label++;
921
failed_label = next_label++;
922
final_label = next_label++;
925
if ((AO2.type == LOCALVAR_OT)&&(AO2.value == 0))
926
{ assembleg_store(temp_var2, AO2); /* ### could peek */
927
assembleg_store(AO2, temp_var2);
928
index_ao = temp_var2;
930
assembleg_2_branch(jlt_gc, index_ao, zero_ao, failed_label);
931
assembleg_2_branch(jlt_gc, index_ao, max_ao, passed_label);
932
assemble_label_no(failed_label);
934
an_ao = zero_ao; an_ao.value = y;
935
set_constant_ot(&an_ao);
936
five_ao = zero_ao; five_ao.value = 5;
937
set_constant_ot(&five_ao);
939
/* Call the error veneer routine. */
940
assembleg_store(stack_pointer, an_ao);
941
assembleg_store(stack_pointer, type_ao);
942
assembleg_store(stack_pointer, size_ao);
943
assembleg_store(stack_pointer, index_ao);
944
assembleg_store(stack_pointer, en_ao);
945
assembleg_3(call_gc, veneer_routine(RT__Err_VR),
946
five_ao, zero_operand);
948
/* We have to clear any of AO1, AO2, AO3 off the stack if
949
present, so that we can achieve the same effect on the stack
950
that executing the opcode would have had */
952
if ((AO1.type == LOCALVAR_OT) && (AO1.value == 0))
953
assembleg_2(copy_gc, stack_pointer, zero_operand);
954
if ((AO2.type == LOCALVAR_OT) && (AO2.value == 0))
955
assembleg_2(copy_gc, stack_pointer, zero_operand);
956
if ((AO3.type == LOCALVAR_OT) && (AO3.value == 0))
957
{ if ((oc == aloadb_gc) || (oc == aload_gc))
958
{ assembleg_store(AO3, zero_ao);
960
else assembleg_2(copy_gc, stack_pointer, zero_operand);
962
assembleg_jump(final_label);
964
assemble_label_no(passed_label);
965
assembleg_3(oc, AO1, AO2, AO3);
966
assemble_label_no(final_label);
970
/* Otherwise, compile a call to the veneer which verifies that
971
the proposed read/write is within dynamic Z-machine memory. */
974
case aloadb_gc: vr = RT__ChLDB_VR; break;
975
case aload_gc: vr = RT__ChLDW_VR; break;
976
case astoreb_gc: vr = RT__ChSTB_VR; break;
977
case astore_gc: vr = RT__ChSTW_VR; break;
980
if ((oc == aloadb_gc) || (oc == aload_gc))
981
assembleg_call_2(veneer_routine(vr), AO1, AO2, AO3);
983
assembleg_call_3(veneer_routine(vr), AO1, AO2, AO3, zero_operand);
986
static assembly_operand check_nonzero_at_runtime_g(assembly_operand AO1,
987
int error_label, int rte_number)
989
assembly_operand AO, AO2, AO3;
991
int check_sp = FALSE, passed_label, failed_label, last_label;
996
/* Assemble to code to check that the operand AO1 is ofclass Object:
997
if it is, execution should continue and the stack should be
998
unchanged. Otherwise, call the veneer's run-time-error routine
999
with the given error number, and then: if the label isn't -1,
1000
switch execution to this label, with the value popped from
1001
the stack if it was on the stack in the first place;
1002
if the label is -1, either replace the top of the stack with
1003
the constant symbol (class-object) Object.
1005
The Object has no parent, child or sibling, so that the
1006
built-in tree functions will safely return 0 on this object. */
1008
/* Sometimes we can already see that the object number is valid. */
1009
if (AO1.marker == OBJECT_MV &&
1010
((AO1.value >= 1) && (AO1.value <= no_objects))) {
1014
passed_label = next_label++;
1015
failed_label = next_label++;
1017
if ((AO1.type == LOCALVAR_OT) && (AO1.value == 0) && (AO1.marker == 0)) {
1018
/* That is, if AO1 is the stack pointer */
1020
assembleg_store(temp_var2, stack_pointer);
1021
assembleg_store(stack_pointer, temp_var2);
1028
if ((rte_number == IN_RTE) || (rte_number == HAS_RTE)
1029
|| (rte_number == PROPERTY_RTE) || (rte_number == PROP_NUM_RTE)
1030
|| (rte_number == PROP_ADD_RTE)) {
1032
/* Test if zero... */
1033
assembleg_1_branch(jz_gc, AO, failed_label);
1034
/* Test if first byte is 0x70... */
1035
assembleg_3(aloadb_gc, AO, zero_operand, stack_pointer);
1037
AO3.value = 0x70; /* type byte -- object */
1038
set_constant_ot(&AO3);
1039
assembleg_2_branch(jeq_gc, stack_pointer, AO3, passed_label);
1042
/* Test if zero... */
1043
assembleg_1_branch(jz_gc, AO, failed_label);
1044
/* Test if first byte is 0x70... */
1045
assembleg_3(aloadb_gc, AO, zero_operand, stack_pointer);
1047
AO3.value = 0x70; /* type byte -- object */
1048
set_constant_ot(&AO3);
1049
assembleg_2_branch(jne_gc, stack_pointer, AO3, failed_label);
1050
/* Test if inside the "Class" object... */
1051
AO3.type = BYTECONSTANT_OT;
1052
AO3.value = 5; /* object-offset: parent */
1054
assembleg_3(aload_gc, AO, AO3, stack_pointer);
1055
ln = symbol_index("Class", -1);
1056
AO3.value = svals[ln];
1057
AO3.marker = OBJECT_MV;
1058
AO3.type = CONSTANT_OT;
1059
assembleg_2_branch(jne_gc, stack_pointer, AO3, passed_label);
1062
assemble_label_no(failed_label);
1064
AO2.value = rte_number;
1065
set_constant_ot(&AO2);
1066
assembleg_call_2(veneer_routine(RT__Err_VR), AO2, AO1, zero_operand);
1068
if (error_label != -1) {
1069
/* Jump to the error label */
1070
if (error_label == -3) assembleg_1(return_gc, zero_operand);
1071
else if (error_label == -4) assembleg_1(return_gc, one_operand);
1072
else assembleg_jump(error_label);
1075
/* Build the symbol for "Object" */
1076
ln = symbol_index("Object", -1);
1077
AO2.value = svals[ln];
1078
AO2.marker = OBJECT_MV;
1079
AO2.type = CONSTANT_OT;
1082
assembleg_store(AO1, AO2);
1085
/* Store either "Object" or the operand's value in the temporary
1087
assembleg_store(temp_var2, AO2);
1088
last_label = next_label++;
1089
assembleg_jump(last_label);
1090
assemble_label_no(passed_label);
1091
assembleg_store(temp_var2, AO1);
1092
assemble_label_no(last_label);
1097
assemble_label_no(passed_label);
1101
static void compile_conditional_g(condclass *cc,
1102
assembly_operand AO1, assembly_operand AO2, int label, int flag)
1103
{ assembly_operand AO4;
1104
int the_zc, error_label = label,
1105
va_flag = FALSE, va_label;
1109
the_zc = (flag ? cc->posform : cc->negform);
1112
switch ((cc-condclasses)*2 + 500) {
1115
if (runtime_error_checking_switch) {
1117
error_label = next_label++;
1118
AO1 = check_nonzero_at_runtime(AO1, error_label, HAS_RTE);
1119
if (is_constant_ot(AO2.type) && AO2.marker == 0) {
1120
if ((AO2.value < 0) || (AO2.value >= NUM_ATTR_BYTES*8)) {
1121
error("'has'/'hasnt' applied to illegal attribute number");
1125
int pa_label = next_label++, fa_label = next_label++;
1126
assembly_operand en_ao, max_ao;
1128
if ((AO1.type == LOCALVAR_OT) && (AO1.value == 0)) {
1129
if ((AO2.type == LOCALVAR_OT) && (AO2.value == 0)) {
1130
assembleg_2(stkpeek_gc, zero_operand, temp_var1);
1131
assembleg_2(stkpeek_gc, one_operand, temp_var2);
1134
assembleg_2(stkpeek_gc, zero_operand, temp_var1);
1135
assembleg_store(temp_var2, AO2);
1139
assembleg_store(temp_var1, AO1);
1140
if ((AO2.type == LOCALVAR_OT) && (AO2.value == 0)) {
1141
assembleg_2(stkpeek_gc, zero_operand, temp_var2);
1144
assembleg_store(temp_var2, AO2);
1149
max_ao.value = NUM_ATTR_BYTES*8;
1150
set_constant_ot(&max_ao);
1151
assembleg_2_branch(jlt_gc, temp_var2, zero_operand, fa_label);
1152
assembleg_2_branch(jlt_gc, temp_var2, max_ao, pa_label);
1153
assemble_label_no(fa_label);
1155
en_ao.value = 19; /* INVALIDATTR_RTE */
1156
set_constant_ot(&en_ao);
1157
assembleg_store(stack_pointer, temp_var2);
1158
assembleg_store(stack_pointer, temp_var1);
1159
assembleg_store(stack_pointer, en_ao);
1160
assembleg_3(call_gc, veneer_routine(RT__Err_VR),
1161
three_operand, zero_operand);
1163
va_label = next_label++;
1164
assembleg_jump(va_label);
1165
assemble_label_no(pa_label);
1168
if (is_constant_ot(AO2.type) && AO2.marker == 0) {
1170
set_constant_ot(&AO2);
1175
AO4.type = BYTECONSTANT_OT;
1176
if ((AO1.type == LOCALVAR_OT) && (AO1.value == 0)) {
1177
if ((AO2.type == LOCALVAR_OT) && (AO2.value == 0))
1178
assembleg_0(stkswap_gc);
1179
assembleg_3(add_gc, AO2, AO4, stack_pointer);
1180
assembleg_0(stkswap_gc);
1183
assembleg_3(add_gc, AO2, AO4, stack_pointer);
1185
AO2 = stack_pointer;
1187
assembleg_3(aloadbit_gc, AO1, AO2, stack_pointer);
1188
the_zc = (flag ? jnz_gc : jz_gc);
1189
AO1 = stack_pointer;
1193
if (runtime_error_checking_switch) {
1195
error_label = next_label++;
1196
AO1 = check_nonzero_at_runtime(AO1, error_label, IN_RTE);
1200
AO4.type = BYTECONSTANT_OT;
1201
assembleg_3(aload_gc, AO1, AO4, stack_pointer);
1202
AO1 = stack_pointer;
1203
the_zc = (flag ? jeq_gc : jne_gc);
1207
assembleg_call_2(veneer_routine(OC__Cl_VR), AO1, AO2, stack_pointer);
1208
the_zc = (flag ? jnz_gc : jz_gc);
1209
AO1 = stack_pointer;
1213
assembleg_call_2(veneer_routine(OP__Pr_VR), AO1, AO2, stack_pointer);
1214
the_zc = (flag ? jnz_gc : jz_gc);
1215
AO1 = stack_pointer;
1219
error("condition not yet supported in Glulx");
1224
if (the_zc == jnz_gc || the_zc == jz_gc)
1225
assembleg_1_branch(the_zc, AO1, label);
1227
assembleg_2_branch(the_zc, AO1, AO2, label);
1228
if (error_label != label) assemble_label_no(error_label);
1229
if (va_flag) assemble_label_no(va_label);
1232
static void value_in_void_context(assembly_operand AO)
1235
value_in_void_context_z(AO);
1237
value_in_void_context_g(AO);
1241
extern assembly_operand check_nonzero_at_runtime(assembly_operand AO1,
1242
int error_label, int rte_number)
1245
return check_nonzero_at_runtime_z(AO1, error_label, rte_number);
1247
return check_nonzero_at_runtime_g(AO1, error_label, rte_number);
1250
static void generate_code_from(int n, int void_flag)
1252
/* When void, this must not leave anything on the stack. */
1254
int i, j, below, above, opnum, arity; assembly_operand Result;
1256
below = ET[n].down; above = ET[n].up;
1258
{ if ((void_flag) && (ET[n].value.type != OMITTED_OT))
1259
value_in_void_context(ET[n].value);
1263
opnum = ET[n].operator_number;
1265
if (opnum == COMMA_OP)
1266
{ generate_code_from(below, TRUE);
1267
generate_code_from(ET[below].right, void_flag);
1268
ET[n].value = ET[ET[below].right].value;
1269
goto OperatorGenerated;
1272
if ((opnum == LOGAND_OP) || (opnum == LOGOR_OP))
1273
{ generate_code_from(below, FALSE);
1274
generate_code_from(ET[below].right, FALSE);
1275
goto OperatorGenerated;
1280
/* Signifies a SETEQUALS_OP which has already been done */
1282
ET[n].down = -1; return;
1285
/* Note that (except in the cases of comma and logical and/or) it
1286
is essential to code generate the operands right to left, because
1287
of the peculiar way the Z-machine's stack works:
1291
(for instance) pulls to the first operand, then the second. So
1297
calculates (b+7)-(a*2), not the other way around (as would be more
1298
usual in stack machines evaluating expressions written in reverse
1299
Polish notation). (Basically this is because the Z-machine was
1300
designed to implement a LISP-like language naturally expressed
1301
in forward Polish notation: (PLUS 3 4), for instance.) */
1303
/* And the Glulx machine follows the Z-machine in this respect. */
1307
{ i = ET[i].right; arity++;
1309
for (j=arity;j>0;j--)
1313
{ k++; i = ET[i].right;
1315
generate_code_from(i, FALSE);
1319
/* Check this again, because code generation lower down may have
1320
stubbed it into -1 */
1322
if (ET[n].operator_number == -1)
1323
{ ET[n].down = -1; return;
1328
if (operators[opnum].opcode_number_z >= 400)
1330
/* Conditional terms such as '==': */
1332
int a = ET[n].true_label, b = ET[n].false_label,
1333
branch_away, branch_other,
1334
make_jump_away = FALSE, make_branch_label = FALSE;
1335
int oc = operators[opnum].opcode_number_z-400, flag = TRUE;
1337
if (oc >= 400) { oc = oc - 400; flag = FALSE; }
1339
if ((oc == je_zc) && (arity == 2))
1340
{ i = ET[ET[n].down].right;
1341
if ((ET[i].value.value == zero_operand.value)
1342
&& (ET[i].value.type == zero_operand.type))
1346
/* If the condition has truth state flag, branch to
1347
label a, and if not, to label b. Possibly one of a, b
1348
equals -1, meaning "continue from this instruction".
1350
branch_away is the label which is a branch away (the one
1351
which isn't immediately after) and flag is the truth
1352
state to branch there.
1354
Note that when multiple instructions are needed (because
1355
of the use of the 'or' operator) the branch_other label
1356
is created if need be.
1359
/* Reduce to the case where the branch_away label does exist: */
1361
if (a == -1) { a = b; b = -1; flag = !flag; }
1363
branch_away = a; branch_other = b;
1364
if (branch_other != -1) make_jump_away = TRUE;
1366
if ((((oc != je_zc)&&(arity > 2)) || (arity > 4)) && (flag == FALSE))
1368
/* In this case, we have an 'or' situation where multiple
1369
instructions are needed and where the overall condition
1370
is negated. That is, we have, e.g.
1372
if not (A cond B or C or D) then branch_away
1374
which we transform into
1376
if (A cond B) then branch_other
1377
if (A cond C) then branch_other
1378
if not (A cond D) then branch_away
1381
if (branch_other == -1)
1382
{ branch_other = next_label++; make_branch_label = TRUE;
1387
assemblez_1_branch(jz_zc, ET[below].value, branch_away, flag);
1389
{ assembly_operand left_operand;
1392
compile_conditional_z(oc, ET[below].value,
1393
ET[ET[below].right].value, branch_away, flag);
1395
{ /* The case of a condition using "or".
1396
First: if the condition tests the stack pointer,
1397
and it can't always be done in a single test, move
1398
the value off the stack and into temporary variable
1401
if (((ET[below].value.type == VARIABLE_OT)
1402
&& (ET[below].value.value == 0))
1403
&& ((oc != je_zc) || (arity>4)) )
1404
{ left_operand.type = VARIABLE_OT;
1405
left_operand.value = 255;
1406
left_operand.marker = 0;
1407
assemblez_store(left_operand, ET[below].value);
1409
else left_operand = ET[below].value;
1410
i = ET[below].right; arity--;
1412
/* "left_operand" now holds the quantity to be tested;
1413
"i" holds the right operand reached so far;
1414
"arity" the number of right operands. */
1417
{ if ((oc == je_zc) && (arity>1))
1419
/* je_zc is an especially good case since the
1420
Z-machine implements "or" for up to three
1421
right operands automatically, though it's an
1422
especially bad case to generate code for! */
1425
{ assemblez_3_branch(je_zc,
1426
left_operand, ET[i].value,
1427
ET[ET[i].right].value, branch_away, flag);
1428
i = ET[i].right; arity--;
1431
{ if ((arity == 3) || flag)
1432
assemblez_4_branch(je_zc, left_operand,
1434
ET[ET[i].right].value,
1435
ET[ET[ET[i].right].right].value,
1438
assemblez_4_branch(je_zc, left_operand,
1440
ET[ET[i].right].value,
1441
ET[ET[ET[i].right].right].value,
1442
branch_other, !flag);
1443
i = ET[ET[i].right].right; arity -= 2;
1447
{ /* Otherwise we can compare the left_operand with
1448
only one right operand at the time. There are
1449
two cases: it's the last right operand, or it
1452
if ((arity == 1) || flag)
1453
compile_conditional_z(oc, left_operand,
1454
ET[i].value, branch_away, flag);
1456
compile_conditional_z(oc, left_operand,
1457
ET[i].value, branch_other, !flag);
1459
i = ET[i].right; arity--;
1465
/* NB: These two conditions cannot both occur, fortunately! */
1467
if (make_branch_label) assemble_label_no(branch_other);
1468
if (make_jump_away) assemblez_jump(branch_other);
1470
goto OperatorGenerated;
1475
if (operators[opnum].opcode_number_g >= FIRST_CC
1476
&& operators[opnum].opcode_number_g <= LAST_CC) {
1477
/* Conditional terms such as '==': */
1479
int a = ET[n].true_label, b = ET[n].false_label;
1480
int branch_away, branch_other, flag,
1481
make_jump_away = FALSE, make_branch_label = FALSE;
1482
int ccode = operators[opnum].opcode_number_g;
1483
condclass *cc = &condclasses[(ccode-FIRST_CC) / 2];
1484
flag = (ccode & 1) ? 0 : 1;
1486
/* If the comparison is "equal to (constant) 0", change it
1487
to the simple "zero" test. Unfortunately, this doesn't
1488
work for the commutative form "(constant) 0 is equal to".
1489
At least I don't think it does. */
1491
if ((cc == &condclasses[1]) && (arity == 2)) {
1492
i = ET[ET[n].down].right;
1493
if ((ET[i].value.value == 0)
1494
&& (ET[i].value.marker == 0)
1495
&& is_constant_ot(ET[i].value.type)) {
1496
cc = &condclasses[0];
1500
/* If the condition has truth state flag, branch to
1501
label a, and if not, to label b. Possibly one of a, b
1502
equals -1, meaning "continue from this instruction".
1504
branch_away is the label which is a branch away (the one
1505
which isn't immediately after) and flag is the truth
1506
state to branch there.
1508
Note that when multiple instructions are needed (because
1509
of the use of the 'or' operator) the branch_other label
1510
is created if need be.
1513
/* Reduce to the case where the branch_away label does exist: */
1515
if (a == -1) { a = b; b = -1; flag = !flag; }
1517
branch_away = a; branch_other = b;
1518
if (branch_other != -1) make_jump_away = TRUE;
1520
if ((arity > 2) && (flag == FALSE)) {
1521
/* In this case, we have an 'or' situation where multiple
1522
instructions are needed and where the overall condition
1523
is negated. That is, we have, e.g.
1525
if not (A cond B or C or D) then branch_away
1527
which we transform into
1529
if (A cond B) then branch_other
1530
if (A cond C) then branch_other
1531
if not (A cond D) then branch_away
1534
if (branch_other == -1) {
1535
branch_other = next_label++; make_branch_label = TRUE;
1539
if (cc == &condclasses[0]) {
1540
assembleg_1_branch((flag ? cc->posform : cc->negform),
1541
ET[below].value, branch_away);
1545
compile_conditional_g(cc, ET[below].value,
1546
ET[ET[below].right].value, branch_away, flag);
1549
/* The case of a condition using "or".
1550
First: if the condition tests the stack pointer,
1551
and it can't always be done in a single test, move
1552
the value off the stack and into temporary variable
1555
assembly_operand left_operand;
1556
if (((ET[below].value.type == LOCALVAR_OT)
1557
&& (ET[below].value.value == 0))) {
1558
assembleg_store(temp_var1, ET[below].value);
1559
left_operand = temp_var1;
1562
left_operand = ET[below].value;
1564
i = ET[below].right;
1567
/* "left_operand" now holds the quantity to be tested;
1568
"i" holds the right operand reached so far;
1569
"arity" the number of right operands. */
1572
/* We can compare the left_operand with
1573
only one right operand at the time. There are
1574
two cases: it's the last right operand, or it
1577
if ((arity == 1) || flag)
1578
compile_conditional_g(cc, left_operand,
1579
ET[i].value, branch_away, flag);
1581
compile_conditional_g(cc, left_operand,
1582
ET[i].value, branch_other, !flag);
1590
/* NB: These two conditions cannot both occur, fortunately! */
1592
if (make_branch_label) assemble_label_no(branch_other);
1593
if (make_jump_away) assembleg_jump(branch_other);
1595
goto OperatorGenerated;
1600
/* The operator is now definitely one which produces a value */
1602
if (void_flag && (!(operators[opnum].side_effect)))
1603
error_named("Evaluating this has no effect:",
1604
operators[opnum].description);
1606
/* Where shall we put the resulting value? (In Glulx, this could
1607
be smarter, and peg the result into ZEROCONSTANT.) */
1609
if (void_flag) Result = temp_var1; /* Throw it away */
1611
{ if ((above != -1) && (ET[above].operator_number == SETEQUALS_OP))
1613
/* If the node above is "set variable equal to", then
1614
make that variable the place to put the result, and
1615
delete the SETEQUALS_OP node since its effect has already
1616
been accomplished. */
1618
ET[above].operator_number = -1;
1619
Result = ET[ET[above].down].value;
1620
ET[above].value = Result;
1622
else Result = stack_pointer; /* Otherwise, put it on the stack */
1627
if (operators[opnum].opcode_number_z != -1)
1629
/* Operators directly translatable into Z-code opcodes: infix ops
1630
take two operands whereas pre/postfix operators take only one */
1632
if (operators[opnum].usage == IN_U)
1633
{ int o_n = operators[opnum].opcode_number_z;
1634
if (runtime_error_checking_switch && (!veneer_mode)
1635
&& ((o_n == div_zc) || (o_n == mod_zc)))
1636
{ assembly_operand by_ao, error_ao; int ln;
1637
by_ao = ET[ET[below].right].value;
1638
if ((by_ao.value != 0) && (by_ao.marker == 0)
1639
&& ((by_ao.type == SHORT_CONSTANT_OT)
1640
|| (by_ao.type == LONG_CONSTANT_OT)))
1641
assemblez_2_to(o_n, ET[below].value,
1645
assemblez_store(temp_var1, ET[below].value);
1646
assemblez_store(temp_var2, by_ao);
1648
assemblez_1_branch(jz_zc, temp_var2, ln, FALSE);
1649
error_ao.type = SHORT_CONSTANT_OT; error_ao.marker = 0;
1650
error_ao.value = DBYZERO_RTE;
1651
assemblez_2(call_vn_zc, veneer_routine(RT__Err_VR),
1653
assemblez_inc(temp_var2);
1654
assemble_label_no(ln);
1655
assemblez_2_to(o_n, temp_var1, temp_var2, Result);
1659
assemblez_2_to(o_n, ET[below].value,
1660
ET[ET[below].right].value, Result);
1664
assemblez_1_to(operators[opnum].opcode_number_z, ET[below].value,
1670
access_memory_z(loadb_zc, ET[below].value,
1671
ET[ET[below].right].value, Result);
1674
access_memory_z(loadw_zc, ET[below].value,
1675
ET[ET[below].right].value, Result);
1677
case UNARY_MINUS_OP:
1678
assemblez_2_to(sub_zc, zero_operand, ET[below].value, Result);
1681
assemblez_1_to(not_zc, ET[below].value, Result);
1685
{ assembly_operand AO = ET[below].value;
1686
if (runtime_error_checking_switch && (!veneer_mode))
1687
AO = check_nonzero_at_runtime(AO, -1, PROP_ADD_RTE);
1688
assemblez_2_to(get_prop_addr_zc, AO,
1689
ET[ET[below].right].value, temp_var1);
1690
if (!void_flag) write_result_z(Result, temp_var1);
1695
{ assembly_operand AO = ET[below].value;
1696
if (runtime_error_checking_switch && (!veneer_mode))
1697
AO = check_nonzero_at_runtime(AO, -1, PROP_NUM_RTE);
1698
assemblez_2_to(get_prop_addr_zc, AO,
1699
ET[ET[below].right].value, temp_var1);
1700
assemblez_1_branch(jz_zc, temp_var1, next_label++, TRUE);
1701
assemblez_1_to(get_prop_len_zc, temp_var1, temp_var1);
1702
assemble_label_no(next_label-1);
1703
if (!void_flag) write_result_z(Result, temp_var1);
1708
{ assembly_operand AO = ET[below].value;
1710
if (runtime_error_checking_switch && (!veneer_mode))
1711
assemblez_3_to(call_vs_zc, veneer_routine(RT__ChPR_VR),
1712
AO, ET[ET[below].right].value, temp_var1);
1714
assemblez_2_to(get_prop_zc, AO,
1715
ET[ET[below].right].value, temp_var1);
1716
if (!void_flag) write_result_z(Result, temp_var1);
1721
j=1; AI.operand[0] = veneer_routine(RV__Pr_VR);
1722
goto GenFunctionCallZ;
1724
j=1; AI.operand[0] = veneer_routine(RA__Pr_VR);
1725
goto GenFunctionCallZ;
1727
j=1; AI.operand[0] = veneer_routine(RL__Pr_VR);
1728
goto GenFunctionCallZ;
1729
case MESSAGE_SETEQUALS_OP:
1730
j=1; AI.operand[0] = veneer_routine(WV__Pr_VR);
1731
goto GenFunctionCallZ;
1732
case MESSAGE_INC_OP:
1733
j=1; AI.operand[0] = veneer_routine(IB__Pr_VR);
1734
goto GenFunctionCallZ;
1735
case MESSAGE_DEC_OP:
1736
j=1; AI.operand[0] = veneer_routine(DB__Pr_VR);
1737
goto GenFunctionCallZ;
1738
case MESSAGE_POST_INC_OP:
1739
j=1; AI.operand[0] = veneer_routine(IA__Pr_VR);
1740
goto GenFunctionCallZ;
1741
case MESSAGE_POST_DEC_OP:
1742
j=1; AI.operand[0] = veneer_routine(DA__Pr_VR);
1743
goto GenFunctionCallZ;
1745
j=1; AI.operand[0] = veneer_routine(RA__Sc_VR);
1746
goto GenFunctionCallZ;
1748
j=1; AI.operand[0] = veneer_routine(CA__Pr_VR);
1749
goto GenFunctionCallZ;
1750
case MESSAGE_CALL_OP:
1751
j=1; AI.operand[0] = veneer_routine(CA__Pr_VR);
1752
goto GenFunctionCallZ;
1758
if ((ET[below].value.type == VARIABLE_OT)
1759
&& (ET[below].value.value >= 256))
1760
{ int sf_number = ET[below].value.value - 256;
1762
i = ET[below].right;
1764
{ error("Argument to system function missing");
1765
AI.operand[0] = one_operand;
1766
AI.operand_count = 1;
1770
while (i != -1) { j++; i = ET[i].right; }
1772
if (((sf_number != INDIRECT_SYSF) &&
1773
(sf_number != RANDOM_SYSF) && (j > 1))
1774
|| ((sf_number == INDIRECT_SYSF) && (j>7)))
1776
error("System function given with too many arguments");
1778
if (sf_number != RANDOM_SYSF)
1780
i = ET[below].right;
1781
for (jcount = 0; jcount < j; jcount++)
1782
{ AI.operand[jcount] = ET[i].value;
1785
AI.operand_count = j;
1788
AI.store_variable_number = Result.value;
1789
AI.branch_label_number = -1;
1794
{ assembly_operand AO, AO2; int arg_c, arg_et;
1795
AO.value = j; AO.marker = 0;
1796
AO.type = SHORT_CONSTANT_OT;
1797
AO2.type = LONG_CONSTANT_OT;
1798
AO2.value = begin_word_array();
1799
AO2.marker = ARRAY_MV;
1801
for (arg_c=0, arg_et = ET[below].right;arg_c<j;
1802
arg_c++, arg_et = ET[arg_et].right)
1803
{ if (ET[arg_et].value.type == VARIABLE_OT)
1804
error("Only constants can be used as possible 'random' results");
1805
array_entry(arg_c, ET[arg_et].value);
1807
finish_array(arg_c);
1809
assemblez_1_to(random_zc, AO, temp_var1);
1810
assemblez_dec(temp_var1);
1811
assemblez_2_to(loadw_zc, AO2, temp_var1, Result);
1814
assemblez_1_to(random_zc,
1815
ET[ET[below].right].value, Result);
1819
{ assembly_operand AO;
1820
AO = ET[ET[below].right].value;
1821
if (runtime_error_checking_switch)
1822
AO = check_nonzero_at_runtime(AO, -1,
1824
assemblez_1_to(get_parent_zc, AO, Result);
1830
{ assembly_operand AO;
1831
AO = ET[ET[below].right].value;
1832
if (runtime_error_checking_switch)
1833
AO = check_nonzero_at_runtime(AO, -1,
1834
(sf_number==CHILD_SYSF)?CHILD_RTE:ELDEST_RTE);
1835
assemblez_objcode(get_child_zc,
1836
AO, Result, -2, TRUE);
1842
{ assembly_operand AO;
1843
AO = ET[ET[below].right].value;
1844
if (runtime_error_checking_switch)
1845
AO = check_nonzero_at_runtime(AO, -1,
1846
(sf_number==SIBLING_SYSF)
1847
?SIBLING_RTE:YOUNGER_RTE);
1848
assemblez_objcode(get_sibling_zc,
1849
AO, Result, -2, TRUE);
1854
j=0; i = ET[below].right;
1855
goto IndirectFunctionCallZ;
1858
{ assembly_operand AO;
1859
AO = ET[ET[below].right].value;
1860
if (runtime_error_checking_switch)
1861
AO = check_nonzero_at_runtime(AO, -1,
1863
assemblez_store(temp_var1, zero_operand);
1864
assemblez_objcode(get_child_zc,
1865
AO, stack_pointer, next_label+1, FALSE);
1866
assemble_label_no(next_label);
1867
assemblez_inc(temp_var1);
1868
assemblez_objcode(get_sibling_zc,
1869
stack_pointer, stack_pointer,
1871
assemble_label_no(next_label+1);
1872
assemblez_store(temp_var2, stack_pointer);
1873
if (!void_flag) write_result_z(Result, temp_var1);
1879
{ assembly_operand AO;
1880
AO = ET[ET[below].right].value;
1881
if (runtime_error_checking_switch)
1882
AO = check_nonzero_at_runtime(AO, -1,
1884
assemblez_objcode(get_child_zc,
1885
AO, temp_var1, next_label+1, FALSE);
1886
assemblez_1(push_zc, temp_var1);
1887
assemble_label_no(next_label);
1888
assemblez_store(temp_var1, stack_pointer);
1889
assemblez_objcode(get_sibling_zc,
1890
temp_var1, stack_pointer, next_label, TRUE);
1891
assemble_label_no(next_label+1);
1892
if (!void_flag) write_result_z(Result, temp_var1);
1898
assemblez_store(temp_var1, ET[ET[below].right].value);
1899
if (runtime_error_checking_switch)
1900
check_nonzero_at_runtime(temp_var1, -1,
1902
assemblez_1_to(get_parent_zc, temp_var1, temp_var3);
1903
assemblez_1_branch(jz_zc, temp_var3,next_label+1,TRUE);
1904
assemblez_store(temp_var2, temp_var3);
1905
assemblez_store(temp_var3, zero_operand);
1906
assemblez_objcode(get_child_zc,
1907
temp_var2, temp_var2, next_label, TRUE);
1908
assemble_label_no(next_label++);
1909
assemblez_2_branch(je_zc, temp_var1, temp_var2,
1911
assemblez_store(temp_var3, temp_var2);
1912
assemblez_objcode(get_sibling_zc,
1913
temp_var2, temp_var2, next_label - 1, TRUE);
1914
assemble_label_no(next_label++);
1915
if (!void_flag) write_result_z(Result, temp_var3);
1918
case METACLASS_SYSF:
1919
assemblez_2_to((version_number==3)?call_zc:call_vs_zc,
1920
veneer_routine(Metaclass_VR),
1921
ET[ET[below].right].value, Result);
1925
error("The glk() system function does not exist in Z-code");
1935
IndirectFunctionCallZ:
1937
while ((i != -1) && (j<8))
1938
{ AI.operand[j++] = ET[i].value;
1942
if ((j > 4) && (version_number == 3))
1943
{ error("A function may be called with at most 3 arguments");
1946
if ((j==8) && (i != -1))
1947
{ error("A function may be called with at most 7 arguments");
1950
AI.operand_count = j;
1952
if ((void_flag) && (version_number >= 5))
1953
{ AI.store_variable_number = -1;
1955
{ case 1: AI.internal_number = call_1n_zc; break;
1956
case 2: AI.internal_number = call_2n_zc; break;
1957
case 3: case 4: AI.internal_number = call_vn_zc; break;
1958
case 5: case 6: case 7: case 8:
1959
AI.internal_number = call_vn2_zc; break;
1963
{ AI.store_variable_number = Result.value;
1964
if (version_number == 3)
1965
AI.internal_number = call_zc;
1968
{ case 1: AI.internal_number = call_1s_zc; break;
1969
case 2: AI.internal_number = call_2s_zc; break;
1970
case 3: case 4: AI.internal_number = call_vs_zc; break;
1971
case 5: case 6: case 7: case 8:
1972
AI.internal_number = call_vs2_zc; break;
1976
AI.branch_label_number = -1;
1977
assemblez_instruction(&AI);
1981
assemblez_store(ET[below].value,
1982
ET[ET[below].right].value);
1983
if (!void_flag) write_result_z(Result, ET[below].value);
1986
case PROPERTY_SETEQUALS_OP:
1988
{ if (runtime_error_checking_switch)
1989
assemblez_4_to(call_zc, veneer_routine(RT__ChPS_VR),
1990
ET[below].value, ET[ET[below].right].value,
1991
ET[ET[ET[below].right].right].value, Result);
1993
{ assemblez_store(temp_var1,
1994
ET[ET[ET[below].right].right].value);
1995
assemblez_3(put_prop_zc, ET[below].value,
1996
ET[ET[below].right].value,
1998
write_result_z(Result, temp_var1);
2002
{ if (runtime_error_checking_switch && (!veneer_mode))
2003
assemblez_4(call_vn_zc, veneer_routine(RT__ChPS_VR),
2004
ET[below].value, ET[ET[below].right].value,
2005
ET[ET[ET[below].right].right].value);
2006
else assemblez_3(put_prop_zc, ET[below].value,
2007
ET[ET[below].right].value,
2008
ET[ET[ET[below].right].right].value);
2011
case ARROW_SETEQUALS_OP:
2013
{ assemblez_store(temp_var1,
2014
ET[ET[ET[below].right].right].value);
2015
access_memory_z(storeb_zc, ET[below].value,
2016
ET[ET[below].right].value,
2018
write_result_z(Result, temp_var1);
2020
else access_memory_z(storeb_zc, ET[below].value,
2021
ET[ET[below].right].value,
2022
ET[ET[ET[below].right].right].value);
2025
case DARROW_SETEQUALS_OP:
2027
{ assemblez_store(temp_var1,
2028
ET[ET[ET[below].right].right].value);
2029
access_memory_z(storew_zc, ET[below].value,
2030
ET[ET[below].right].value,
2032
write_result_z(Result, temp_var1);
2035
access_memory_z(storew_zc, ET[below].value,
2036
ET[ET[below].right].value,
2037
ET[ET[ET[below].right].right].value);
2041
assemblez_inc(ET[below].value);
2042
if (!void_flag) write_result_z(Result, ET[below].value);
2045
assemblez_dec(ET[below].value);
2046
if (!void_flag) write_result_z(Result, ET[below].value);
2049
if (!void_flag) write_result_z(Result, ET[below].value);
2050
assemblez_inc(ET[below].value);
2053
if (!void_flag) write_result_z(Result, ET[below].value);
2054
assemblez_dec(ET[below].value);
2058
assemblez_store(temp_var1, ET[below].value);
2059
assemblez_store(temp_var2, ET[ET[below].right].value);
2060
access_memory_z(loadb_zc, temp_var1, temp_var2, temp_var3);
2061
assemblez_inc(temp_var3);
2062
access_memory_z(storeb_zc, temp_var1, temp_var2, temp_var3);
2063
if (!void_flag) write_result_z(Result, temp_var3);
2067
assemblez_store(temp_var1, ET[below].value);
2068
assemblez_store(temp_var2, ET[ET[below].right].value);
2069
access_memory_z(loadb_zc, temp_var1, temp_var2, temp_var3);
2070
assemblez_dec(temp_var3);
2071
access_memory_z(storeb_zc, temp_var1, temp_var2, temp_var3);
2072
if (!void_flag) write_result_z(Result, temp_var3);
2075
case ARROW_POST_INC_OP:
2076
assemblez_store(temp_var1, ET[below].value);
2077
assemblez_store(temp_var2, ET[ET[below].right].value);
2078
access_memory_z(loadb_zc, temp_var1, temp_var2, temp_var3);
2079
if (!void_flag) write_result_z(Result, temp_var3);
2080
assemblez_inc(temp_var3);
2081
access_memory_z(storeb_zc, temp_var1, temp_var2, temp_var3);
2084
case ARROW_POST_DEC_OP:
2085
assemblez_store(temp_var1, ET[below].value);
2086
assemblez_store(temp_var2, ET[ET[below].right].value);
2087
access_memory_z(loadb_zc, temp_var1, temp_var2, temp_var3);
2088
if (!void_flag) write_result_z(Result, temp_var3);
2089
assemblez_dec(temp_var3);
2090
access_memory_z(storeb_zc, temp_var1, temp_var2, temp_var3);
2094
assemblez_store(temp_var1, ET[below].value);
2095
assemblez_store(temp_var2, ET[ET[below].right].value);
2096
access_memory_z(loadw_zc, temp_var1, temp_var2, temp_var3);
2097
assemblez_inc(temp_var3);
2098
access_memory_z(storew_zc, temp_var1, temp_var2, temp_var3);
2099
if (!void_flag) write_result_z(Result, temp_var3);
2103
assemblez_store(temp_var1, ET[below].value);
2104
assemblez_store(temp_var2, ET[ET[below].right].value);
2105
access_memory_z(loadw_zc, temp_var1, temp_var2, temp_var3);
2106
assemblez_dec(temp_var3);
2107
access_memory_z(storew_zc, temp_var1, temp_var2, temp_var3);
2108
if (!void_flag) write_result_z(Result, temp_var3);
2111
case DARROW_POST_INC_OP:
2112
assemblez_store(temp_var1, ET[below].value);
2113
assemblez_store(temp_var2, ET[ET[below].right].value);
2114
access_memory_z(loadw_zc, temp_var1, temp_var2, temp_var3);
2115
if (!void_flag) write_result_z(Result, temp_var3);
2116
assemblez_inc(temp_var3);
2117
access_memory_z(storew_zc, temp_var1, temp_var2, temp_var3);
2120
case DARROW_POST_DEC_OP:
2121
assemblez_store(temp_var1, ET[below].value);
2122
assemblez_store(temp_var2, ET[ET[below].right].value);
2123
access_memory_z(loadw_zc, temp_var1, temp_var2, temp_var3);
2124
if (!void_flag) write_result_z(Result, temp_var3);
2125
assemblez_dec(temp_var3);
2126
access_memory_z(storew_zc, temp_var1, temp_var2, temp_var3);
2129
case PROPERTY_INC_OP:
2130
assemblez_store(temp_var1, ET[below].value);
2131
assemblez_store(temp_var2, ET[ET[below].right].value);
2132
assemblez_2_to(get_prop_zc, temp_var1, temp_var2, temp_var3);
2133
assemblez_inc(temp_var3);
2134
if (runtime_error_checking_switch && (!veneer_mode))
2135
assemblez_4(call_vn_zc, veneer_routine(RT__ChPS_VR),
2136
temp_var1, temp_var2, temp_var3);
2137
else assemblez_3(put_prop_zc, temp_var1, temp_var2, temp_var3);
2138
if (!void_flag) write_result_z(Result, temp_var3);
2141
case PROPERTY_DEC_OP:
2142
assemblez_store(temp_var1, ET[below].value);
2143
assemblez_store(temp_var2, ET[ET[below].right].value);
2144
assemblez_2_to(get_prop_zc, temp_var1, temp_var2, temp_var3);
2145
assemblez_dec(temp_var3);
2146
if (runtime_error_checking_switch && (!veneer_mode))
2147
assemblez_4(call_vn_zc, veneer_routine(RT__ChPS_VR),
2148
temp_var1, temp_var2, temp_var3);
2149
else assemblez_3(put_prop_zc, temp_var1, temp_var2, temp_var3);
2150
if (!void_flag) write_result_z(Result, temp_var3);
2153
case PROPERTY_POST_INC_OP:
2154
assemblez_store(temp_var1, ET[below].value);
2155
assemblez_store(temp_var2, ET[ET[below].right].value);
2156
assemblez_2_to(get_prop_zc, temp_var1, temp_var2, temp_var3);
2157
if (!void_flag) write_result_z(Result, temp_var3);
2158
assemblez_inc(temp_var3);
2159
if (runtime_error_checking_switch && (!veneer_mode))
2160
assemblez_4(call_vn_zc, veneer_routine(RT__ChPS_VR),
2161
temp_var1, temp_var2, temp_var3);
2162
else assemblez_3(put_prop_zc, temp_var1, temp_var2, temp_var3);
2165
case PROPERTY_POST_DEC_OP:
2166
assemblez_store(temp_var1, ET[below].value);
2167
assemblez_store(temp_var2, ET[ET[below].right].value);
2168
assemblez_2_to(get_prop_zc, temp_var1, temp_var2, temp_var3);
2169
if (!void_flag) write_result_z(Result, temp_var3);
2170
assemblez_dec(temp_var3);
2171
if (runtime_error_checking_switch && (!veneer_mode))
2172
assemblez_4(call_vn_zc, veneer_routine(RT__ChPS_VR),
2173
temp_var1, temp_var2, temp_var3);
2174
else assemblez_3(put_prop_zc, temp_var1, temp_var2, temp_var3);
2178
printf("** Trouble op = %d i.e. '%s' **\n",
2179
opnum, operators[opnum].description);
2180
compiler_error("Expr code gen: Can't generate yet");
2184
assembly_operand AO, AO2;
2185
if (operators[opnum].opcode_number_g != -1)
2187
/* Operators directly translatable into opcodes: infix ops
2188
take two operands whereas pre/postfix operators take only one */
2190
if (operators[opnum].usage == IN_U)
2191
{ int o_n = operators[opnum].opcode_number_g;
2192
if (runtime_error_checking_switch && (!veneer_mode)
2193
&& ((o_n == div_gc) || (o_n == mod_gc)))
2194
{ assembly_operand by_ao, error_ao; int ln;
2195
by_ao = ET[ET[below].right].value;
2196
if ((by_ao.value != 0) && (by_ao.marker == 0)
2197
&& is_constant_ot(by_ao.type))
2198
assembleg_3(o_n, ET[below].value,
2201
{ assembleg_store(temp_var1, ET[below].value);
2202
assembleg_store(temp_var2, by_ao);
2204
assembleg_1_branch(jnz_gc, temp_var2, ln);
2205
error_ao.marker = 0;
2206
error_ao.value = DBYZERO_RTE;
2207
set_constant_ot(&error_ao);
2208
assembleg_call_1(veneer_routine(RT__Err_VR),
2209
error_ao, zero_operand);
2210
assembleg_store(temp_var2, one_operand);
2211
assemble_label_no(ln);
2212
assembleg_3(o_n, temp_var1, temp_var2, Result);
2216
assembleg_3(o_n, ET[below].value,
2217
ET[ET[below].right].value, Result);
2220
assembleg_2(operators[opnum].opcode_number_g, ET[below].value,
2228
if (ET[below].value.type == Result.type
2229
&& ET[below].value.value == Result.value
2230
&& ET[below].value.marker == Result.marker)
2232
assembleg_2(copy_gc, ET[below].value, Result);
2235
case UNARY_MINUS_OP:
2236
assembleg_2(neg_gc, ET[below].value, Result);
2239
assembleg_2(bitnot_gc, ET[below].value, Result);
2243
access_memory_g(aloadb_gc, ET[below].value,
2244
ET[ET[below].right].value, Result);
2247
access_memory_g(aload_gc, ET[below].value,
2248
ET[ET[below].right].value, Result);
2252
assembleg_store(ET[below].value,
2253
ET[ET[below].right].value);
2254
if (!void_flag) write_result_g(Result, ET[below].value);
2257
case ARROW_SETEQUALS_OP:
2259
{ assembleg_store(temp_var1,
2260
ET[ET[ET[below].right].right].value);
2261
access_memory_g(astoreb_gc, ET[below].value,
2262
ET[ET[below].right].value,
2264
write_result_g(Result, temp_var1);
2266
else access_memory_g(astoreb_gc, ET[below].value,
2267
ET[ET[below].right].value,
2268
ET[ET[ET[below].right].right].value);
2271
case DARROW_SETEQUALS_OP:
2273
{ assembleg_store(temp_var1,
2274
ET[ET[ET[below].right].right].value);
2275
access_memory_g(astore_gc, ET[below].value,
2276
ET[ET[below].right].value,
2278
write_result_g(Result, temp_var1);
2281
access_memory_g(astore_gc, ET[below].value,
2282
ET[ET[below].right].value,
2283
ET[ET[ET[below].right].right].value);
2287
assembleg_inc(ET[below].value);
2288
if (!void_flag) write_result_g(Result, ET[below].value);
2291
assembleg_dec(ET[below].value);
2292
if (!void_flag) write_result_g(Result, ET[below].value);
2295
if (!void_flag) write_result_g(Result, ET[below].value);
2296
assembleg_inc(ET[below].value);
2299
if (!void_flag) write_result_g(Result, ET[below].value);
2300
assembleg_dec(ET[below].value);
2304
assembleg_store(temp_var1, ET[below].value);
2305
assembleg_store(temp_var2, ET[ET[below].right].value);
2306
access_memory_g(aloadb_gc, temp_var1, temp_var2, temp_var3);
2307
assembleg_inc(temp_var3);
2308
access_memory_g(astoreb_gc, temp_var1, temp_var2, temp_var3);
2309
if (!void_flag) write_result_g(Result, temp_var3);
2313
assembleg_store(temp_var1, ET[below].value);
2314
assembleg_store(temp_var2, ET[ET[below].right].value);
2315
access_memory_g(aloadb_gc, temp_var1, temp_var2, temp_var3);
2316
assembleg_dec(temp_var3);
2317
access_memory_g(astoreb_gc, temp_var1, temp_var2, temp_var3);
2318
if (!void_flag) write_result_g(Result, temp_var3);
2321
case ARROW_POST_INC_OP:
2322
assembleg_store(temp_var1, ET[below].value);
2323
assembleg_store(temp_var2, ET[ET[below].right].value);
2324
access_memory_g(aloadb_gc, temp_var1, temp_var2, temp_var3);
2325
if (!void_flag) write_result_g(Result, temp_var3);
2326
assembleg_inc(temp_var3);
2327
access_memory_g(astoreb_gc, temp_var1, temp_var2, temp_var3);
2330
case ARROW_POST_DEC_OP:
2331
assembleg_store(temp_var1, ET[below].value);
2332
assembleg_store(temp_var2, ET[ET[below].right].value);
2333
access_memory_g(aloadb_gc, temp_var1, temp_var2, temp_var3);
2334
if (!void_flag) write_result_g(Result, temp_var3);
2335
assembleg_dec(temp_var3);
2336
access_memory_g(astoreb_gc, temp_var1, temp_var2, temp_var3);
2340
assembleg_store(temp_var1, ET[below].value);
2341
assembleg_store(temp_var2, ET[ET[below].right].value);
2342
access_memory_g(aload_gc, temp_var1, temp_var2, temp_var3);
2343
assembleg_inc(temp_var3);
2344
access_memory_g(astore_gc, temp_var1, temp_var2, temp_var3);
2345
if (!void_flag) write_result_g(Result, temp_var3);
2349
assembleg_store(temp_var1, ET[below].value);
2350
assembleg_store(temp_var2, ET[ET[below].right].value);
2351
access_memory_g(aload_gc, temp_var1, temp_var2, temp_var3);
2352
assembleg_dec(temp_var3);
2353
access_memory_g(astore_gc, temp_var1, temp_var2, temp_var3);
2354
if (!void_flag) write_result_g(Result, temp_var3);
2357
case DARROW_POST_INC_OP:
2358
assembleg_store(temp_var1, ET[below].value);
2359
assembleg_store(temp_var2, ET[ET[below].right].value);
2360
access_memory_g(aload_gc, temp_var1, temp_var2, temp_var3);
2361
if (!void_flag) write_result_g(Result, temp_var3);
2362
assembleg_inc(temp_var3);
2363
access_memory_g(astore_gc, temp_var1, temp_var2, temp_var3);
2366
case DARROW_POST_DEC_OP:
2367
assembleg_store(temp_var1, ET[below].value);
2368
assembleg_store(temp_var2, ET[ET[below].right].value);
2369
access_memory_g(aload_gc, temp_var1, temp_var2, temp_var3);
2370
if (!void_flag) write_result_g(Result, temp_var3);
2371
assembleg_dec(temp_var3);
2372
access_memory_g(astore_gc, temp_var1, temp_var2, temp_var3);
2377
AO = veneer_routine(RV__Pr_VR);
2378
goto TwoArgFunctionCall;
2381
AO = veneer_routine(RA__Pr_VR);
2382
goto TwoArgFunctionCall;
2385
AO = veneer_routine(RL__Pr_VR);
2386
goto TwoArgFunctionCall;
2389
case MESSAGE_CALL_OP:
2390
AO2 = veneer_routine(CA__Pr_VR);
2392
goto DoFunctionCall;
2394
case MESSAGE_INC_OP:
2395
case PROPERTY_INC_OP:
2396
AO = veneer_routine(IB__Pr_VR);
2397
goto TwoArgFunctionCall;
2398
case MESSAGE_DEC_OP:
2399
case PROPERTY_DEC_OP:
2400
AO = veneer_routine(DB__Pr_VR);
2401
goto TwoArgFunctionCall;
2402
case MESSAGE_POST_INC_OP:
2403
case PROPERTY_POST_INC_OP:
2404
AO = veneer_routine(IA__Pr_VR);
2405
goto TwoArgFunctionCall;
2406
case MESSAGE_POST_DEC_OP:
2407
case PROPERTY_POST_DEC_OP:
2408
AO = veneer_routine(DA__Pr_VR);
2409
goto TwoArgFunctionCall;
2411
AO = veneer_routine(RA__Sc_VR);
2412
goto TwoArgFunctionCall;
2416
assembly_operand AO2 = ET[below].value;
2417
assembly_operand AO3 = ET[ET[below].right].value;
2419
assembleg_call_2(AO, AO2, AO3, zero_operand);
2421
assembleg_call_2(AO, AO2, AO3, Result);
2425
case PROPERTY_SETEQUALS_OP:
2426
case MESSAGE_SETEQUALS_OP:
2427
if (runtime_error_checking_switch && (!veneer_mode))
2428
AO = veneer_routine(RT__ChPS_VR);
2430
AO = veneer_routine(WV__Pr_VR);
2433
assembly_operand AO2 = ET[below].value;
2434
assembly_operand AO3 = ET[ET[below].right].value;
2435
assembly_operand AO4 = ET[ET[ET[below].right].right].value;
2436
if (AO4.type == LOCALVAR_OT && AO4.value == 0) {
2437
/* Rightmost is on the stack; reduce to previous case. */
2438
if (AO2.type == LOCALVAR_OT && AO2.value == 0) {
2439
if (AO3.type == LOCALVAR_OT && AO3.value == 0) {
2440
/* both already on stack. */
2443
assembleg_store(stack_pointer, AO3);
2444
assembleg_0(stkswap_gc);
2448
if (AO3.type == LOCALVAR_OT && AO3.value == 0) {
2449
assembleg_store(stack_pointer, AO2);
2452
assembleg_store(stack_pointer, AO3);
2453
assembleg_store(stack_pointer, AO2);
2458
/* We have to get the rightmost on the stack, below the
2460
if (AO3.type == LOCALVAR_OT && AO3.value == 0) {
2461
if (AO2.type == LOCALVAR_OT && AO2.value == 0) {
2462
assembleg_store(stack_pointer, AO4);
2463
assembleg_2(stkroll_gc, three_operand, one_operand);
2466
assembleg_store(stack_pointer, AO4);
2467
assembleg_0(stkswap_gc);
2468
assembleg_store(stack_pointer, AO2);
2472
if (AO2.type == LOCALVAR_OT && AO2.value == 0) {
2473
assembleg_store(stack_pointer, AO4);
2474
assembleg_store(stack_pointer, AO3);
2475
assembleg_2(stkroll_gc, three_operand, two_operand);
2478
assembleg_store(stack_pointer, AO4);
2479
assembleg_store(stack_pointer, AO3);
2480
assembleg_store(stack_pointer, AO2);
2485
assembleg_3(call_gc, AO, three_operand, zero_operand);
2487
assembleg_3(call_gc, AO, three_operand, Result);
2494
if (ET[below].value.type == SYSFUN_OT)
2495
{ int sf_number = ET[below].value.value;
2497
i = ET[below].right;
2499
{ error("Argument to system function missing");
2500
AI.operand[0] = one_operand;
2501
AI.operand_count = 1;
2505
while (i != -1) { j++; i = ET[i].right; }
2507
if (((sf_number != INDIRECT_SYSF) &&
2508
(sf_number != GLK_SYSF) &&
2509
(sf_number != RANDOM_SYSF) && (j > 1)))
2511
error("System function given with too many arguments");
2513
if (sf_number != RANDOM_SYSF)
2515
i = ET[below].right;
2516
for (jcount = 0; jcount < j; jcount++)
2517
{ AI.operand[jcount] = ET[i].value;
2520
AI.operand_count = j;
2528
{ assembly_operand AO, AO2;
2532
set_constant_ot(&AO);
2533
AO2.type = CONSTANT_OT;
2534
AO2.value = begin_word_array();
2535
AO2.marker = ARRAY_MV;
2537
for (arg_c=0, arg_et = ET[below].right;arg_c<j;
2538
arg_c++, arg_et = ET[arg_et].right)
2539
{ if (ET[arg_et].value.type == LOCALVAR_OT
2540
|| ET[arg_et].value.type == GLOBALVAR_OT)
2541
error("Only constants can be used as possible 'random' results");
2542
array_entry(arg_c, ET[arg_et].value);
2544
finish_array(arg_c);
2546
assembleg_2(random_gc, AO, stack_pointer);
2547
assembleg_3(aload_gc, AO2, stack_pointer, Result);
2550
assembleg_2(random_gc,
2551
ET[ET[below].right].value, stack_pointer);
2552
assembleg_3(add_gc, stack_pointer, one_operand,
2558
{ assembly_operand AO;
2559
AO = ET[ET[below].right].value;
2560
if (runtime_error_checking_switch)
2561
AO = check_nonzero_at_runtime(AO, -1,
2563
AO2.type = BYTECONSTANT_OT;
2566
assembleg_3(aload_gc, AO, AO2, Result);
2572
{ assembly_operand AO;
2573
AO = ET[ET[below].right].value;
2574
if (runtime_error_checking_switch)
2575
AO = check_nonzero_at_runtime(AO, -1,
2576
(sf_number==CHILD_SYSF)?CHILD_RTE:ELDEST_RTE);
2577
AO2.type = BYTECONSTANT_OT;
2580
assembleg_3(aload_gc, AO, AO2, Result);
2586
{ assembly_operand AO;
2587
AO = ET[ET[below].right].value;
2588
if (runtime_error_checking_switch)
2589
AO = check_nonzero_at_runtime(AO, -1,
2590
(sf_number==SIBLING_SYSF)
2591
?SIBLING_RTE:YOUNGER_RTE);
2592
AO2.type = BYTECONSTANT_OT;
2595
assembleg_3(aload_gc, AO, AO2, Result);
2600
{ assembly_operand AO;
2601
AO = ET[ET[below].right].value;
2602
if (runtime_error_checking_switch)
2603
AO = check_nonzero_at_runtime(AO, -1,
2605
AO2.type = BYTECONSTANT_OT;
2608
assembleg_store(temp_var1, zero_operand);
2609
assembleg_3(aload_gc, AO, AO2, temp_var2);
2611
assemble_label_no(next_label);
2612
assembleg_1_branch(jz_gc, temp_var2, next_label+1);
2613
assembleg_3(add_gc, temp_var1, one_operand,
2615
assembleg_3(aload_gc, temp_var2, AO2, temp_var2);
2616
assembleg_0_branch(jump_gc, next_label);
2617
assemble_label_no(next_label+1);
2620
write_result_g(Result, temp_var1);
2625
i = ET[below].right;
2626
goto IndirectFunctionCallG;
2629
AO2 = veneer_routine(Glk__Wrap_VR);
2630
i = ET[below].right;
2631
goto DoFunctionCall;
2633
case METACLASS_SYSF:
2634
assembleg_call_1(veneer_routine(Metaclass_VR),
2635
ET[ET[below].right].value, Result);
2639
AO = ET[ET[below].right].value;
2640
if (runtime_error_checking_switch)
2641
AO = check_nonzero_at_runtime(AO, -1,
2645
AO2.type = BYTECONSTANT_OT;
2646
assembleg_3(aload_gc, AO, AO2, temp_var1);
2648
assembleg_1_branch(jz_gc, temp_var1, next_label+1);
2649
assemble_label_no(next_label);
2650
assembleg_3(aload_gc, temp_var1, AO2, temp_var2);
2651
assembleg_1_branch(jz_gc, temp_var2, next_label+1);
2652
assembleg_store(temp_var1, temp_var2);
2653
assembleg_0_branch(jump_gc, next_label);
2654
assemble_label_no(next_label+1);
2656
write_result_g(Result, temp_var1);
2661
AO = ET[ET[below].right].value;
2662
if (runtime_error_checking_switch)
2663
AO = check_nonzero_at_runtime(AO, -1,
2665
assembleg_store(temp_var3, AO);
2668
AO2.type = BYTECONSTANT_OT;
2669
assembleg_3(aload_gc, temp_var3, AO2, temp_var1);
2670
assembleg_1_branch(jz_gc, temp_var1, next_label+2);
2672
assembleg_3(aload_gc, temp_var1, AO2, temp_var1);
2673
assembleg_1_branch(jz_gc, temp_var1, next_label+2);
2674
assembleg_2_branch(jeq_gc, temp_var3, temp_var1,
2676
assemble_label_no(next_label);
2678
assembleg_3(aload_gc, temp_var1, AO2, temp_var2);
2679
assembleg_2_branch(jeq_gc, temp_var3, temp_var2,
2681
assembleg_store(temp_var1, temp_var2);
2682
assembleg_0_branch(jump_gc, next_label);
2683
assemble_label_no(next_label+1);
2684
assembleg_store(temp_var1, zero_operand);
2685
assemble_label_no(next_label+2);
2687
write_result_g(Result, temp_var1);
2692
error("*** system function not implemented ***");
2701
IndirectFunctionCallG:
2703
/* Get the function address. */
2710
/* If all the function arguments are in local/global
2711
variables, we have to push them all on the stack.
2712
If all of them are on the stack, we have to do nothing.
2713
If some are and some aren't, we have a hopeless mess,
2714
and we should throw a compiler error.
2720
/* begin part of patch G03701 */
2729
assembleg_2(callf_gc, AO2, void_flag ? zero_operand : Result);
2730
} else if (nargs==1) {
2731
assembleg_call_1(AO2, ET[i].value, void_flag ? zero_operand : Result);
2732
} else if (nargs==2) {
2733
assembly_operand o1 = ET[i].value;
2734
assembly_operand o2 = ET[ET[i].right].value;
2735
assembleg_call_2(AO2, o1, o2, void_flag ? zero_operand : Result);
2736
} else if (nargs==3) {
2737
assembly_operand o1 = ET[i].value;
2738
assembly_operand o2 = ET[ET[i].right].value;
2739
assembly_operand o3 = ET[ET[ET[i].right].right].value;
2740
assembleg_call_3(AO2, o1, o2, o3, void_flag ? zero_operand : Result);
2745
if (ET[i].value.type == LOCALVAR_OT
2746
&& ET[i].value.value == 0) {
2750
assembleg_store(stack_pointer, ET[i].value);
2757
if (onstack && offstack)
2758
error("*** Function call cannot be generated with mixed arguments ***");
2760
error("*** Function call cannot be generated with more than one nonstack argument ***");
2764
set_constant_ot(&AO);
2767
assembleg_3(call_gc, AO2, AO, zero_operand);
2769
assembleg_3(call_gc, AO2, AO, Result);
2771
} /* else nargs>=4 */
2772
} /* DoFunctionCall: */
2777
printf("** Trouble op = %d i.e. '%s' **\n",
2778
opnum, operators[opnum].description);
2779
compiler_error("Expr code gen: Can't generate yet");
2783
ET[n].value = Result;
2789
if (ET[n].to_expression)
2790
{ if (ET[n].true_label != -1)
2791
{ assemblez_1(push_zc, zero_operand);
2792
assemblez_jump(next_label++);
2793
assemble_label_no(ET[n].true_label);
2794
assemblez_1(push_zc, one_operand);
2795
assemble_label_no(next_label-1);
2798
{ assemblez_1(push_zc, one_operand);
2799
assemblez_jump(next_label++);
2800
assemble_label_no(ET[n].false_label);
2801
assemblez_1(push_zc, zero_operand);
2802
assemble_label_no(next_label-1);
2804
ET[n].value = stack_pointer;
2807
if (ET[n].label_after != -1)
2808
assemble_label_no(ET[n].label_after);
2813
if (ET[n].to_expression)
2814
{ if (ET[n].true_label != -1)
2815
{ assembleg_store(stack_pointer, zero_operand);
2816
assembleg_jump(next_label++);
2817
assemble_label_no(ET[n].true_label);
2818
assembleg_store(stack_pointer, one_operand);
2819
assemble_label_no(next_label-1);
2822
{ assembleg_store(stack_pointer, one_operand);
2823
assembleg_jump(next_label++);
2824
assemble_label_no(ET[n].false_label);
2825
assembleg_store(stack_pointer, zero_operand);
2826
assemble_label_no(next_label-1);
2828
ET[n].value = stack_pointer;
2831
if (ET[n].label_after != -1)
2832
assemble_label_no(ET[n].label_after);
2839
assembly_operand code_generate(assembly_operand AO, int context, int label)
2841
/* Used in three contexts: VOID_CONTEXT, CONDITION_CONTEXT and
2844
If CONDITION_CONTEXT, then compile code branching to label number
2845
"label" if the condition is false: there's no return value.
2846
(Except that if label is -3 or -4 (internal codes for rfalse and
2847
rtrue rather than branch) then this is for branching when the
2848
condition is true. This is used for optimising code generation
2849
for "if" statements.)
2851
Otherwise return the assembly operand containing the result
2852
(probably the stack pointer variable but not necessarily:
2853
e.g. is would be short constant 2 from the expression "j++, 2") */
2857
if (AO.type != EXPRESSION_OT)
2859
{ case VOID_CONTEXT:
2860
value_in_void_context(AO);
2861
AO.type = OMITTED_OT;
2864
case CONDITION_CONTEXT:
2866
if (label < -2) assemblez_1_branch(jz_zc, AO, label, FALSE);
2867
else assemblez_1_branch(jz_zc, AO, label, TRUE);
2871
assembleg_1_branch(jnz_gc, AO, label);
2873
assembleg_1_branch(jz_gc, AO, label);
2875
AO.type = OMITTED_OT;
2882
if (expr_trace_level >= 2)
2883
{ printf("Raw parse tree:\n"); show_tree(AO, FALSE);
2886
if (context == CONDITION_CONTEXT)
2887
{ if (label < -2) annotate_for_conditions(AO.value, label, -1);
2888
else annotate_for_conditions(AO.value, -1, label);
2890
else annotate_for_conditions(AO.value, -1, -1);
2892
if (expr_trace_level >= 1)
2893
{ printf("Code generation for expression in ");
2895
{ case VOID_CONTEXT: printf("void"); break;
2896
case CONDITION_CONTEXT: printf("condition"); break;
2897
case QUANTITY_CONTEXT: printf("quantity"); break;
2898
case ASSEMBLY_CONTEXT: printf("assembly"); break;
2899
case ARRAY_CONTEXT: printf("array initialisation"); break;
2900
default: printf("* ILLEGAL *"); break;
2902
printf(" context with annotated tree:\n");
2903
show_tree(AO, TRUE);
2906
generate_code_from(AO.value, (context==VOID_CONTEXT));
2907
return ET[AO.value].value;
2910
/* ========================================================================= */
2911
/* Data structure management routines */
2912
/* ------------------------------------------------------------------------- */
2914
extern void init_expressc_vars(void)
2918
extern void expressc_begin_pass(void)
2922
extern void expressc_allocate_arrays(void)
2926
extern void expressc_free_arrays(void)
2930
/* ========================================================================= */