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:
2023-11-03 19:07:10 +00:00
parent b5a1582976
commit fe7f26256b
2 changed files with 87 additions and 0 deletions

View File

@@ -433,3 +433,68 @@ inst_t *insts_read_bytecode_file(FILE *fp, size_t *ret)
free(darr.data); free(darr.data);
return instructions; 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;
}

View File

@@ -188,6 +188,28 @@ inst_t *insts_read_bytecode(darr_t *, size_t *);
void insts_write_bytecode_file(inst_t *, size_t, FILE *); void insts_write_bytecode_file(inst_t *, size_t, FILE *);
inst_t *insts_read_bytecode_file(FILE *, size_t *); 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_NOOP ((inst_t){0})
#define INST_HALT ((inst_t){.opcode = OP_HALT}) #define INST_HALT ((inst_t){.opcode = OP_HALT})