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
.vscode
.clangd
.directory
perf.*

View File

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

View File

@ -1,4 +1,4 @@
#include "../../tools/compiler/compiler.h"
//#include "../../tools/compiler/compiler.h"
#include "../../tools/assembler/assembler.h"
#include "../../vm/vm.h"
#include "devices.h"
@ -225,8 +225,8 @@ bool compileAndSave(const char *source_file, const char *output_file, VM *vm) {
fclose(f);
ScopeTable table = {0};
symbol_table_init(&table);
compile(vm, &table, source);
/* symbol_table_init(&table); */
/* compile(vm, &table, source); */
#ifndef STATIC
free(table.scopes);
#endif
@ -340,7 +340,9 @@ i32 main(i32 argc, char *argv[]) {
&console_device_ops, 4);
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;
}

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,
i32 scope_ref) {
i32 scope_ref) {
SymbolTable st = table->scopes[scope_ref];
for (u32 i = 0; i < st.count; i++) {
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);
}
#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;
table->scopes[table->scope_ref].count++;
return index;
@ -602,11 +603,8 @@ void asm_define_branch(VM *vm, ScopeTable *st) {
int asm_get_instruction_byte_size(const char *opname) {
if (strcmp(opname, "return") == 0) {
return 2;
}
if (strcmp(opname, "neg_int") == 0 || strcmp(opname, "abs_int") == 0 ||
if (strcmp(opname, "return") == 0 ||
strcmp(opname, "neg_int") == 0 || strcmp(opname, "abs_int") == 0 ||
strcmp(opname, "neg_nat") == 0 || strcmp(opname, "abs_nat") == 0 ||
strcmp(opname, "neg_real") == 0 || strcmp(opname, "abs_real") == 0 ||
strcmp(opname, "int_to_string") == 0 ||
@ -699,9 +697,9 @@ int asm_get_instruction_byte_size(const char *opname) {
token = next_token(); \
} \
/*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 += asm_get_instruction_byte_size(op); \
* asm_get_instruction_byte_size(op), vm->cp, vm->cp + \
* asm_get_instruction_byte_size(op)); */ \
vm->cp += asm_get_instruction_byte_size(op); \
} while (0);
/**
@ -729,7 +727,8 @@ void asm_build_symbol_table(VM *vm, char *source, ScopeTable *st) {
if (token.type == TOKEN_RBRACE) {
i32 current_scope = st->scope_ref;
i32 parent = st->scopes[current_scope].parent;
if (parent < 0) parent = 0;
if (parent < 0)
parent = 0;
st->scope_ref = parent;
continue;
}
@ -773,6 +772,15 @@ void asm_build_symbol_table(VM *vm, char *source, ScopeTable *st) {
asm_get_reg(next, st);
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);
continue;
}
@ -959,7 +967,8 @@ void asm_emit_bytecode(VM *vm, char *source, ScopeTable *st) {
if (token.type == TOKEN_RBRACE) {
i32 current_scope = st->scope_ref;
i32 parent = st->scopes[current_scope].parent;
if (parent < 0) parent = 0;
if (parent < 0)
parent = 0;
st->scope_ref = parent;
continue;
}
@ -1012,12 +1021,40 @@ void asm_emit_bytecode(VM *vm, char *source, ScopeTable *st) {
/* put 0xFF as return register */
asm_emit_byte(vm, 0xFF);
vm->cp++;
/* if no return then also no heap */
asm_emit_byte(vm, false);
vm->cp++;
continue;
}
u32 reg = asm_get_reg(next, st);
asm_emit_byte(vm, reg);
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);
continue;
}

View File

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

View File

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

View File

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

View File

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

View File

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