/* "bpatch" : Keeps track of, and finally acts on, backpatch markers, */
/* correcting symbol values not known at compilation time */
/* */
-/* Part of Inform 6.35 */
-/* copyright (c) Graham Nelson 1993 - 2020 */
+/* Part of Inform 6.41 */
+/* copyright (c) Graham Nelson 1993 - 2022 */
/* */
/* Inform is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
#include "header.h"
-memory_block zcode_backpatch_table, staticarray_backpatch_table,
- zmachine_backpatch_table;
+uchar *staticarray_backpatch_table; /* Allocated to staticarray_backpatch_size */
+memory_list staticarray_backpatch_table_memlist;
+uchar *zmachine_backpatch_table; /* Allocated to zmachine_backpatch_size */
+memory_list zmachine_backpatch_table_memlist;
+uchar *zcode_backpatch_table; /* Allocated to zcode_backpatch_size */
+memory_list zcode_backpatch_table_memlist;
int32 zcode_backpatch_size, staticarray_backpatch_size,
zmachine_backpatch_size;
+/* ------------------------------------------------------------------------- */
+/* Marker values */
+/* ------------------------------------------------------------------------- */
+
+extern char *describe_mv(int mval)
+{ switch(mval)
+ { case NULL_MV: return("null");
+
+ /* Marker values used in ordinary story file backpatching */
+
+ case DWORD_MV: return("dictionary word");
+ case STRING_MV: return("string literal");
+ case INCON_MV: return("system constant");
+ case IROUTINE_MV: return("routine");
+ case VROUTINE_MV: return("veneer routine");
+ case ARRAY_MV: return("internal array");
+ case NO_OBJS_MV: return("the number of objects");
+ case INHERIT_MV: return("inherited common p value");
+ case INDIVPT_MV: return("indiv prop table address");
+ case INHERIT_INDIV_MV: return("inherited indiv p value");
+ case MAIN_MV: return("ref to Main");
+ case SYMBOL_MV: return("ref to symbol value");
+
+ /* Additional marker values used in Glulx backpatching
+ (IDENT_MV is not really used at all any more) */
+
+ case VARIABLE_MV: return("global variable");
+ case IDENT_MV: return("prop identifier number");
+ case ACTION_MV: return("action");
+ case OBJECT_MV: return("internal object");
+
+ }
+ return("** No such MV **");
+}
+
/* ------------------------------------------------------------------------- */
/* The mending operation */
/* ------------------------------------------------------------------------- */
ASSERT_ZCODE();
- if (asm_trace_level >= 4)
+ if (bpatch_trace_setting)
printf("BP %s applied to %04x giving ",
describe_mv(backpatch_marker), value);
break;
case VROUTINE_MV:
if ((value<0) || (value>=VENEER_ROUTINES))
- { if (no_link_errors > 0) break;
+ {
if (compiler_error
("Backpatch veneer routine number out of range"))
{ printf("Illegal BP veneer routine number: %d\n", value);
value = no_objects; break;
case INCON_MV:
if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
- { if (no_link_errors > 0) break;
+ {
if (compiler_error
("Backpatch system constant number out of range"))
{ printf("Illegal BP system constant number: %d\n", value);
value = value_of_system_constant(value); break;
case DWORD_MV:
value = dictionary_offset + 7 +
- final_dict_order[value]*((version_number==3)?7:9);
+ final_dict_order[value]*(DICT_ENTRY_BYTE_LENGTH);
break;
case ACTION_MV:
break;
break;
case MAIN_MV:
value = symbol_index("Main", -1);
- if (stypes[value] != ROUTINE_T)
+ if (symbols[value].type != ROUTINE_T)
error("No 'Main' routine has been defined");
- sflags[value] |= USED_SFLAG;
- value = svals[value];
+ symbols[value].flags |= USED_SFLAG;
+ value = symbols[value].value;
if (OMIT_UNUSED_ROUTINES)
value = df_stripped_address_for_address(value);
value += code_offset/scale_factor;
break;
case SYMBOL_MV:
if ((value<0) || (value>=no_symbols))
- { if (no_link_errors > 0) break;
+ {
if (compiler_error("Backpatch symbol number out of range"))
{ printf("Illegal BP symbol number: %d\n", value);
backpatch_error_flag = TRUE;
value = 0;
break;
}
- if (sflags[value] & UNKNOWN_SFLAG)
- { if (!(sflags[value] & UERROR_SFLAG))
- { sflags[value] |= UERROR_SFLAG;
+ if (symbols[value].flags & UNKNOWN_SFLAG)
+ { if (!(symbols[value].flags & UERROR_SFLAG))
+ { symbols[value].flags |= UERROR_SFLAG;
error_named_at("No such constant as",
- (char *) symbs[value], slines[value]);
+ symbols[value].name, symbols[value].line);
}
}
else
- if (sflags[value] & CHANGE_SFLAG)
- { sflags[value] &= (~(CHANGE_SFLAG));
- backpatch_marker = (svals[value]/0x10000);
+ if (symbols[value].flags & CHANGE_SFLAG)
+ { symbols[value].flags &= (~(CHANGE_SFLAG));
+ backpatch_marker = (symbols[value].marker);
if ((backpatch_marker < 0)
|| (backpatch_marker > LARGEST_BPATCH_MV))
{
- if (no_link_errors == 0)
- { compiler_error_named(
+ compiler_error_named(
"Illegal backpatch marker attached to symbol",
- (char *) symbs[value]);
- backpatch_error_flag = TRUE;
- }
+ symbols[value].name);
+ backpatch_error_flag = TRUE;
}
else
- svals[value] = backpatch_value_z((svals[value]) % 0x10000);
+ symbols[value].value = backpatch_value_z((symbols[value].value) % 0x10000);
}
- sflags[value] |= USED_SFLAG;
- { int t = stypes[value];
- value = svals[value];
+ symbols[value].flags |= USED_SFLAG;
+ { int t = symbols[value].type;
+ value = symbols[value].value;
switch(t)
{ case ROUTINE_T:
if (OMIT_UNUSED_ROUTINES)
}
break;
default:
- if (no_link_errors > 0) break;
if (compiler_error("Illegal backpatch marker"))
{ printf("Illegal backpatch marker %d value %04x\n",
backpatch_marker, value);
break;
}
- if (asm_trace_level >= 4) printf(" %04x\n", value);
+ if (bpatch_trace_setting) printf(" %04x\n", value);
return(value);
}
ASSERT_GLULX();
- if (asm_trace_level >= 4)
+ if (bpatch_trace_setting)
printf("BP %s applied to %04x giving ",
describe_mv(backpatch_marker), value);
break;
case VROUTINE_MV:
if ((value<0) || (value>=VENEER_ROUTINES))
- { if (no_link_errors > 0) break;
+ {
if (compiler_error
("Backpatch veneer routine number out of range"))
{ printf("Illegal BP veneer routine number: %d\n", value);
value = no_objects; break;
case INCON_MV:
if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
- { if (no_link_errors > 0) break;
+ {
if (compiler_error
("Backpatch system constant number out of range"))
{ printf("Illegal BP system constant number: %d\n", value);
break;
case MAIN_MV:
value = symbol_index("Main", -1);
- if (stypes[value] != ROUTINE_T)
+ if (symbols[value].type != ROUTINE_T)
error("No 'Main' routine has been defined");
- sflags[value] |= USED_SFLAG;
- value = svals[value];
+ symbols[value].flags |= USED_SFLAG;
+ value = symbols[value].value;
if (OMIT_UNUSED_ROUTINES)
value = df_stripped_address_for_address(value);
value += code_offset;
break;
case SYMBOL_MV:
if ((value<0) || (value>=no_symbols))
- { if (no_link_errors > 0) break;
+ {
if (compiler_error("Backpatch symbol number out of range"))
{ printf("Illegal BP symbol number: %d\n", value);
backpatch_error_flag = TRUE;
value = 0;
break;
}
- if (sflags[value] & UNKNOWN_SFLAG)
- { if (!(sflags[value] & UERROR_SFLAG))
- { sflags[value] |= UERROR_SFLAG;
+ if (symbols[value].flags & UNKNOWN_SFLAG)
+ { if (!(symbols[value].flags & UERROR_SFLAG))
+ { symbols[value].flags |= UERROR_SFLAG;
error_named_at("No such constant as",
- (char *) symbs[value], slines[value]);
+ symbols[value].name, symbols[value].line);
}
}
else
- if (sflags[value] & CHANGE_SFLAG)
- { sflags[value] &= (~(CHANGE_SFLAG));
- backpatch_marker = smarks[value];
+ if (symbols[value].flags & CHANGE_SFLAG)
+ { symbols[value].flags &= (~(CHANGE_SFLAG));
+ backpatch_marker = symbols[value].marker;
if ((backpatch_marker < 0)
|| (backpatch_marker > LARGEST_BPATCH_MV))
{
- if (no_link_errors == 0)
- { compiler_error_named(
+ compiler_error_named(
"Illegal backpatch marker attached to symbol",
- (char *) symbs[value]);
- backpatch_error_flag = TRUE;
- }
+ symbols[value].name);
+ backpatch_error_flag = TRUE;
}
else
- svals[value] = backpatch_value_g(svals[value]);
+ symbols[value].value = backpatch_value_g(symbols[value].value);
}
- sflags[value] |= USED_SFLAG;
- { int t = stypes[value];
- value = svals[value];
+ symbols[value].flags |= USED_SFLAG;
+ { int t = symbols[value].type;
+ value = symbols[value].value;
switch(t)
{
case ROUTINE_T:
break;
case CONSTANT_T:
case INDIVIDUAL_PROPERTY_T:
+ case PROPERTY_T:
/* value is unchanged */
break;
default:
}
break;
default:
- if (no_link_errors > 0) break;
if (compiler_error("Illegal backpatch marker"))
{ printf("Illegal backpatch marker %d value %04x\n",
backpatch_marker, value);
break;
}
- if (asm_trace_level >= 4) printf(" %04x\n", value);
+ if (bpatch_trace_setting) printf(" %04x\n", value);
return(value);
}
}
static void backpatch_zmachine_z(int mv, int zmachine_area, int32 offset)
-{ if (module_switch)
- { if (zmachine_area == PROP_DEFAULTS_ZA) return;
- }
- else
- { if (mv == OBJECT_MV) return;
- if (mv == IDENT_MV) return;
- if (mv == ACTION_MV) return;
- }
-
- /* printf("MV %d ZA %d Off %04x\n", mv, zmachine_area, offset); */
-
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, mv);
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, zmachine_area);
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, offset/256);
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, offset%256);
+{
+ if (mv == OBJECT_MV) return;
+ if (mv == IDENT_MV) return;
+ if (mv == ACTION_MV) return;
+
+ if (bpatch_trace_setting >= 2)
+ printf("BP added: MV %d ZA %d Off %04x\n", mv, zmachine_area, offset);
+
+ ensure_memory_list_available(&zmachine_backpatch_table_memlist, zmachine_backpatch_size+4);
+ zmachine_backpatch_table[zmachine_backpatch_size++] = mv;
+ zmachine_backpatch_table[zmachine_backpatch_size++] = zmachine_area;
+ zmachine_backpatch_table[zmachine_backpatch_size++] = offset/256;
+ zmachine_backpatch_table[zmachine_backpatch_size++] = offset%256;
}
static void backpatch_zmachine_g(int mv, int zmachine_area, int32 offset)
-{ if (module_switch)
- { if (zmachine_area == PROP_DEFAULTS_ZA) return;
- }
- else
- { if (mv == IDENT_MV) return;
- if (mv == ACTION_MV) return;
- }
+{
+ if (mv == IDENT_MV) return;
+ if (mv == ACTION_MV) return;
/* The backpatch table format for Glulx:
First, the marker byte.
Then the four-byte address.
*/
-/* printf("+MV %d ZA %d Off %06x\n", mv, zmachine_area, offset); */
-
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, mv);
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, zmachine_area);
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, (offset >> 24) & 0xFF);
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, (offset >> 16) & 0xFF);
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, (offset >> 8) & 0xFF);
- write_byte_to_memory_block(&zmachine_backpatch_table,
- zmachine_backpatch_size++, (offset) & 0xFF);
+ if (bpatch_trace_setting >= 2)
+ printf("BP added: MV %d ZA %d Off %06x\n", mv, zmachine_area, offset);
+
+ ensure_memory_list_available(&zmachine_backpatch_table_memlist, zmachine_backpatch_size+6);
+ zmachine_backpatch_table[zmachine_backpatch_size++] = mv;
+ zmachine_backpatch_table[zmachine_backpatch_size++] = zmachine_area;
+ zmachine_backpatch_table[zmachine_backpatch_size++] = (offset >> 24) & 0xFF;
+ zmachine_backpatch_table[zmachine_backpatch_size++] = (offset >> 16) & 0xFF;
+ zmachine_backpatch_table[zmachine_backpatch_size++] = (offset >> 8) & 0xFF;
+ zmachine_backpatch_table[zmachine_backpatch_size++] = (offset) & 0xFF;
}
extern void backpatch_zmachine(int mv, int zmachine_area, int32 offset)
backpatch_error_flag = FALSE;
while (bm < zmachine_backpatch_size)
{ backpatch_marker
- = read_byte_from_memory_block(&zmachine_backpatch_table, bm);
+ = zmachine_backpatch_table[bm];
zmachine_area
- = read_byte_from_memory_block(&zmachine_backpatch_table, bm+1);
+ = zmachine_backpatch_table[bm+1];
offset
- = 256*read_byte_from_memory_block(&zmachine_backpatch_table,bm+2)
- + read_byte_from_memory_block(&zmachine_backpatch_table, bm+3);
+ = 256*zmachine_backpatch_table[bm+2]
+ + zmachine_backpatch_table[bm+3];
bm += 4;
switch(zmachine_area)
case DYNAMIC_ARRAY_ZA: addr = variables_offset; break;
case STATIC_ARRAY_ZA: addr = static_arrays_offset; break;
default:
- if (no_link_errors == 0)
- if (compiler_error("Illegal area to backpatch"))
- backpatch_error_flag = TRUE;
+ if (compiler_error("Illegal area to backpatch"))
+ backpatch_error_flag = TRUE;
}
addr += offset;
if (backpatch_error_flag)
{ backpatch_error_flag = FALSE;
- if (no_link_errors == 0)
- printf("*** MV %d ZA %d Off %04x ***\n",
- backpatch_marker, zmachine_area, offset);
+ printf("*** MV %d ZA %d Off %04x ***\n",
+ backpatch_marker, zmachine_area, offset);
}
}
}
backpatch_error_flag = FALSE;
while (bm < zmachine_backpatch_size)
{ backpatch_marker
- = read_byte_from_memory_block(&zmachine_backpatch_table, bm);
+ = zmachine_backpatch_table[bm];
zmachine_area
- = read_byte_from_memory_block(&zmachine_backpatch_table, bm+1);
- offset = read_byte_from_memory_block(&zmachine_backpatch_table, bm+2);
+ = zmachine_backpatch_table[bm+1];
+ offset = zmachine_backpatch_table[bm+2];
offset = (offset << 8) |
- read_byte_from_memory_block(&zmachine_backpatch_table, bm+3);
+ zmachine_backpatch_table[bm+3];
offset = (offset << 8) |
- read_byte_from_memory_block(&zmachine_backpatch_table, bm+4);
+ zmachine_backpatch_table[bm+4];
offset = (offset << 8) |
- read_byte_from_memory_block(&zmachine_backpatch_table, bm+5);
- bm += 6;
-
- /* printf("-MV %d ZA %d Off %06x\n", backpatch_marker, zmachine_area, offset); */
+ zmachine_backpatch_table[bm+5];
+ bm += 6;
switch(zmachine_area) {
case PROP_DEFAULTS_ZA: addr = prop_defaults_offset+4; break;
case GLOBALVAR_ZA: addr = variables_offset; break;
/* STATIC_ARRAY_ZA is in ROM and therefore not handled here */
default:
- if (no_link_errors == 0)
if (compiler_error("Illegal area to backpatch"))
backpatch_error_flag = TRUE;
}
if (backpatch_error_flag)
{ backpatch_error_flag = FALSE;
- if (no_link_errors == 0)
- printf("*** MV %d ZA %d Off %04x ***\n",
- backpatch_marker, zmachine_area, offset);
+ printf("*** MV %d ZA %d Off %04x ***\n",
+ backpatch_marker, zmachine_area, offset);
}
}
}
/* ------------------------------------------------------------------------- */
extern void init_bpatch_vars(void)
-{ initialise_memory_block(&zcode_backpatch_table);
- initialise_memory_block(&staticarray_backpatch_table);
- initialise_memory_block(&zmachine_backpatch_table);
+{ zcode_backpatch_table = NULL;
+ staticarray_backpatch_table = NULL;
+ zmachine_backpatch_table = NULL;
}
extern void bpatch_begin_pass(void)
extern void bpatch_allocate_arrays(void)
{
+ initialise_memory_list(&zcode_backpatch_table_memlist,
+ sizeof(uchar), 128, (void**)&zcode_backpatch_table,
+ "code backpatch table");
+ initialise_memory_list(&staticarray_backpatch_table_memlist,
+ sizeof(uchar), 128, (void**)&staticarray_backpatch_table,
+ "static array backpatch table");
+ initialise_memory_list(&zmachine_backpatch_table_memlist,
+ sizeof(uchar), 128, (void**)&zmachine_backpatch_table,
+ "machine backpatch table");
}
extern void bpatch_free_arrays(void)
-{ deallocate_memory_block(&zcode_backpatch_table);
- deallocate_memory_block(&staticarray_backpatch_table);
- deallocate_memory_block(&zmachine_backpatch_table);
+{ deallocate_memory_list(&zcode_backpatch_table_memlist);
+ deallocate_memory_list(&staticarray_backpatch_table_memlist);
+ deallocate_memory_list(&zmachine_backpatch_table_memlist);
}
/* ========================================================================= */