change to uint8_t for bytecode to reduce wasted bytes
This commit is contained in:
35
src/main.c
35
src/main.c
@@ -13,12 +13,15 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char FILE_IDENTIFIER[] = "ARBI";
|
||||
const uint64_t version_number = 0;
|
||||
const uint32_t version_number = 0;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
clock_t start,end;
|
||||
double time_spent;
|
||||
setlocale(LC_ALL, "");
|
||||
if (argc <= 1)
|
||||
return -1;
|
||||
@@ -35,37 +38,48 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
LexerState state = {path, file, 0, 0, &tokens};
|
||||
start = clock();
|
||||
lexer(state);
|
||||
end = clock();
|
||||
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||
printf("Lexer time taken: %f seconds\n", time_spent);
|
||||
fclose(state.file);
|
||||
|
||||
DArray ast;
|
||||
|
||||
darray_init(&ast, sizeof(ParsedValue));
|
||||
|
||||
|
||||
start = clock();
|
||||
parser(path, &ast, &tokens, false);
|
||||
end = clock();
|
||||
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||
printf("Parser time taken: %f seconds\n", time_spent);
|
||||
darray_free(&tokens, free_token);
|
||||
|
||||
Translated translated = init_translator();
|
||||
|
||||
|
||||
start = clock();
|
||||
translate(&translated, &ast);
|
||||
end = clock();
|
||||
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||
printf("Translation time taken: %f seconds\n", time_spent);
|
||||
|
||||
darray_free(&ast, free_parsed);
|
||||
|
||||
file = fopen("out.arbin", "wb");
|
||||
|
||||
uint64_t regCount = (uint64_t)translated.registerCount;
|
||||
uint64_t constantsSize = (uint64_t)translated.constants.size;
|
||||
uint64_t bytecodeSize = (uint64_t)translated.bytecode.size;
|
||||
|
||||
uint64_t version_number_htole64ed = htole64(version_number);
|
||||
regCount = htole64(regCount);
|
||||
regCount = htole64(regCount);
|
||||
uint32_t version_number_htole32ed = htole32(version_number);
|
||||
constantsSize = htole64(constantsSize);
|
||||
bytecodeSize = htole64(bytecodeSize);
|
||||
|
||||
fwrite(&FILE_IDENTIFIER, sizeof(char), strlen(FILE_IDENTIFIER), file);
|
||||
fwrite(&version_number_htole64ed, sizeof(uint64_t), 1, file);
|
||||
fwrite(®Count, sizeof(uint64_t), 1, file);
|
||||
fwrite(&version_number_htole32ed, sizeof(uint32_t), 1, file);
|
||||
fwrite(&translated.registerCount, sizeof(uint8_t), 1, file);
|
||||
fwrite(&constantsSize, sizeof(uint64_t), 1, file);
|
||||
fwrite(&bytecodeSize, sizeof(uint64_t), 1, file);
|
||||
fwrite(translated.constants.data, 1, translated.constants.size, file);
|
||||
@@ -77,8 +91,15 @@ int main(int argc, char *argv[]) {
|
||||
generate_siphash_key();
|
||||
|
||||
init_types();
|
||||
|
||||
start = clock();
|
||||
runtime(translated);
|
||||
|
||||
end = clock();
|
||||
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||
|
||||
printf("Execution time taken: %f seconds\n", time_spent);
|
||||
|
||||
free_translator(&translated);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
uint64_t bytes_to_uint64(const uint8_t bytes[8]) {
|
||||
uint64_t value = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
value |= ((uint64_t)bytes[i]) << (i * 8);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void init_types() {
|
||||
BASE_CLASS = init_argon_class("BASE_CLASS");
|
||||
|
||||
@@ -25,14 +33,22 @@ void init_types() {
|
||||
init_base_field();
|
||||
}
|
||||
|
||||
|
||||
uint8_t pop_byte(Translated *translated, RuntimeState *state) {
|
||||
return *((uint8_t *)darray_get(&translated->bytecode, state->head++));
|
||||
}
|
||||
|
||||
uint64_t pop_bytecode(Translated *translated, RuntimeState *state) {
|
||||
uint64_t *instruction = darray_get(&translated->bytecode, state->head++);
|
||||
return *instruction;
|
||||
uint8_t bytes[8];
|
||||
for (size_t i = 0; i < sizeof(bytes); i++) {
|
||||
bytes[i] = *((uint8_t *)darray_get(&translated->bytecode, state->head++));
|
||||
}
|
||||
return bytes_to_uint64(bytes);
|
||||
}
|
||||
|
||||
void load_const(Translated *translated, RuntimeState *state) {
|
||||
uint64_t to_register = pop_bytecode(translated, state);
|
||||
types type = pop_bytecode(translated, state);
|
||||
uint64_t to_register = pop_byte(translated, state);
|
||||
types type = pop_byte(translated, state);
|
||||
size_t length = pop_bytecode(translated, state);
|
||||
uint64_t offset = pop_bytecode(translated, state);
|
||||
|
||||
@@ -49,10 +65,10 @@ void load_const(Translated *translated, RuntimeState *state) {
|
||||
|
||||
void run_instruction(Translated *translated, RuntimeState *state,
|
||||
struct Stack stack) {
|
||||
OperationType opcode = pop_bytecode(translated, state);
|
||||
OperationType opcode = pop_byte(translated, state);
|
||||
switch (opcode) {
|
||||
case OP_LOAD_NULL:
|
||||
state->registers[pop_bytecode(translated, state)] = ARGON_NULL;
|
||||
state->registers[pop_byte(translated, state)] = ARGON_NULL;
|
||||
break;
|
||||
case OP_LOAD_CONST:
|
||||
load_const(translated, state);
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
# Bytecode Specification
|
||||
|
||||
all opcodes are uint8_t, and all operands are uint64_t unless marked with an asterisk (*), where it is marked as uint8_t
|
||||
|
||||
## OP_LOAD_CONST
|
||||
|
||||
loads and initialises a value from the constant buffer into the provided register.
|
||||
|
||||
this operation 4 operands.
|
||||
|
||||
1. the register to write to.
|
||||
2. the type of data from the constant buffer.
|
||||
1. the register to write to. (*)
|
||||
2. the type of data from the constant buffer. (*)
|
||||
3. the length of the data in the constant buffer.
|
||||
4. the offset in the constant buffer.
|
||||
|
||||
@@ -19,7 +21,7 @@ this operation takes 3 operands.
|
||||
|
||||
1. the length of the variable name.
|
||||
2. the offset in the constant buffer of the variable name.
|
||||
3. the register of the given value
|
||||
3. the register of the given value (*)
|
||||
|
||||
## OP_LOAD_NULL
|
||||
|
||||
@@ -27,7 +29,7 @@ sets a given register to null.
|
||||
|
||||
this operation takes 1 operand.
|
||||
|
||||
1. the register to set to null.
|
||||
1. the register to set to null. (*)
|
||||
|
||||
## OP_LOAD_FUNCTION
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ size_t translate_parsed_declaration(Translated *translated,
|
||||
size_t offset =
|
||||
arena_push(&translated->constants, singleDeclaration->name, length);
|
||||
|
||||
push_instruction_code(translated, OP_DECLARE);
|
||||
push_instruction_byte(translated, OP_DECLARE);
|
||||
push_instruction_code(translated, length);
|
||||
push_instruction_code(translated, offset);
|
||||
push_instruction_code(translated, 0);
|
||||
push_instruction_byte(translated, 0);
|
||||
}
|
||||
if (delcarations.size != 1) {
|
||||
push_instruction_code(translated, OP_LOAD_NULL);
|
||||
push_instruction_code(translated, 0);
|
||||
push_instruction_byte(translated, OP_LOAD_NULL);
|
||||
push_instruction_byte(translated, 0);
|
||||
}
|
||||
return first;
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
#include "function.h"
|
||||
#include "../translator.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
size_t translate_parsed_function(Translated *translated,
|
||||
ParsedFunction *parsedFunction) {
|
||||
DArray temp_bytecode;
|
||||
darray_init(&temp_bytecode, sizeof(uint64_t));
|
||||
DArray main_bytecode = translated->bytecode;
|
||||
translated->bytecode = temp_bytecode;
|
||||
DArray _temp_bytecode;
|
||||
darray_init(&_temp_bytecode, sizeof(uint8_t));
|
||||
translated->bytecode = _temp_bytecode;
|
||||
translate_parsed(translated, parsedFunction->body);
|
||||
size_t function_bytecode_offset =
|
||||
arena_push(&translated->constants, translated->bytecode.data,
|
||||
translated->bytecode.size*translated->bytecode.element_size);
|
||||
size_t function_bytecode_length = translated->bytecode.size;
|
||||
darray_free(&translated->bytecode, NULL);
|
||||
translated->bytecode = main_bytecode;
|
||||
darray_free(&temp_bytecode, NULL);
|
||||
size_t start = push_instruction_code(translated, OP_LOAD_FUNCTION);
|
||||
size_t start = push_instruction_byte(translated, OP_LOAD_FUNCTION);
|
||||
size_t offset = arena_push(&translated->constants, parsedFunction->name,
|
||||
strlen(parsedFunction->name));
|
||||
push_instruction_code(translated, offset);
|
||||
|
||||
@@ -10,10 +10,10 @@ size_t translate_parsed_number(Translated *translated, char *number_str, size_t
|
||||
size_t number_pos = arena_push(&translated->constants, number_str, length);
|
||||
set_registers(translated, to_register+1);
|
||||
|
||||
size_t start = push_instruction_code(translated, OP_LOAD_CONST);
|
||||
push_instruction_code(translated, to_register);
|
||||
size_t start = push_instruction_byte(translated, OP_LOAD_CONST);
|
||||
push_instruction_byte(translated, to_register);
|
||||
|
||||
push_instruction_code(translated, TYPE_OP_NUMBER);
|
||||
push_instruction_byte(translated, TYPE_OP_NUMBER);
|
||||
push_instruction_code(translated,length);
|
||||
push_instruction_code(translated, number_pos);
|
||||
return start;
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
size_t translate_parsed_string(Translated *translated, ParsedString parsedString) {
|
||||
size_t string_pos = arena_push(&translated->constants, parsedString.string, parsedString.length);
|
||||
set_registers(translated, 1);
|
||||
size_t start = push_instruction_code(translated, OP_LOAD_CONST);
|
||||
push_instruction_code(translated, 0);
|
||||
push_instruction_code(translated, TYPE_OP_STRING);
|
||||
size_t start = push_instruction_byte(translated, OP_LOAD_CONST);
|
||||
push_instruction_byte(translated, 0);
|
||||
push_instruction_byte(translated, TYPE_OP_STRING);
|
||||
push_instruction_code(translated,parsedString.length);
|
||||
push_instruction_code(translated, string_pos);
|
||||
return start;
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void uint64_to_bytes(uint64_t value, uint8_t bytes[8]) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
bytes[i] = (value >> (i * 8)) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void arena_init(ConstantArena *arena) {
|
||||
arena->data = checked_malloc(CHUNK_SIZE);
|
||||
arena->capacity = CHUNK_SIZE;
|
||||
@@ -56,25 +62,29 @@ size_t arena_push(ConstantArena *arena, const void *data, size_t length) {
|
||||
Translated init_translator() {
|
||||
Translated translated;
|
||||
translated.registerCount = 0;
|
||||
darray_init(&translated.bytecode, sizeof(uint64_t));
|
||||
darray_init(&translated.bytecode, sizeof(uint8_t));
|
||||
arena_init(&translated.constants);
|
||||
return translated;
|
||||
}
|
||||
|
||||
void set_instruction_code(Translated *translator, size_t offset,
|
||||
uint64_t code) {
|
||||
size_t *ptr = (translator->bytecode.data + offset);
|
||||
*ptr = code;
|
||||
}
|
||||
|
||||
size_t push_instruction_code(Translated *translator, uint64_t code) {
|
||||
code = htole64(code);
|
||||
size_t push_instruction_byte(Translated *translator, uint8_t byte) {
|
||||
size_t offset = translator->bytecode.size;
|
||||
darray_push(&translator->bytecode, &code);
|
||||
darray_push(&translator->bytecode, &byte);
|
||||
return offset;
|
||||
}
|
||||
|
||||
void set_registers(Translated *translator, size_t count) {
|
||||
size_t push_instruction_code(Translated *translator, uint64_t code) {
|
||||
size_t offset = translator->bytecode.size;
|
||||
uint8_t bytes[8];
|
||||
uint64_to_bytes(code, bytes);
|
||||
for (size_t i = 0; i < sizeof(bytes); i++) {
|
||||
darray_push(&translator->bytecode, &(bytes[i]));
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
void set_registers(Translated *translator, uint8_t count) {
|
||||
if (count > translator->registerCount)
|
||||
translator->registerCount = count;
|
||||
}
|
||||
@@ -91,8 +101,8 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue) {
|
||||
return translate_parsed_number(translated, (char *)parsedValue->data, 0);
|
||||
case AST_NULL:
|
||||
set_registers(translated, 1);
|
||||
size_t output = push_instruction_code(translated, OP_LOAD_NULL);
|
||||
push_instruction_code(translated, 0);
|
||||
size_t output = push_instruction_byte(translated, OP_LOAD_NULL);
|
||||
push_instruction_byte(translated, 0);
|
||||
return output;
|
||||
case AST_FUNCTION:
|
||||
return translate_parsed_function(translated,
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum { OP_LOAD_CONST = 255, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION } OperationType;
|
||||
typedef enum { TYPE_OP_STRING = 255, TYPE_OP_NUMBER } types;
|
||||
typedef enum { OP_LOAD_CONST, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION } OperationType;
|
||||
typedef enum { TYPE_OP_STRING, TYPE_OP_NUMBER } types;
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
@@ -17,7 +17,7 @@ typedef struct {
|
||||
} ConstantArena;
|
||||
|
||||
typedef struct {
|
||||
size_t registerCount;
|
||||
uint8_t registerCount;
|
||||
DArray bytecode;
|
||||
ConstantArena constants;
|
||||
} Translated;
|
||||
@@ -26,11 +26,11 @@ void *arena_get(ConstantArena *arena, size_t offset);
|
||||
|
||||
size_t arena_push(ConstantArena *arena, const void *data, size_t length);
|
||||
|
||||
void set_instruction_code(Translated * translator, size_t offset, uint64_t code);
|
||||
size_t push_instruction_byte(Translated *translator, uint8_t byte);
|
||||
|
||||
size_t push_instruction_code(Translated *translator, uint64_t code);
|
||||
|
||||
void set_registers(Translated *translator, size_t count);
|
||||
void set_registers(Translated *translator, uint8_t count);
|
||||
|
||||
Translated init_translator();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user