bcprelink.c 4.87 KB
Newer Older
1 2 3 4
#include <inttypes.h>
#include <stdio.h>
#include <string.h>

5
#include "abc_instructions.h"
6 7 8 9 10 11
#include "util.h"
#include "parse.h"

const char usage[] = "Usage: %s FILE [-o FILE]\n";

enum section_type {
12
	ST_Preamble,
13 14 15 16 17
	ST_Code,
	ST_Data,
	ST_Start
};

18 19 20 21
#define _3chars2int(a,b,c)           ((uint64_t) (a+(b<<8)+(c<<16)))
#define _4chars2int(a,b,c,d)         ((uint64_t) (a+(b<<8)+(c<<16)+(d<<24)))
#define _7chars2int(a,b,c,d,e,f,g)   ((uint64_t) (a+(b<<8)+(c<<16)+(d<<24)+((uint64_t)e<<32)+((uint64_t)f<<40)+((uint64_t)g<<48)))
#define _8chars2int(a,b,c,d,e,f,g,h) ((uint64_t) (a+(b<<8)+(c<<16)+(d<<24)+((uint64_t)e<<32)+((uint64_t)f<<40)+((uint64_t)g<<48)+((uint64_t)h<<56)))
Camil Staps's avatar
Camil Staps committed
22
uint64_t prelinker_preamble[658] = {
23 24 25 26 27 28
	/*  0 */ 0, 0, 0, 7, _7chars2int('_','A','R','R','A','Y','_'),
	/*  5 */ 0, 0, 0, 8, _8chars2int('_','S','T','R','I','N','G','_'),
	/* 10 */ 0, 0, 0, 4, _4chars2int('B','O','O','L'),
	/* 15 */ 0, 0, 0, 4, _4chars2int('C','H','A','R'),
	/* 20 */ 0, 0, 0, 4, _4chars2int('R','E','A','L'),
	/* 25 */ 0, 0, 0, 3, _3chars2int('I','N','T'),
29 30 31 32
	/* 30 small integers */
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,
33 34 35 36 37 38 39 40 41 42
	/* 96 */ 0, 97*8, /* caf list */
	/* 98 */
		Cjmp_ap1,  Cjmp_ap2,  Cjmp_ap3,  Cjmp_ap4,  Cjmp_ap5,
		Cjmp_ap6,  Cjmp_ap7,  Cjmp_ap8,  Cjmp_ap9,  Cjmp_ap10,
		Cjmp_ap11, Cjmp_ap12, Cjmp_ap13, Cjmp_ap14, Cjmp_ap15,
		Cjmp_ap16, Cjmp_ap17, Cjmp_ap18, Cjmp_ap19, Cjmp_ap20,
		Cjmp_ap21, Cjmp_ap22, Cjmp_ap23, Cjmp_ap24, Cjmp_ap25,
		Cjmp_ap26, Cjmp_ap27, Cjmp_ap28, Cjmp_ap29, Cjmp_ap30,
		Cjmp_ap31, Cjmp_ap32,
	/* 130 */ Chalt, /* cycle in spine */
43 44 45 46
	/* 131 */ Cjsr_eval0, Cfill_a01_pop_rtn, Chalt, Chalt, -2, /* indirection */
		Cpush_node1, (131+1+5)*8, Cjsr_eval0, Cfill_a01_pop_rtn,
	/* 140 */ (141+1)*8+2, 0, 0, 0, 4, /* Nil */
		_4chars2int('_','N','i','l'),
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
	/* 146 static characters*/
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
	/* 658 */
65 66
};

67 68
void prepare_preamble(void) {
	for (int i=0; i<=32; i++) {
Camil Staps's avatar
Camil Staps committed
69 70
		prelinker_preamble[30+i*2]=26*8+2; /* INT+2 */
		prelinker_preamble[30+i*2+1]=i;
71 72 73
	}

	for (int i=0; i<256; i++) {
Camil Staps's avatar
Camil Staps committed
74 75
		prelinker_preamble[146+i*2]=16*8+2; /* CHAR+2 */
		prelinker_preamble[146+i*2+1]=i;
76 77 78
	}
}

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
void write_section(FILE *f, enum section_type type, uint32_t len, uint64_t *data) {
	fwrite(&type, 1, sizeof(uint32_t), f);
	fwrite(&len, 1, sizeof(uint32_t), f);
	fwrite(data, sizeof(uint64_t), len, f);
}

int main(int argc, char **argv) {
	char *output_file_name=NULL;
	FILE *input_file=NULL;

	for (int i=1; i<argc; i++) {
		if(!strcmp("-o", argv[i]) && i <= argc-1) {
			output_file_name=argv[i+1];
			i++;
		} else if (input_file!=NULL) {
			fprintf(stderr, usage, argv[0]);
			return -1;
		} else {
			input_file=fopen(argv[i], "rb");
			if (input_file==NULL) {
				fprintf(stderr, "Error: Could not open input file: %s\n", argv[i]);
				return -1;
			}
		}
	}

	if (input_file==NULL) {
		fprintf(stderr, usage, argv[0]);
		return -1;
	}

	struct parser state;
	init_parser(&state);

	struct char_provider cp;
	new_file_char_provider(&cp, input_file);
	int res=parse_program(&state, &cp);
	free_parser(&state);
	free_char_provider(&cp);
	if (res) {
		EPRINTF("Parsing failed (%d)\n", res);
		return res;
	}

	FILE *output_file=stdout;
	if(output_file_name!=NULL && (output_file=fopen(output_file_name, "wb"))==NULL) {
		fprintf(stderr, "Error: Could not open output file: %s\n", output_file_name);
		return -1;
	}

	struct program *program=state.program;

131
	prepare_preamble();
Camil Staps's avatar
Camil Staps committed
132
	write_section(output_file, ST_Preamble, sizeof(prelinker_preamble)/sizeof(uint64_t), prelinker_preamble);
133 134 135 136
	write_section(output_file, ST_Code, program->code_size, program->code);
	write_section(output_file, ST_Data, program->data_size, program->data);
	write_section(output_file, ST_Start, 1, &program->symbol_table[program->start_symbol_id].offset);

137 138
	fclose(output_file);

139 140
	return 0;
}