123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- /* ------------------------------------------------------------------------- */
- /* "bpatch" : Keeps track of, and finally acts on, backpatch markers, */
- /* correcting symbol values not known at compilation time */
- /* */
- /* Part of Inform 6.33 */
- /* copyright (c) Graham Nelson 1993 - 2014 */
- /* */
- /* ------------------------------------------------------------------------- */
- #include "header.h"
- memory_block zcode_backpatch_table, zmachine_backpatch_table;
- int32 zcode_backpatch_size, zmachine_backpatch_size;
- /* ------------------------------------------------------------------------- */
- /* The mending operation */
- /* ------------------------------------------------------------------------- */
- int backpatch_marker, backpatch_size, backpatch_error_flag;
- static int32 backpatch_value_z(int32 value)
- { /* Corrects the quantity "value" according to backpatch_marker */
- ASSERT_ZCODE();
- if (asm_trace_level >= 4)
- printf("BP %s applied to %04x giving ",
- describe_mv(backpatch_marker), value);
- switch(backpatch_marker)
- { case STRING_MV:
- value += strings_offset/scale_factor; break;
- case ARRAY_MV:
- value += variables_offset; break;
- case IROUTINE_MV:
- if (OMIT_UNUSED_ROUTINES)
- value = df_stripped_address_for_address(value);
- value += code_offset/scale_factor;
- 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);
- backpatch_error_flag = TRUE;
- }
- value = 0;
- break;
- }
- value = veneer_routine_address[value];
- if (OMIT_UNUSED_ROUTINES)
- value = df_stripped_address_for_address(value);
- value += code_offset/scale_factor;
- break;
- case NO_OBJS_MV:
- 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);
- backpatch_error_flag = TRUE;
- }
- value = 0;
- break;
- }
- value = value_of_system_constant(value); break;
- case DWORD_MV:
- value = dictionary_offset + 7 +
- final_dict_order[value]*((version_number==3)?7:9);
- break;
- case ACTION_MV:
- break;
- case INHERIT_MV:
- value = 256*zmachine_paged_memory[value + prop_values_offset]
- + zmachine_paged_memory[value + prop_values_offset + 1];
- break;
- case INHERIT_INDIV_MV:
- value = 256*zmachine_paged_memory[value
- + individuals_offset]
- + zmachine_paged_memory[value
- + individuals_offset + 1];
- break;
- case INDIVPT_MV:
- value += individuals_offset;
- break;
- case MAIN_MV:
- value = symbol_index("Main", -1);
- if (stypes[value] != ROUTINE_T)
- error("No 'Main' routine has been defined");
- sflags[value] |= USED_SFLAG;
- value = svals[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;
- error_named_at("No such constant as",
- (char *) symbs[value], slines[value]);
- }
- }
- else
- if (sflags[value] & CHANGE_SFLAG)
- { sflags[value] &= (~(CHANGE_SFLAG));
- backpatch_marker = (svals[value]/0x10000);
- if ((backpatch_marker < 0)
- || (backpatch_marker > LARGEST_BPATCH_MV))
- {
- if (no_link_errors == 0)
- { compiler_error_named(
- "Illegal backpatch marker attached to symbol",
- (char *) symbs[value]);
- backpatch_error_flag = TRUE;
- }
- }
- else
- svals[value] = backpatch_value_z((svals[value]) % 0x10000);
- }
- sflags[value] |= USED_SFLAG;
- { int t = stypes[value];
- value = svals[value];
- switch(t)
- { case ROUTINE_T:
- if (OMIT_UNUSED_ROUTINES)
- value = df_stripped_address_for_address(value);
- value += code_offset/scale_factor;
- break;
- case ARRAY_T: value += variables_offset; break;
- }
- }
- 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);
- backpatch_error_flag = TRUE;
- }
- break;
- }
- if (asm_trace_level >= 4) printf(" %04x\n", value);
- return(value);
- }
- static int32 backpatch_value_g(int32 value)
- { /* Corrects the quantity "value" according to backpatch_marker */
- int32 valaddr;
- ASSERT_GLULX();
- if (asm_trace_level >= 4)
- printf("BP %s applied to %04x giving ",
- describe_mv(backpatch_marker), value);
- switch(backpatch_marker)
- {
- case STRING_MV:
- if (value <= 0 || value > no_strings)
- compiler_error("Illegal string marker.");
- value = strings_offset + compressed_offsets[value-1]; break;
- case IROUTINE_MV:
- if (OMIT_UNUSED_ROUTINES)
- value = df_stripped_address_for_address(value);
- value += code_offset;
- break;
- case ARRAY_MV:
- value += arrays_offset; break;
- case VARIABLE_MV:
- value = variables_offset + (4*value); break;
- case OBJECT_MV:
- value = object_tree_offset + (OBJECT_BYTE_LENGTH*(value-1));
- 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);
- backpatch_error_flag = TRUE;
- }
- value = 0;
- break;
- }
- value = veneer_routine_address[value];
- if (OMIT_UNUSED_ROUTINES)
- value = df_stripped_address_for_address(value);
- value += code_offset;
- break;
- case NO_OBJS_MV:
- 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);
- backpatch_error_flag = TRUE;
- }
- value = 0;
- break;
- }
- value = value_of_system_constant(value); break;
- case DWORD_MV:
- value = dictionary_offset + 4
- + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
- break;
- case ACTION_MV:
- break;
- case INHERIT_MV:
- valaddr = (prop_values_offset - Write_RAM_At) + value;
- value = ReadInt32(zmachine_paged_memory + valaddr);
- break;
- case INHERIT_INDIV_MV:
- error("*** No individual property storage in Glulx ***");
- break;
- case INDIVPT_MV:
- value += individuals_offset;
- break;
- case MAIN_MV:
- value = symbol_index("Main", -1);
- if (stypes[value] != ROUTINE_T)
- error("No 'Main' routine has been defined");
- sflags[value] |= USED_SFLAG;
- value = svals[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;
- error_named_at("No such constant as",
- (char *) symbs[value], slines[value]);
- }
- }
- else
- if (sflags[value] & CHANGE_SFLAG)
- { sflags[value] &= (~(CHANGE_SFLAG));
- backpatch_marker = smarks[value];
- if ((backpatch_marker < 0)
- || (backpatch_marker > LARGEST_BPATCH_MV))
- {
- if (no_link_errors == 0)
- { compiler_error_named(
- "Illegal backpatch marker attached to symbol",
- (char *) symbs[value]);
- backpatch_error_flag = TRUE;
- }
- }
- else
- svals[value] = backpatch_value_g(svals[value]);
- }
- sflags[value] |= USED_SFLAG;
- { int t = stypes[value];
- value = svals[value];
- switch(t)
- {
- case ROUTINE_T:
- if (OMIT_UNUSED_ROUTINES)
- value = df_stripped_address_for_address(value);
- value += code_offset;
- break;
- case ARRAY_T: value += arrays_offset; break;
- case OBJECT_T:
- case CLASS_T:
- value = object_tree_offset +
- (OBJECT_BYTE_LENGTH*(value-1));
- break;
- case ATTRIBUTE_T:
- /* value is unchanged */
- break;
- case CONSTANT_T:
- case INDIVIDUAL_PROPERTY_T:
- /* value is unchanged */
- break;
- default:
- error("*** Illegal backpatch marker in forward-declared \
- symbol");
- break;
- }
- }
- 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);
- backpatch_error_flag = TRUE;
- }
- break;
- }
- if (asm_trace_level >= 4) printf(" %04x\n", value);
- return(value);
- }
- extern int32 backpatch_value(int32 value)
- {
- if (!glulx_mode)
- return backpatch_value_z(value);
- else
- return backpatch_value_g(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);
- }
- 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;
- }
- /* The backpatch table format for Glulx:
- First, the marker byte.
- Then, the zmachine area being patched.
- 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);
- }
- extern void backpatch_zmachine(int mv, int zmachine_area, int32 offset)
- {
- if (!glulx_mode)
- backpatch_zmachine_z(mv, zmachine_area, offset);
- else
- backpatch_zmachine_g(mv, zmachine_area, offset);
- }
- extern void backpatch_zmachine_image_z(void)
- { int bm = 0, zmachine_area; int32 offset, value, addr;
- ASSERT_ZCODE();
- backpatch_error_flag = FALSE;
- while (bm < zmachine_backpatch_size)
- { backpatch_marker
- = read_byte_from_memory_block(&zmachine_backpatch_table, bm);
- zmachine_area
- = read_byte_from_memory_block(&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);
- bm += 4;
- switch(zmachine_area)
- { case PROP_DEFAULTS_ZA: addr = prop_defaults_offset; break;
- case PROP_ZA: addr = prop_values_offset; break;
- case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
- case DYNAMIC_ARRAY_ZA: addr = variables_offset; break;
- default:
- if (no_link_errors == 0)
- if (compiler_error("Illegal area to backpatch"))
- backpatch_error_flag = TRUE;
- }
- addr += offset;
- value = 256*zmachine_paged_memory[addr]
- + zmachine_paged_memory[addr+1];
- value = backpatch_value_z(value);
- zmachine_paged_memory[addr] = value/256;
- zmachine_paged_memory[addr+1] = value%256;
- 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);
- }
- }
- }
- extern void backpatch_zmachine_image_g(void)
- { int bm = 0, zmachine_area; int32 offset, value, addr;
- ASSERT_GLULX();
- backpatch_error_flag = FALSE;
- while (bm < zmachine_backpatch_size)
- { backpatch_marker
- = read_byte_from_memory_block(&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);
- offset = (offset << 8) |
- read_byte_from_memory_block(&zmachine_backpatch_table, bm+3);
- offset = (offset << 8) |
- read_byte_from_memory_block(&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); */
- switch(zmachine_area) {
- case PROP_DEFAULTS_ZA: addr = prop_defaults_offset+4; break;
- case PROP_ZA: addr = prop_values_offset; break;
- case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
- case ARRAY_ZA: addr = arrays_offset; break;
- case GLOBALVAR_ZA: addr = variables_offset; break;
- default:
- if (no_link_errors == 0)
- if (compiler_error("Illegal area to backpatch"))
- backpatch_error_flag = TRUE;
- }
- addr = addr + offset - Write_RAM_At;
- value = (zmachine_paged_memory[addr] << 24)
- | (zmachine_paged_memory[addr+1] << 16)
- | (zmachine_paged_memory[addr+2] << 8)
- | (zmachine_paged_memory[addr+3]);
- value = backpatch_value_g(value);
- zmachine_paged_memory[addr] = (value >> 24) & 0xFF;
- zmachine_paged_memory[addr+1] = (value >> 16) & 0xFF;
- zmachine_paged_memory[addr+2] = (value >> 8) & 0xFF;
- zmachine_paged_memory[addr+3] = (value) & 0xFF;
- 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);
- }
- }
- }
- /* ========================================================================= */
- /* Data structure management routines */
- /* ------------------------------------------------------------------------- */
- extern void init_bpatch_vars(void)
- { initialise_memory_block(&zcode_backpatch_table);
- initialise_memory_block(&zmachine_backpatch_table);
- }
- extern void bpatch_begin_pass(void)
- { zcode_backpatch_size = 0;
- zmachine_backpatch_size = 0;
- }
- extern void bpatch_allocate_arrays(void)
- {
- }
- extern void bpatch_free_arrays(void)
- { deallocate_memory_block(&zcode_backpatch_table);
- deallocate_memory_block(&zmachine_backpatch_table);
- }
- /* ========================================================================= */
|