Defined a program structure
Essentially a "program header", followed by a count, followed by instructions. Provides a stronger format for bytecode files and allows for better bounds checking on instructions.
This commit is contained in:
65
lib/inst.c
65
lib/inst.c
@@ -433,3 +433,68 @@ inst_t *insts_read_bytecode_file(FILE *fp, size_t *ret)
|
||||
free(darr.data);
|
||||
return instructions;
|
||||
}
|
||||
|
||||
void prog_write_bytecode(prog_t *program, darr_t *buffer)
|
||||
{
|
||||
// Write program header
|
||||
darr_append_bytes(buffer, (byte *)&program->header, sizeof(program->header));
|
||||
// Write instruction count
|
||||
darr_append_bytes(buffer, (byte *)&program->count, sizeof(program->count));
|
||||
// Write instructions
|
||||
insts_write_bytecode(program->instructions, program->count, buffer);
|
||||
}
|
||||
|
||||
void prog_append_bytecode(prog_t *program, darr_t *buffer)
|
||||
{
|
||||
insts_write_bytecode(program->instructions, program->count, buffer);
|
||||
}
|
||||
|
||||
prog_t *prog_read_bytecode(darr_t *buffer)
|
||||
{
|
||||
// TODO: Error (not enough space for program header)
|
||||
if ((buffer->available - buffer->used) < sizeof(prog_header_t))
|
||||
return NULL;
|
||||
// Read program header
|
||||
prog_header_t header = {0};
|
||||
memcpy(&header, buffer->data + buffer->used, sizeof(header));
|
||||
buffer->used += sizeof(prog_header_t);
|
||||
// TODO: Error (not enough space for program instruction count)
|
||||
if ((buffer->available - buffer->used) < WORD_SIZE)
|
||||
return NULL;
|
||||
|
||||
// Read instruction count
|
||||
word count = convert_bytes_to_word(buffer->data + buffer->used);
|
||||
buffer->used += WORD_SIZE;
|
||||
prog_t *program = malloc(sizeof(*program) + (sizeof(inst_t) * count));
|
||||
size_t i;
|
||||
for (i = 0; i < count && (buffer->used < buffer->available); ++i)
|
||||
program->instructions[i] = inst_read_bytecode(buffer);
|
||||
|
||||
// TODO: Error (Expected more instructions)
|
||||
if (i < count - 1)
|
||||
{
|
||||
free(program);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
program->header = header;
|
||||
program->count = count;
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
void prog_write_file(prog_t *program, FILE *fp)
|
||||
{
|
||||
darr_t bytecode = {0};
|
||||
prog_write_bytecode(program, &bytecode);
|
||||
fwrite(bytecode.data, bytecode.used, 1, fp);
|
||||
free(bytecode.data);
|
||||
}
|
||||
|
||||
prog_t *prog_read_file(FILE *fp)
|
||||
{
|
||||
darr_t buffer = darr_read_file(fp);
|
||||
prog_t *p = prog_read_bytecode(&buffer);
|
||||
free(buffer.data);
|
||||
return p;
|
||||
}
|
||||
|
||||
22
lib/inst.h
22
lib/inst.h
@@ -188,6 +188,28 @@ inst_t *insts_read_bytecode(darr_t *, size_t *);
|
||||
void insts_write_bytecode_file(inst_t *, size_t, FILE *);
|
||||
inst_t *insts_read_bytecode_file(FILE *, size_t *);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
word start_address;
|
||||
} prog_header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
prog_header_t header;
|
||||
word count;
|
||||
inst_t instructions[];
|
||||
} prog_t;
|
||||
|
||||
// Write the entire program as bytecode
|
||||
void prog_write_bytecode(prog_t *, darr_t *);
|
||||
// Only append the instructions as bytecode
|
||||
void prog_append_bytecode(prog_t *, darr_t *);
|
||||
// Read an entire program as bytecode
|
||||
prog_t *prog_read_bytecode(darr_t *);
|
||||
|
||||
void prog_write_file(prog_t *, FILE *);
|
||||
prog_t *prog_read_file(FILE *);
|
||||
|
||||
#define INST_NOOP ((inst_t){0})
|
||||
#define INST_HALT ((inst_t){.opcode = OP_HALT})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user