parse.c 21.7 KB
Newer Older
1
#include <stdlib.h>
2
#include <string.h>
3

4
#include "abc_instructions.h"
5
#include "parse.h"
6
#include "util.h"
7

8 9 10 11
#ifdef INTERPRETER
# include "interpret.h"
#endif

12
#ifdef LINKER
13
# include "bcgen_instructions.h"
14 15
#endif

16 17
#ifdef PRELINKER
# include "bcprelink.h"
18 19
#endif

Camil Staps's avatar
Camil Staps committed
20 21 22 23 24 25 26 27
#ifdef LINK_CLEAN_RUNTIME
void preseed_symbol_matcher(struct parser *state, const char *label, void *location) {
       struct host_symbol *sym=find_host_symbol_by_name(state->program,(char*)label);
       if (sym!=NULL)
               sym->interpreter_location=location;
}
#endif

28 29 30 31 32
void init_parser(struct parser *state
#ifdef LINK_CLEAN_RUNTIME
		, int host_symbols_n, int host_symbols_string_length, char *host_symbols
#endif
		) {
Camil Staps's avatar
Camil Staps committed
33
	state->state = PS_init;
34
	state->program = safe_calloc(1, sizeof(struct program));
35 36 37

	state->ptr = 0;

38 39
	state->code_reloc_size = 0;
	state->data_reloc_size = 0;
40 41

	state->strings_size = 0;
42
#if defined(INTERPRETER) && WORD_WIDTH == 32
43 44 45
	state->read_n = 0;
	state->data_n_words = 0;
	state->words_in_strings = 0;
46
	state->strings = NULL;
47 48 49
	state->strings_ptr = 0;
	state->relocation_offset = 0;
#endif
50 51

	state->symbols_ptr = 0;
52

53
#ifdef LINK_CLEAN_RUNTIME
54 55 56
	state->program->host_symbols_n = host_symbols_n;
	state->program->host_symbols = safe_malloc(host_symbols_n * sizeof(struct host_symbol));
	state->program->host_symbols_strings = safe_malloc(host_symbols_string_length + host_symbols_n);
57

58
	char *symbol_strings = state->program->host_symbols_strings;
59 60 61
#ifdef MACH_O64
	BC_WORD offset=0;
#endif
62
	for (int i = 0; i < host_symbols_n; i++) {
63
		state->program->host_symbols[i].interpreter_location = (void*) -1;
64
		state->program->host_symbols[i].location = *(void**)host_symbols;
65
		host_symbols += IF_INT_64_OR_32(8,4);
66
		state->program->host_symbols[i].name = symbol_strings;
67 68 69 70
		for (; *host_symbols; host_symbols++)
			*symbol_strings++ = *host_symbols;
		*symbol_strings++ = '\0';
		host_symbols++;
71 72

#ifdef MACH_O64
73
		if (!strcmp(state->program->host_symbols[i].name,"__ARRAY__"))
74 75
			offset=(BC_WORD)&__ARRAY__-(BC_WORD)state->program->host_symbols[i].location;
#endif
76
	}
77 78 79 80
#ifdef MACH_O64
	for (int i=0; i<host_symbols_n; i++)
		state->program->host_symbols[i].location=(void*)((BC_WORD)state->program->host_symbols[i].location+offset);
#endif
81

82
	preseed_symbol_matcher(state, "INT", (void*) &INT);
Camil Staps's avatar
Camil Staps committed
83 84 85 86 87 88
	preseed_symbol_matcher(state, "dINT", (void*) &dINT);
	preseed_symbol_matcher(state, "BOOL", (void*) &BOOL);
	preseed_symbol_matcher(state, "CHAR", (void*) &CHAR);
	preseed_symbol_matcher(state, "REAL", (void*) &REAL);
	preseed_symbol_matcher(state, "__ARRAY__", (void*) &__ARRAY__);
	preseed_symbol_matcher(state, "__STRING__", (void*) &__STRING__);
89
	preseed_symbol_matcher(state, "e__system__nind", (void*) &__interpreter_indirection[5]);
90 91
#endif

92 93 94 95 96
#ifdef LINKER
	state->code_size = 0;
	state->data_size = 0;
	state->code_offset = 0;
	state->data_offset = 0;
97
	state->is_main_module = 0;
98
#endif
99

100 101 102 103 104
#ifdef INTERPRETER
	state->program->code_symbols_matching=NULL;
	state->program->data_symbols_matching=NULL;
#endif

105 106 107
#ifdef DEBUG_CURSES
	state->program->nr_instructions = 0;
#endif
108 109
}

110
void free_parser(struct parser *state) {
111
#if defined(INTERPRETER) && WORD_WIDTH == 32
112 113
	if (state->strings != NULL)
		free(state->strings);
114
#endif
115 116
}

117
void next_state(struct parser *state) {
118
	state->ptr = 0;
119
#if defined(INTERPRETER) && WORD_WIDTH == 32
120 121 122
	state->strings_ptr = 0;
	state->relocation_offset = 0;
#endif
123
	state->symbols_ptr = 0;
124

125
	switch (state->state) {
Camil Staps's avatar
Camil Staps committed
126
		case PS_init:
127
			state->state = PS_code;
128
#ifdef LINKER
129 130
			if (state->code_size > 0)
#else
131
			if (state->program->code_size > 0)
132
#endif
133 134
				return;
		case PS_code:
135 136 137 138
			state->state = PS_strings;
			if (state->strings_size > 0)
				return;
		case PS_strings:
139
			state->state = PS_data;
140
#ifdef LINKER
141 142
			if (state->data_size > 0)
#else
143
			if (state->program->data_size > 0)
144
#endif
145 146
				return;
		case PS_data:
147
			state->state = PS_symbol_table;
148 149 150 151
#ifdef LINKER
			state->new_label_nodes=safe_malloc(state->program->symbol_table_size*sizeof(struct label_node*));
			state->n_labels=0;
#endif
152 153 154
			if (state->program->symbol_table_size > 0)
				return;
		case PS_symbol_table:
155 156 157 158 159 160 161
#ifdef LINKER
			merge_new_labels_and_rebalance(state->new_label_nodes,state->n_labels);
			free(state->new_label_nodes);

			if (state->is_main_module && state->program->start_symbol_id<state->program->symbol_table_size)
				code_start(state->program->symbol_table[state->program->start_symbol_id].name);
#endif
162 163
			state->state = PS_code_reloc;
			if (state->code_reloc_size > 0)
164
				return;
165 166 167
		case PS_code_reloc:
			state->state = PS_data_reloc;
			if (state->data_reloc_size > 0)
168
				return;
169
		case PS_data_reloc:
170
		case PS_end:
171
#ifdef LINKER
172 173 174
			state->code_offset += state->code_size;
			state->data_offset += state->data_size;
#endif
175 176 177 178 179
			state->state = PS_end;
			return;
	}
}

180 181 182 183
void shift_address(BC_WORD *addr) {
	*addr = ((*addr << 1) & -7) | (*addr & 3);
}

184 185 186 187
/* Return values:
 * 0: success
 * 1: unexpected end of string/file
 * 2: illegal instruction
188 189 190
 * 3: internal state machine error
 * 4: wrong magic number
 * 5: wrong version number */
191
int parse_program(struct parser *state, struct char_provider *cp) {
192
	char elem8;
193 194 195
	int16_t elem16;
	int32_t elem32;
	int64_t elem64;
196

197 198
	while (state->state != PS_end) {
		switch (state->state) {
Camil Staps's avatar
Camil Staps committed
199
			case PS_init:
200
			{
201
				uint32_t header_length,code_size;
202 203 204 205 206 207 208 209 210

				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
				if (elem32 != ABC_MAGIC_NUMBER)
					return 4;

				if (provide_chars(&header_length, sizeof(header_length), 1, cp) < 0)
					return 1;

211 212
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
213 214 215 216 217 218 219
				header_length-=4;
				if (elem32 != ABC_VERSION)
					return 5;

				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
				header_length-=4;
220
#ifdef LINKER
221
				state->code_size = code_size = elem32;
222
#else
223
				state->program->code_size = code_size = elem32;
224
#endif
Camil Staps's avatar
Camil Staps committed
225

226 227
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
228
				header_length-=4;
229
#ifdef LINKER
230
				add_words_in_strings(elem32);
Camil Staps's avatar
Camil Staps committed
231
#elif defined(INTERPRETER) && WORD_WIDTH==32
232 233
				state->words_in_strings = elem32;
#endif
Camil Staps's avatar
Camil Staps committed
234

235 236
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
237
				header_length-=4;
238
				state->strings_size = elem32;
Camil Staps's avatar
Camil Staps committed
239
#if defined(INTERPRETER) && WORD_WIDTH == 32
240 241 242 243
				/* Allocate one more to prevent reading out of bounds in PS_data */
				state->strings = safe_malloc(sizeof(uint32_t*) * (elem32+1));
				state->strings[elem32] = 0;
#endif
Camil Staps's avatar
Camil Staps committed
244

245 246
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
247
				header_length-=4;
248
#ifdef LINKER
249 250
				state->data_size = elem32;
#else
Camil Staps's avatar
Camil Staps committed
251
# if defined(INTERPRETER) && WORD_WIDTH==32
252 253 254
				state->data_n_words = elem32;
				/* Allocate extra space because strings take more words on 32-bit */
				state->program->data_size = elem32 + state->words_in_strings;
255
# else
256
				state->program->data_size = elem32;
257
# endif
258 259
				state->program->code = safe_malloc(sizeof(BC_WORD) * (code_size+state->program->data_size));
				state->program->data = state->program->code + code_size;
260
#endif
Camil Staps's avatar
Camil Staps committed
261

262 263
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
264
				header_length-=4;
265 266 267 268
				state->program->symbol_table_size = elem32;
				state->program->symbol_table = safe_malloc(elem32 * sizeof(struct symbol));
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
269
				header_length-=4;
270
				state->program->symbols = safe_malloc(elem32 + state->program->symbol_table_size);
Camil Staps's avatar
Camil Staps committed
271

272 273
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
274
				header_length-=4;
275
				state->code_reloc_size = elem32;
Camil Staps's avatar
Camil Staps committed
276

277 278
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
279
				header_length-=4;
280
				state->data_reloc_size = elem32;
Camil Staps's avatar
Camil Staps committed
281

282 283
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
284
				header_length-=4;
285 286
				state->program->start_symbol_id = elem32;

287 288 289 290 291 292 293 294
				while (header_length >= sizeof(elem32)) {
					if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
						return 1;
					header_length -= sizeof(elem32);
				}
				if (header_length > 0 && provide_chars(&elem32, header_length, 1, cp) < 0)
					return 1;

295
				next_state(state);
296
				break;
297
			}
298
			case PS_code: {
299 300
				if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
					return 1;
301
#if 0
302
				EPRINTF(":%d\t%d\t%s %s\n", state->ptr, elem16, instruction_name(elem16), instruction_type(elem16));
303
#endif
304
#ifdef LINKER
305 306 307
				state->ptr++;
				store_code_elem(2, elem16);
#else
308 309 310
# ifdef COMPUTED_GOTOS
				state->program->code[state->ptr++] = (BC_WORD) instruction_labels[elem16];
# else
311
				state->program->code[state->ptr++] = elem16;
312
# endif
313 314 315
#endif
#ifdef DEBUG_CURSES
				state->program->nr_instructions++;
316
#endif
317
				const char *type = instruction_type(elem16);
318
				for (; *type; type++) {
319
#ifdef LINKER
320 321
					state->ptr++;
#endif
322
					switch (*type) {
323
						case 'I': /* Instruction */
324 325
							if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
								return 1;
326
#ifdef LINKER
327 328
							store_code_elem(2, elem16);
#else
329 330 331
# ifdef COMPUTED_GOTOS
							state->program->code[state->ptr++] = (BC_WORD) instruction_labels[elem16];
# else
332
							state->program->code[state->ptr++] = elem16;
333
# endif
334
#endif
335
							break;
336
						case 'n': /* Stack index */
337 338
							if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
								return 1;
339
#ifdef LINKER
340 341
							store_code_elem(2, elem16);
#else
342
							state->program->code[state->ptr++] = elem16;
343
#endif
344 345
							break;
						case 'N': /* Stack index, optimised to byte width */
346 347
							if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
								return 1;
348
#ifdef LINKER
349 350
							store_code_elem(2, elem16);
#else
351
							state->program->code[state->ptr++] = ((BC_WORD_S) elem16) * IF_INT_64_OR_32(8, 4);
352
#endif
353
							break;
354
						case 'a': /* Arity */
355 356
							if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
								return 1;
357
#ifdef LINKER
358 359
							store_code_elem(2, elem16);
#else
360
							/* Shift so that offset -1 contains the arity; this is used in the garbage collector */
361
							state->program->code[state->ptr++] = (BC_WORD) elem16 << IF_INT_64_OR_32(32, 0);
362
#endif
363
							break;
364
						case 'l': /* Label */
365
						case 'C': /* CAF label */
366 367
						case 'S': /* String label */
						case 's': /* String label */
368
							if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
369
								return 1;
370
#ifdef LINKER
371
							store_code_elem(2, elem16);
372
#else
373
							state->program->code[state->ptr++] = elem16;
374
#endif
375
							break;
376
						case 'r': /* Real */
377 378
							if (provide_chars(&elem64, sizeof(elem64), 1, cp) < 0)
								return 1;
379
#ifdef LINKER
380
							store_code_elem(8, elem64);
381
#else
382 383 384
# if (WORD_WIDTH == 64)
							state->program->code[state->ptr++] = elem64;
# else
385 386
							float f = *(double*)&elem64;
							state->program->code[state->ptr++] = *(BC_WORD*)&f;
387
# endif
388
#endif
389
							break;
390
						case 'c': /* Char */
391
							if (provide_chars(&elem8, sizeof(elem8), 1, cp) < 0)
392
								return 1;
393
#ifdef LINKER
394
							store_code_elem(1, elem8);
395
#else
396
							state->program->code[state->ptr++] = (unsigned char) elem8;
397
#endif
398
							break;
399
						case 'i':
400 401
							if (provide_chars(&elem64, sizeof(elem64), 1, cp) < 0)
								return 1;
402
#ifdef LINKER
403 404
							store_code_elem(8, elem64);
#else
405
							state->program->code[state->ptr++] = elem64;
406
#endif
407 408 409 410
							break;
						case '?':
							EPRINTF(":%d\t%d\t%s %s\n", state->ptr, elem16, instruction_name(elem16), instruction_type(elem16));
							EPRINTF("\tUnknown instruction; add to abc_instructions.c\n");
411 412
							EXIT((void*)-1,-1);
							return 2;
413 414
						default:
							EPRINTF("\tUnknown type character '%c' in type of %s\n",*type,instruction_name(elem16));
415 416
							EXIT((void*)-1,1);
							return 2;
417
					}
418
				}
419

420
#ifdef LINKER
421 422
				if (state->ptr >= state->code_size) {
#else
423
				if (state->ptr >= state->program->code_size) {
424
#endif
425 426 427
					state->ptr = 0;
					next_state(state);
				}
428
				break; }
429
			case PS_strings:
430 431
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
432
#ifdef LINKER
433
				add_string_information(elem32 + state->data_offset);
Camil Staps's avatar
Camil Staps committed
434
#elif defined(INTERPRETER) && WORD_WIDTH==32
435
				state->strings[state->ptr] = elem32;
436
#endif
437
				if (++state->ptr >= state->strings_size)
438 439 440
					next_state(state);
				break;
			case PS_data:
441 442
				if (provide_chars(&elem64, sizeof(elem64), 1, cp) < 0)
					return 1;
443
#ifdef LINKER
444 445 446
				store_data_l(elem64);
				state->ptr++;
#else
447
				state->program->data[state->ptr++] = elem64;
448
#endif
Camil Staps's avatar
Camil Staps committed
449
#if defined(INTERPRETER) && WORD_WIDTH==32
450 451 452 453 454 455
				/* On 64-bit, strings can be read as-is. On 32-bit, we need to
				 * read 64 bits and store them in two words. */
				if (state->strings[state->strings_ptr] == state->read_n) {
					int length = elem64;
					uint64_t bytes;
					while (length >= 8) {
456 457
						if (provide_chars(&bytes, sizeof(bytes), 1, cp) < 0)
							return 1;
458 459 460 461 462 463
						state->program->data[state->ptr++] = bytes & 0xffffffff;
						state->program->data[state->ptr++] = bytes >> 32;
						length -= 8;
						state->read_n++;
					}
					if (length > 0) {
464 465
						if (provide_chars(&bytes, sizeof(bytes), 1, cp) < 0)
							return 1;
466 467 468 469 470 471 472 473 474
						state->program->data[state->ptr++] = bytes & 0xffffffff;
						if (length > 4)
							state->program->data[state->ptr++] = bytes >> 32;
						state->read_n++;
					}
					state->strings_ptr++;
				}

				if (++state->read_n >= state->data_n_words)
475
#elif defined(LINKER)
476
				if (state->ptr >= state->data_size)
477 478 479
#else
				if (state->ptr >= state->program->data_size)
#endif
480
					next_state(state);
481
				break;
482 483 484 485
			case PS_symbol_table:
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
				state->program->symbol_table[state->ptr].offset = elem32;
486
#ifdef LINKER
487 488 489
				if (elem32 != -1)
					state->program->symbol_table[state->ptr].offset += (elem32 & 1 ? state->data_offset : state->code_offset) * 4;
#endif
490 491 492 493 494 495
				state->program->symbol_table[state->ptr].name = state->program->symbols + state->symbols_ptr;
				do {
					if (provide_chars(&elem8, sizeof(elem8), 1, cp) < 0)
						return 1;
					state->program->symbols[state->symbols_ptr++] = elem8;
				} while (elem8);
496
#if defined(INTERPRETER) || defined(PRELINKER)
497
# ifdef INTERPRETER
498
#  define INTERPRETER_OR_PRELINKER(i,u) i
499
# else
500
#  define INTERPRETER_OR_PRELINKER(i,u) (u*8)
501
# endif
502
				if (!strcmp(state->program->symbol_table[state->ptr].name, "__ARRAY__")) {
503
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&__ARRAY__,0);
504
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "__STRING__")) {
505
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&__STRING__,5);
506 507
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "INT") ||
						!strcmp(state->program->symbol_table[state->ptr].name, "dINT")) {
508
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&INT,25);
509
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "BOOL")) {
510
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&BOOL,10);
511
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "CHAR")) {
512
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&CHAR,15);
513
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "REAL")) {
514
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&REAL,20);
515
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "e__system__nind")) {
516
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&__interpreter_indirection[5], 136);
517
				} else if (state->program->symbol_table[state->ptr].offset == -1) {
518
# ifdef DEBUG_CLEAN_LINKS
519
					EPRINTF("Warning: symbol '%s' is not defined.\n",state->program->symbol_table[state->ptr].name);
520
# endif
521
				} else
522
				if (state->program->symbol_table[state->ptr].offset & 1) /* data symbol */ {
523
					state->program->symbol_table[state->ptr].offset &= -2;
524
# if (WORD_WIDTH == 64)
525
					state->program->symbol_table[state->ptr].offset *= 2;
526
# else
527 528 529 530 531 532 533 534 535 536 537
					/* code[elem32] is an offset to the abstract data segment.
					 * This offset is incorrect, because strings are longer on
					 * 32-bit. Thus, we add the required offset. This is not
					 * that efficient, but it's okay since it is only for
					 * 32-bit and only during parsing. */
					state->program->symbol_table[state->ptr].offset &= -2;
					int temp_relocation_offset = 0;
					for (int i = 0; state->program->symbol_table[state->ptr].offset / 4 > state->strings[i] && i < state->strings_size; i++)
						temp_relocation_offset += (state->program->data[state->strings[i] + temp_relocation_offset] + 3) / 8;
					state->program->symbol_table[state->ptr].offset += temp_relocation_offset * 4;
# endif
538
# ifdef INTERPRETER
539
					state->program->symbol_table[state->ptr].offset += (BC_WORD) state->program->data;
540
# elif defined(PRELINKER)
541
					state->program->symbol_table[state->ptr].offset += ((BC_WORD)state->program->code_size)*8+sizeof(prelinker_preamble);
542
# endif
543 544 545 546 547 548 549
# ifdef LINK_CLEAN_RUNTIME
					if (state->program->symbol_table[state->ptr].name[0]) {
						int v = ((BC_WORD*)state->program->symbol_table[state->ptr].offset)[-2];
						if (v == 0) {
							/* Descriptor has a code address that is not _hnf; ignore */
						} else if (v == -1) {
							/* Descriptor has a _hnf code address */
550
							struct host_symbol *host_sym = find_host_symbol_by_name(state->program, state->program->symbol_table[state->ptr].name);
551
							if (host_sym == NULL) {
552
#  ifdef DEBUG_CLEAN_LINKS
553
								EPRINTF("Warning: symbol '%s' not present in host\n",state->program->symbol_table[state->ptr].name);
554
#  endif
555 556 557 558
							} else {
								((BC_WORD*)state->program->symbol_table[state->ptr].offset)[-2] = (BC_WORD) host_sym->location;
								host_sym->interpreter_location = (BC_WORD*) state->program->symbol_table[state->ptr].offset;
							}
559 560
						} else {
							/* This shouldn't happen */
561
							EPRINTF("Parse error: %s should have -1/0 for descriptor resolve address\n",state->program->symbol_table[state->ptr].name);
562 563
							EXIT((void*)-1,1);
							return 2;
564
						}
565
					}
566 567 568 569
# endif
# ifdef DEBUG_CURSES
					if (!strcmp(state->program->symbol_table[state->ptr].name, "ARRAY"))
						ARRAY = (void*) state->program->symbol_table[state->ptr].offset;
570
# endif
571 572 573 574
				} else /* code symbol */ {
# if (WORD_WIDTH == 64)
					state->program->symbol_table[state->ptr].offset *= 2;
# endif
575
# ifdef INTERPRETER
576
					state->program->symbol_table[state->ptr].offset += (BC_WORD) state->program->code;
577
# elif defined(PRELINKER)
578
					state->program->symbol_table[state->ptr].offset += sizeof(prelinker_preamble);
579
# endif
580 581 582 583 584 585 586 587 588
# ifdef LINK_CLEAN_RUNTIME
					if (state->program->symbol_table[state->ptr].name[0]) {
						/* Descriptor has a _hnf code address */
						struct host_symbol *host_sym = find_host_symbol_by_name(state->program, state->program->symbol_table[state->ptr].name);
						if (host_sym != NULL) {
							host_sym->interpreter_location = (BC_WORD*) state->program->symbol_table[state->ptr].offset;
						}
					}
# endif
589
				}
590
#elif defined(LINKER)
591
				if (state->program->symbol_table[state->ptr].name[0] != '\0') {
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
					struct label *label=find_label(state->program->symbol_table[state->ptr].name);

					if (label==NULL) {
						label=safe_malloc(sizeof(struct label));
						label->label_name=safe_malloc(strlen(state->program->symbol_table[state->ptr].name)+1);
						strcpy(label->label_name,state->program->symbol_table[state->ptr].name);
						label->label_id=-1;
						label->label_offset=state->program->symbol_table[state->ptr].offset;
						label->label_module_n=-2;

						struct label_node *node=safe_malloc(sizeof(struct label_node));
						node->label_node_left=NULL;
						node->label_node_right=NULL;
						node->label_node_label_p=label;

						state->new_label_nodes[state->n_labels++]=node;
					} else {
						if (state->program->symbol_table[state->ptr].offset!=-1)
							label->label_offset=state->program->symbol_table[state->ptr].offset;
						make_label_global(label);
					}
613 614
				}
#endif
615 616 617
				if (++state->ptr >= state->program->symbol_table_size)
					next_state(state);
				break;
618 619 620 621 622 623 624 625
			case PS_code_reloc:
				{
					uint32_t code_i,sym_i;
					if (provide_chars(&code_i, sizeof(code_i), 1, cp) < 0)
						return 1;

					if (provide_chars(&sym_i, sizeof(sym_i), 1, cp) < 0)
						return 1;
626
					struct symbol *sym = &state->program->symbol_table[sym_i];
627

628
#ifdef LINKER
629
					struct label *label;
630 631 632
					if (sym->name[0] == '\0')
						label = new_label_at_offset(sym->offset);
					else
633
						label = enter_label(sym->name);
634
					add_code_relocation(label, code_i + state->code_offset);
635 636
#else
# if (WORD_WIDTH == 64)
637
					shift_address(&state->program->code[code_i]);
638
# endif
639
					state->program->code[code_i] += sym->offset;
640
#endif
641
				}
642 643 644 645

				if (++state->ptr >= state->code_reloc_size)
					next_state(state);
				break;
646 647 648 649 650 651 652 653
			case PS_data_reloc:
				{
					uint32_t data_i,sym_i;
					if (provide_chars(&data_i, sizeof(data_i), 1, cp) < 0)
						return 1;

					if (provide_chars(&sym_i, sizeof(sym_i), 1, cp) < 0)
						return 1;
654
					struct symbol *sym = &state->program->symbol_table[sym_i];
655

656
#ifdef LINKER
657
					struct label *label;
658 659 660
					if (sym->name[0] == '\0')
						label = new_label_at_offset(sym->offset);
					else
661
						label = enter_label(sym->name);
662
					add_data_relocation(label, data_i + state->data_offset);
663 664
#else
# if (WORD_WIDTH == 64)
665
					shift_address(&state->program->data[data_i]);
666
# endif
667

Camil Staps's avatar
Camil Staps committed
668
# if defined(INTERPRETER) && WORD_WIDTH==32
669 670 671 672 673 674 675
					/* data_i is an offset to the abstract data segment. We need to
					 * fix it up for the extra length of strings on 32-bit. */
					while (data_i >= state->strings[state->strings_ptr]) {
						state->relocation_offset += (state->program->data[state->strings[state->strings_ptr] + state->relocation_offset] + 3) / 8;
						state->strings_ptr++;
					}
					data_i += state->relocation_offset;
676
# endif
677

678
					state->program->data[data_i] += sym->offset;
679
#endif
680
				}
681 682 683 684

				if (++state->ptr >= state->data_reloc_size)
					next_state(state);
				break;
685 686 687
			default:
				return 3;
		}
688
	}
689 690 691 692

#ifdef LINK_CLEAN_RUNTIME
	sort_host_symbols_by_location(state->program);
#endif
693
	return 0;
694
}