1
0
Fork 0

Optimizations, have return ask if it is a heap value, move lexer up

This commit is contained in:
zongor 2026-02-26 16:45:48 -08:00
parent fbff4dd188
commit 197b8ee0ef
19 changed files with 88 additions and 76 deletions

2
.clocignore Normal file
View File

@ -0,0 +1,2 @@
.ccls-cache/
build/

2
.gitignore vendored
View File

@ -108,3 +108,5 @@ build/
.gdb_history .gdb_history
.vscode .vscode
.clangd .clangd
.directory
perf.*

View File

@ -44,8 +44,8 @@ ifeq ($(BUILD_MODE), release)
LDFLAGS += -s LDFLAGS += -s
TARGET_SUFFIX := -release TARGET_SUFFIX := -release
else else
CORE_CFLAGS += -g -DDEBUG CORE_CFLAGS += -O0 -ggdb3 -fno-omit-frame-pointer -DDEBUG
PLATFORM_CFLAGS += -g -DDEBUG PLATFORM_CFLAGS += -O0 -ggdb3 -fno-omit-frame-pointer -DDEBUG
TARGET_SUFFIX := -debug TARGET_SUFFIX := -debug
endif endif
@ -91,14 +91,14 @@ ifeq ($(BUILD_MODE), release)
PLATFORM_SOURCE := $(ARCH_DIR)/main.c \ PLATFORM_SOURCE := $(ARCH_DIR)/main.c \
$(ARCH_DIR)/devices.c\ $(ARCH_DIR)/devices.c\
$(SRC_DIR)/tools/lexer.c \ $(SRC_DIR)/tools/lexer.c \
$(SRC_DIR)/tools/assembler/assembler.c \ $(SRC_DIR)/tools/assembler/assembler.c
$(SRC_DIR)/tools/compiler/compiler.c # $(SRC_DIR)/tools/compiler/compiler.c
else else
PLATFORM_SOURCE := $(ARCH_DIR)/main.c \ PLATFORM_SOURCE := $(ARCH_DIR)/main.c \
$(ARCH_DIR)/devices.c \ $(ARCH_DIR)/devices.c \
$(SRC_DIR)/tools/lexer.c \ $(SRC_DIR)/tools/lexer.c \
$(SRC_DIR)/tools/assembler/assembler.c \ $(SRC_DIR)/tools/assembler/assembler.c
$(SRC_DIR)/tools/compiler/compiler.c # $(SRC_DIR)/tools/compiler/compiler.c
endif endif
# --- OBJECT FILES --- # --- OBJECT FILES ---

View File

@ -1,4 +1,4 @@
#include "../../tools/compiler/compiler.h" //#include "../../tools/compiler/compiler.h"
#include "../../tools/assembler/assembler.h" #include "../../tools/assembler/assembler.h"
#include "../../vm/vm.h" #include "../../vm/vm.h"
#include "devices.h" #include "devices.h"
@ -225,8 +225,8 @@ bool compileAndSave(const char *source_file, const char *output_file, VM *vm) {
fclose(f); fclose(f);
ScopeTable table = {0}; ScopeTable table = {0};
symbol_table_init(&table); /* symbol_table_init(&table); */
compile(vm, &table, source); /* compile(vm, &table, source); */
#ifndef STATIC #ifndef STATIC
free(table.scopes); free(table.scopes);
#endif #endif
@ -340,7 +340,9 @@ i32 main(i32 argc, char *argv[]) {
&console_device_ops, 4); &console_device_ops, 4);
if (terminal_only_mode) { if (terminal_only_mode) {
while (step_vm(&vm)); while (step_vm(&vm)) {
//printf("code[%d] = %s\n", vm.pc, opcode_to_string(vm.code[vm.pc]));
}
return 0; return 0;
} }

View File

@ -163,7 +163,7 @@ void asm_emit_u32(VM *vm, u32 value) {
} }
Symbol *asm_symbol_table_lookup(ScopeTable *table, const char *name, u32 length, Symbol *asm_symbol_table_lookup(ScopeTable *table, const char *name, u32 length,
i32 scope_ref) { i32 scope_ref) {
SymbolTable st = table->scopes[scope_ref]; SymbolTable st = table->scopes[scope_ref];
for (u32 i = 0; i < st.count; i++) { for (u32 i = 0; i < st.count; i++) {
if (st.symbols[i].name_length == length) { if (st.symbols[i].name_length == length) {
@ -214,7 +214,8 @@ u8 asm_symbol_table_add(ScopeTable *table, Symbol s) {
printf("code[%d] = %s\n", s.ref, s.name); printf("code[%d] = %s\n", s.ref, s.name);
} }
#endif #endif
table->scopes[table->scope_ref].symbols[table->scopes[table->scope_ref].count] = s; table->scopes[table->scope_ref]
.symbols[table->scopes[table->scope_ref].count] = s;
u8 index = table->scopes[table->scope_ref].count; u8 index = table->scopes[table->scope_ref].count;
table->scopes[table->scope_ref].count++; table->scopes[table->scope_ref].count++;
return index; return index;
@ -602,11 +603,8 @@ void asm_define_branch(VM *vm, ScopeTable *st) {
int asm_get_instruction_byte_size(const char *opname) { int asm_get_instruction_byte_size(const char *opname) {
if (strcmp(opname, "return") == 0) { if (strcmp(opname, "return") == 0 ||
return 2; strcmp(opname, "neg_int") == 0 || strcmp(opname, "abs_int") == 0 ||
}
if (strcmp(opname, "neg_int") == 0 || strcmp(opname, "abs_int") == 0 ||
strcmp(opname, "neg_nat") == 0 || strcmp(opname, "abs_nat") == 0 || strcmp(opname, "neg_nat") == 0 || strcmp(opname, "abs_nat") == 0 ||
strcmp(opname, "neg_real") == 0 || strcmp(opname, "abs_real") == 0 || strcmp(opname, "neg_real") == 0 || strcmp(opname, "abs_real") == 0 ||
strcmp(opname, "int_to_string") == 0 || strcmp(opname, "int_to_string") == 0 ||
@ -699,9 +697,9 @@ int asm_get_instruction_byte_size(const char *opname) {
token = next_token(); \ token = next_token(); \
} \ } \
/*printf("code[%d]=%s\n %d + %d = %d\n", vm->cp, op, \ /*printf("code[%d]=%s\n %d + %d = %d\n", vm->cp, op, \
* asm_get_instruction_byte_size(op), vm->cp, vm->cp + \ * asm_get_instruction_byte_size(op), vm->cp, vm->cp + \
* asm_get_instruction_byte_size(op)); */ \ * asm_get_instruction_byte_size(op)); */ \
vm->cp += asm_get_instruction_byte_size(op); \ vm->cp += asm_get_instruction_byte_size(op); \
} while (0); } while (0);
/** /**
@ -729,7 +727,8 @@ void asm_build_symbol_table(VM *vm, char *source, ScopeTable *st) {
if (token.type == TOKEN_RBRACE) { if (token.type == TOKEN_RBRACE) {
i32 current_scope = st->scope_ref; i32 current_scope = st->scope_ref;
i32 parent = st->scopes[current_scope].parent; i32 parent = st->scopes[current_scope].parent;
if (parent < 0) parent = 0; if (parent < 0)
parent = 0;
st->scope_ref = parent; st->scope_ref = parent;
continue; continue;
} }
@ -773,6 +772,15 @@ void asm_build_symbol_table(VM *vm, char *source, ScopeTable *st) {
asm_get_reg(next, st); asm_get_reg(next, st);
vm->cp++; vm->cp++;
next = next_token();
if (next.type == TOKEN_SEMICOLON) {
/* assume it is not a heap value */
vm->cp++;
continue;
}
vm->cp++;
asm_next_token_is(TOKEN_SEMICOLON); asm_next_token_is(TOKEN_SEMICOLON);
continue; continue;
} }
@ -959,7 +967,8 @@ void asm_emit_bytecode(VM *vm, char *source, ScopeTable *st) {
if (token.type == TOKEN_RBRACE) { if (token.type == TOKEN_RBRACE) {
i32 current_scope = st->scope_ref; i32 current_scope = st->scope_ref;
i32 parent = st->scopes[current_scope].parent; i32 parent = st->scopes[current_scope].parent;
if (parent < 0) parent = 0; if (parent < 0)
parent = 0;
st->scope_ref = parent; st->scope_ref = parent;
continue; continue;
} }
@ -1012,12 +1021,40 @@ void asm_emit_bytecode(VM *vm, char *source, ScopeTable *st) {
/* put 0xFF as return register */ /* put 0xFF as return register */
asm_emit_byte(vm, 0xFF); asm_emit_byte(vm, 0xFF);
vm->cp++; vm->cp++;
/* if no return then also no heap */
asm_emit_byte(vm, false);
vm->cp++;
continue; continue;
} }
u32 reg = asm_get_reg(next, st); u32 reg = asm_get_reg(next, st);
asm_emit_byte(vm, reg); asm_emit_byte(vm, reg);
vm->cp++; vm->cp++;
next = next_token();
if (next.type == TOKEN_SEMICOLON) {
/* assume it is not a heap value */
asm_emit_byte(vm, false);
vm->cp++;
continue;
}
switch (next.type) {
case TOKEN_KEYWORD_TRUE: {
asm_emit_byte(vm, true);
break;
}
case TOKEN_KEYWORD_FALSE: {
asm_emit_byte(vm, false);
break;
}
default:
printf("Error: must be true or false for if it is a heap value");
exit(1);
}
vm->cp++;
asm_next_token_is(TOKEN_SEMICOLON); asm_next_token_is(TOKEN_SEMICOLON);
continue; continue;
} }

View File

@ -2,6 +2,7 @@
#define UNDAR_CODEGEN_H #define UNDAR_CODEGEN_H
#include "../vm/common.h" #include "../vm/common.h"
#include "lexer.h"
typedef enum { GLOBAL, LOCAL, VAR } ScopeType; typedef enum { GLOBAL, LOCAL, VAR } ScopeType;
typedef enum { typedef enum {
@ -66,6 +67,7 @@ struct symbol_s {
char name[MAX_SYMBOL_NAME_LENGTH]; char name[MAX_SYMBOL_NAME_LENGTH];
u8 name_length; u8 name_length;
SymbolType type; SymbolType type;
TokenType return_type;
ScopeType scope; ScopeType scope;
u32 ref; // vm->mp if global, vm->pc local, register if var u32 ref; // vm->mp if global, vm->pc local, register if var
u32 size; // size of symbol u32 size; // size of symbol

View File

@ -30,7 +30,7 @@ static char advance() {
return lexer.current[-1]; return lexer.current[-1];
} }
static char peek() { return *lexer.current; } char peek() { return *lexer.current; }
static char peek_next() { static char peek_next() {
if (is_at_end()) if (is_at_end())

View File

@ -86,5 +86,6 @@ typedef struct {
void init_lexer(const char *source); void init_lexer(const char *source);
Token next_token(); Token next_token();
const char* token_type_to_string(TokenType type); const char* token_type_to_string(TokenType type);
char peek();
#endif #endif

View File

@ -99,7 +99,6 @@ typedef enum {
#define MAX_LOCALS 256 #define MAX_LOCALS 256
typedef struct frame_s { typedef struct frame_s {
u32 heap_mask[8];
u32 locals[MAX_LOCALS]; /* $0-$255 */ u32 locals[MAX_LOCALS]; /* $0-$255 */
u32 start; /* start of memory block */ u32 start; /* start of memory block */
u32 end; /* end of memory block */ u32 end; /* end of memory block */

View File

@ -16,7 +16,7 @@ const char radix_set[11] = "0123456789";
u8 src1, src2; \ u8 src1, src2; \
type value; \ type value; \
type value2; \ type value2; \
target = read_u32(vm, code, vm->pc); \ target = *code_u32; \
vm->pc += 4; \ vm->pc += 4; \
src1 = read_u8(vm, code, vm->pc); \ src1 = read_u8(vm, code, vm->pc); \
vm->pc++; \ vm->pc++; \
@ -58,23 +58,6 @@ const char radix_set[11] = "0123456789";
return true; \ return true; \
} while (0) } while (0)
/* Set heap status for a register in current frame */
void set_heap_status(VM *vm, u8 reg, bool is_heap) {
u32 index = reg / 32;
u32 mask = 1 << (reg % 32);
if (is_heap) {
vm->frames[vm->fp].heap_mask[index] |= mask;
} else {
vm->frames[vm->fp].heap_mask[index] &= ~mask;
}
}
/* Check if register contains heap pointer */
bool is_heap_value(VM *vm, u8 reg) {
u32 index = reg / 32;
return (vm->frames[vm->fp].heap_mask[index] >> (reg % 32)) & 1;
}
u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) { u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) {
u32 str_addr = vm->mp; u32 str_addr = vm->mp;
@ -95,20 +78,20 @@ u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) {
*/ */
bool step_vm(VM *vm) { bool step_vm(VM *vm) {
/* Get current instruction & Advance to next instruction */ /* Get current instruction & Advance to next instruction */
u8 opcode = vm->code[vm->pc++];
Frame *frame = &vm->frames[vm->fp]; Frame *frame = &vm->frames[vm->fp];
u8 opcode = vm->code[vm->pc++];
u32 *code_u32 = (u32*)(&vm->code[vm->pc]);
switch (opcode) { switch (opcode) {
case OP_EXIT: { case OP_EXIT: {
vm->flag = read_u32(vm, code, vm->pc); vm->flag = *code_u32;
return false; return false;
} }
case OP_CALL: { case OP_CALL: {
u8 N, return_reg, src_reg, args[MAX_LOCALS]; u8 N, return_reg, src_reg, args[MAX_LOCALS];
Frame *child; Frame *child;
u32 jmp, mask, i; u32 jmp, i;
jmp = *code_u32;
jmp = read_u32(vm, code, vm->pc);
vm->pc += 4; vm->pc += 4;
N = vm->code[vm->pc++]; N = vm->code[vm->pc++];
@ -135,16 +118,13 @@ bool step_vm(VM *vm) {
for (i = 0; i < N; i++) { for (i = 0; i < N; i++) {
src_reg = args[i]; src_reg = args[i];
child->locals[i] = frame->locals[src_reg]; child->locals[i] = frame->locals[src_reg];
mask = 1 << (src_reg % 32);
if (frame->heap_mask[src_reg / 32] & mask) {
child->heap_mask[i / 32] |= 1 << (i % 32);
}
} }
vm->pc = jmp; vm->pc = jmp;
return true; return true;
} }
case OP_RETURN: { case OP_RETURN: {
bool is_heap_value;
u8 child_return_reg; u8 child_return_reg;
u32 value; u32 value;
u32 ptr; u32 ptr;
@ -154,13 +134,14 @@ bool step_vm(VM *vm) {
Frame *parent; Frame *parent;
child_return_reg = vm->code[vm->pc++]; child_return_reg = vm->code[vm->pc++];
is_heap_value = vm->code[vm->pc++];
child = frame; child = frame;
parent = &vm->frames[vm->fp - 1]; parent = &vm->frames[vm->fp - 1];
if (child_return_reg != 0xFF && parent->return_reg != 0xFF) { if (child_return_reg != 0xFF) {
value = child->locals[child_return_reg]; value = child->locals[child_return_reg];
if (is_heap_value(vm, child_return_reg)) { if (is_heap_value) {
ptr = value; ptr = value;
size = *(u32 *)(vm->memory + ptr - 4); size = *(u32 *)(vm->memory + ptr - 4);
new_ptr = parent->end; new_ptr = parent->end;
@ -171,11 +152,8 @@ bool step_vm(VM *vm) {
memcopy(vm->memory + new_ptr + 4, vm->memory + ptr + 4, size); memcopy(vm->memory + new_ptr + 4, vm->memory + ptr + 4, size);
parent->end += size + 4; parent->end += size + 4;
parent->locals[parent->return_reg] = new_ptr; parent->locals[parent->return_reg] = new_ptr;
parent->heap_mask[parent->return_reg / 32] |= (1 << parent->return_reg);
} else { } else {
parent->locals[parent->return_reg] = value; parent->locals[parent->return_reg] = value;
parent->heap_mask[parent->return_reg / 32] &=
~(1 << parent->return_reg);
} }
} }
@ -187,7 +165,7 @@ bool step_vm(VM *vm) {
case OP_LOAD_IMM: { case OP_LOAD_IMM: {
u32 v; u32 v;
u8 dest; u8 dest;
v = read_u32(vm, code, vm->pc); v = *code_u32;
vm->pc += 4; vm->pc += 4;
dest = read_u8(vm, code, vm->pc); dest = read_u8(vm, code, vm->pc);
vm->pc++; vm->pc++;
@ -205,13 +183,12 @@ bool step_vm(VM *vm) {
size = frame->locals[src1]; size = frame->locals[src1];
write_u32(vm, memory, vm->mp, size); write_u32(vm, memory, vm->mp, size);
vm->mp += (size + 4); vm->mp += (size + 4);
set_heap_status(vm, dest, true); /* Mark as heap pointer */
return true; return true;
} }
case OP_LOAD_ABS_32: { case OP_LOAD_ABS_32: {
u32 v, ptr; u32 v, ptr;
u8 dest; u8 dest;
ptr = read_u32(vm, code, vm->pc); ptr = *code_u32;
vm->pc += 4; vm->pc += 4;
v = read_u32(vm, memory, ptr); v = read_u32(vm, memory, ptr);
dest = read_u8(vm, code, vm->pc); dest = read_u8(vm, code, vm->pc);
@ -222,7 +199,7 @@ bool step_vm(VM *vm) {
case OP_LOAD_ABS_16: { case OP_LOAD_ABS_16: {
u32 v, ptr; u32 v, ptr;
u8 dest; u8 dest;
ptr = read_u32(vm, code, vm->pc); ptr = *code_u32;
vm->pc += 4; vm->pc += 4;
v = read_u16(vm, memory, ptr); v = read_u16(vm, memory, ptr);
dest = read_u8(vm, code, vm->pc); dest = read_u8(vm, code, vm->pc);
@ -233,7 +210,7 @@ bool step_vm(VM *vm) {
case OP_LOAD_ABS_8: { case OP_LOAD_ABS_8: {
u32 v, ptr; u32 v, ptr;
u8 dest; u8 dest;
ptr = read_u32(vm, code, vm->pc); ptr = *code_u32;
vm->pc += 4; vm->pc += 4;
v = read_u8(vm, memory, ptr); v = read_u8(vm, memory, ptr);
dest = read_u8(vm, code, vm->pc); dest = read_u8(vm, code, vm->pc);
@ -544,23 +521,16 @@ bool step_vm(VM *vm) {
dest = read_u8(vm, code, vm->pc); dest = read_u8(vm, code, vm->pc);
vm->pc++; vm->pc++;
frame->locals[dest] = frame->locals[src1]; frame->locals[dest] = frame->locals[src1];
if (is_heap_value(vm, src1)) {
set_heap_status(vm, dest, true);
} else {
set_heap_status(vm, dest, false);
}
return true; return true;
} }
case OP_JMP: { case OP_JMP: {
u32 jmp = read_u32(vm, code, vm->pc); u32 jmp = *code_u32;
vm->pc = jmp; /* Jump to address */ vm->pc = jmp; /* Jump to address */
return true; return true;
} }
case OP_JMPF: { /* error handling for syscall, jump if flag == 0 */ case OP_JMPF: { /* error handling for syscall, jump if flag == 0 */
u32 mask; u32 mask;
u32 jmp = read_u32(vm, code, vm->pc); u32 jmp = *code_u32;
mask = -(u32)(vm->flag == 0); mask = -(u32)(vm->flag == 0);
vm->pc = (jmp & mask) | (vm->pc & ~mask); vm->pc = (jmp & mask) | (vm->pc & ~mask);
return true; return true;
@ -568,7 +538,7 @@ bool step_vm(VM *vm) {
case OP_SYSCALL: { case OP_SYSCALL: {
u32 syscall_id; u32 syscall_id;
syscall_id = read_u32(vm, code, vm->pc); syscall_id = *code_u32;
vm->pc += 4; vm->pc += 4;
switch (syscall_id) { switch (syscall_id) {
@ -966,7 +936,6 @@ bool step_vm(VM *vm) {
buffer[--i] = '0'; buffer[--i] = '0';
frame->locals[dest] = str_alloc(vm, frame, buffer + i, MAX_LEN_INT32 - i); frame->locals[dest] = str_alloc(vm, frame, buffer + i, MAX_LEN_INT32 - i);
set_heap_status(vm, dest, true); /* Mark as heap pointer */
return true; return true;
} }
case OP_NAT_TO_STRING: { case OP_NAT_TO_STRING: {
@ -991,7 +960,6 @@ bool step_vm(VM *vm) {
buffer[--i] = '0'; buffer[--i] = '0';
/* Copy from buffer[i] to buffer + MAX_LEN_INT32 */ /* Copy from buffer[i] to buffer + MAX_LEN_INT32 */
frame->locals[dest] = str_alloc(vm, frame, buffer + i, MAX_LEN_INT32 - i); frame->locals[dest] = str_alloc(vm, frame, buffer + i, MAX_LEN_INT32 - i);
set_heap_status(vm, dest, true); /* Mark as heap pointer */
return true; return true;
} }
case OP_REAL_TO_STRING: { case OP_REAL_TO_STRING: {
@ -1036,7 +1004,6 @@ bool step_vm(VM *vm) {
buffer[--i] = '-'; buffer[--i] = '-';
frame->locals[dest] = str_alloc(vm, frame, buffer + i, MAX_LEN_REAL32 - i); frame->locals[dest] = str_alloc(vm, frame, buffer + i, MAX_LEN_REAL32 - i);
set_heap_status(vm, dest, true); /* Mark as heap pointer */
return true; return true;
} }
case OP_STRLEN: { case OP_STRLEN: {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.