diff options
| author | 0x221E <0x221E@0xinfinity.dev> | 2026-04-12 16:24:06 +0200 |
|---|---|---|
| committer | 0x221E <0x221E@0xinfinity.dev> | 2026-04-12 16:24:06 +0200 |
| commit | 4946ca67cf04845737f0f7f70b5ed27bcfe9a18b (patch) | |
| tree | e0ce4c11f5b81828da7680143ea444003dd355b3 /src/irm.c | |
Diffstat (limited to 'src/irm.c')
| -rw-r--r-- | src/irm.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/src/irm.c b/src/irm.c new file mode 100644 index 0000000..6260ae0 --- /dev/null +++ b/src/irm.c @@ -0,0 +1,247 @@ +#include "irm.h" + +#include <assert.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> + +#include <backend.h> +#include <x86.h> + +#define STACK_SUB(irm, syment, type) \ + do { \ + irm->stackdepth += sizeof(type); \ + syment->loc = irm->stackdepth; \ + syment->len = sizeof(type); \ + while(0) + +// TODO: Add scopes. + +void irm_init(struct irm *irm) +{ + assert(irm != NULL); + irm->storage = malloc(1024 * 1024); // TODO: platform-agnostic + irm->size = (1024 * 1024) / 8; + irm->curr_pos = 0; + irm->state = IRM_GRACEFUL; + symtab_init(&irm->symtab); +} + +void irm_panic(struct irm *irm) +{ + irm->state = IRM_PANIC; +} + +void irm_stmt_enter_scope(struct irm *irm) +{ + assert(irm != NULL); + // Append 1 level. +} + +void irm_stmt_leave_scope(struct irm *irm) +{ + assert(irm != NULL); +} + +void irm_stmt_var_decl(struct irm *irm, size_t *offset) +{ + uint64_t* mem = irm->storage; + + uint64_t ltype = mem[*offset]; + (*offset)++; + + uint64_t symbol_type = mem[*offset]; + if(symbol_type != SYM_VAR) { + DIE("Symbol type invalid! sym:'%x'", symbol_type); + } + (*offset)++; + uint64_t symid = mem[*offset]; + + if(irm->symtab.count < symid) { + DIE("Symbol id: '%d' not found! This is a compiler bug.\n", + symid); + } + + struct symbol_entry *syment = &irm->symtab.entries[symid]; + irm->stackdepth += sizeof(uint64_t); + syment->loc = irm->stackdepth; + + DEBUG("Symbol id: %d\n", symid); + (*offset)++; + (*offset)++; + switch(ltype) { + case VAR_DECL_QWORD: { + uint64_t value = mem[*offset]; + syment->len = sizeof(uint64_t); + (*offset)++; + x86_mov_r_i64(RAX, value); + x86_push_r64(RAX); + break; + } + case VAR_DECL_DWORD: { + uint64_t value = mem[*offset]; + syment->len = sizeof(uint32_t); + (*offset)++; + x86_push_i32(value); + break; + } + case VAR_DECL_WORD: { + uint64_t value = mem[*offset]; + syment->len = sizeof(uint32_t); + (*offset)++; + x86_push_i32(value); // TODO: Replace with immediate 16 instruction + break; + } + case VAR_DECL_BYTE: { + uint64_t value = mem[*offset]; + (*offset)++; + syment->len = sizeof(uint16_t); + x86_push_i8(value); + break; + } + default: + DIE("Invalid type supplied! This is a compiler bug. type: %x.\n" + , ltype); + break; + } +} + +void irm_stmt_var_assign(struct irm *irm, size_t *offset) +{ + assert(irm != NULL); + if(offset == NULL) { + DIE("offset must not be null!"); + } + + (*offset)++; + uint64_t sym_id = irm->storage[*offset]; + if(sym_id != SYM_VAR) { + DIE("Variable assignment only supports a symbol of type variable!"); + } + + (*offset)++; + uint64_t symtab_id = irm->storage[*offset]; + struct symbol_entry *ent = &irm->symtab.entries[symtab_id]; + if(ent->symtype != SYM_VAR) { + DIE("Symbol '%.*s' is not of type variable!", ent->name.len, ent->name.buf); + } + (*offset)++; + uint64_t value_type = irm->storage[*offset]; + switch(value_type) { + case NUMBER64: { // FIX STACK ISSUE + DIE("TODO:: STACK ALGINMENT ISSUE!!"); + (*offset)++; + uint64_t value = irm->storage[*offset]; + DEBUG("Assigned nr64 literal %d to '%.*s'.\n", value, ent->name.len, ent->name.buf); + (*offset)++; + // TODO: mov [rsp - X], value + // mov rax, rsp + emit8(0x48); + emit8(0x8B); // MR + emit8(0xC4); // rsp -> rax + // sub rax, 8 + emit8(0x48); + emit8(0x2d); + emit32(ent->loc); + // mov rbx, value + emit8(0x48); + emit8(0xBB); // b8 + rd + emit64(value); // FALSE VALUE!! FIX! + // mov qword ptr [rax], rbx + emit8(0x48); + emit8(0x89); // MR + emit8(0x18); // rbx -> [rax] + break; + } + default: + DIE("Variable assignment only supports a number literal!"); + } +} + +void irm_stmt_done(struct irm *irm) +{ + if(irm->state == IRM_PANIC) return; + size_t offset = 0; + + while(offset < irm->curr_pos - 1) { + uint64_t type = irm->storage[offset]; + type &= 0xFFFF0000; + + switch(type) { + case VAR_DECL: + irm_stmt_var_decl(irm, &offset); + break; + case VAR_ASSIGN: + irm_stmt_var_assign(irm, &offset); + break; + default: + DIE("Statement identifier not found: %d.", type); + break; + } + DEBUG("Offset: %d, Size: %d\n", offset, irm->curr_pos); + } + if(irm->storage[offset] != STMT_DONE) { + DIE("Statement done was not received! This is a compiler bug."); + } + memset(irm->storage, 0, irm->curr_pos); + irm->curr_pos = 0; +} + +void irm_push(struct irm *irm, uint64_t type) +{ + assert(irm != NULL); + uint64_t *mem = irm->storage + irm->curr_pos; + mem[0] = type; + irm->curr_pos += 1; + DEBUG("added %x to irm.\n", type); +} + +void irm_push_64v(struct irm *irm, uint64_t type, uint64_t value) +{ + assert(irm != NULL); + if(irm->curr_pos + 2 > irm->size) + DIE("IRM OVERFLOW!"); + uint64_t* mem = irm->storage + irm->curr_pos; + mem[0] = type; + mem[1] = value; + irm->curr_pos += 2; + DEBUG("added %d to irm with value %d.\n", type, value); +} + +void irm_push_lookup_sym(struct irm *irm, uint64_t type, struct string_view sym) +{ + assert(irm != NULL); + + uint64_t *mem = irm->storage + irm->curr_pos; + mem[0] = type; + struct symlookup_result ent = symtab_lookup(&irm->symtab, sym); + + if(ent.ent == NULL) { + DIE("'%.*s' not found!", sym.len, sym.buf); + } + + mem[1] = ent.i; + irm->curr_pos+=2; +} + +// TODO: +// 1. Push SYM_TYPE +// 2. Push SYMTAB offset (after adding the sym to it) +void irm_push_sym(struct irm *irm, uint64_t type, struct string_view sym) +{ + assert(irm != NULL); + struct symbol_entry entry; + entry.name = sym; + entry.loc = 0; + entry.symtype = type; + if(symtab_lookup(&irm->symtab, sym).ent != NULL) { + DIE("Symbol '%.*s' already exists.\n", sym.len, sym.buf); + } + size_t symindex = symtab_append(&irm->symtab, entry); + uint64_t* mem = irm->storage + irm->curr_pos; + mem[0] = type; + mem[1] = symindex; + irm->curr_pos += 2; + DEBUG("added %.*s to symbol table.\n", sym.len, sym.buf); +} |
