initial codegen

This commit is contained in:
janis 2025-10-31 15:49:10 +01:00
parent 6bdd2ef18a
commit d5de30d9e7
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
3 changed files with 194 additions and 1 deletions

112
lang/src/codegen.asm Normal file
View file

@ -0,0 +1,112 @@
default rel
%include "ast.inc"
extern panic
extern vec_extend
extern vec_get
section .rdata
SECTION_TEXT db "section .text\n"
SECTION_TEXT_LEN equ $ - SECTION_TEXT
GLOBAL_ db "global "
GLOBAL_LEN equ $ - GLOBAL_
COLON_NL db ":", 10
COLON_NL_LEN equ $ - COLON_NL
RET_NL db "ret", 10
RET_NL_LEN equ $ - RET_NL
section .text
;; start-structs
;; struct CodegenCtx {
;; ast: *const Ast,
;; text: Vec<u8>,
;; }
;; end-structs
;; rdi: *Ctx
;; rsi: function index
;; define-fn: fn codegen_function(ast: *const CodegenCtx, func_idx: usize) -> ()
codegen_function:
push rbp
mov rbp, rsp
push rbx
; register-bitset [72..88] [a,b,c,d,di,si,sp,bp,8,9,10,11,12,13,14,15]
; stack-vars: Vec<(index, offset)> [32..72]
; current_stack_size: [24..32]
; func_idx [16..24]
; ast [8..16]
; ctx [0..8]
sub rsp, 88
mov [rsp], rdi ; ctx
mov rax, [rdi]
mov [rsp + 8], rax ; ast
mov [rsp + 16], rsi ; func_idx
bts [rsp + 72], 7 ; mark rbp as used
bts [rsp + 72], 6 ; mark rsp as used
; push "section .text\n"
mov rdi, [rsp] ; ctx
lea rdi, [rsp + 8] ; &ctx.text
lea rsi, [rel SECTION_TEXT]
mov rdx, SECTION_TEXT_LEN
call vec_extend
mov rdi, [rsp + 8] ; ast
mov rsi, [rsp + 16] ; func_idx
call vec_get
cmp [rax + 0], AST_FUNCTION ; AstNode.kind
mov rbx, [rax + 8] ; AstNode.data
jne .panic
; push "global {function_name}\n"
mov rdi, [rsp] ; ctx
lea rdi, [rdi] ; &ctx.text
lea rsi, [rel GLOBAL_]
mov rdx, GLOBAL_LEN
call vec_extend
; get function name
mov rdi, [rsp] ; ctx
lea rdi, [rdi] ; &ctx.text
mov rsi, [rbx + 0] ; AstFunction.name
mov rdx, [rbx + 8] ; AstFunction.name_len
call vec_extend
; push "\n"
mov rdi, [rsp] ; ctx
lea rdi, [rdi] ; &ctx.text
lea rsi, [rel COLON_NL]
inc rsi
mov rdx, 1
call vec_extend
; push "{function_name}:\n"
mov rdi, [rsp] ; ctx
lea rdi, [rdi] ; &ctx.text
mov rsi, [rbx + 0] ; AstFunction.name
mov rdx, [rbx + 8] ; AstFunction.name_len
call vec_extend
; push ":\n"
mov rdi, [rsp] ; ctx
lea rdi, [rdi] ; &ctx.text
lea rsi, [rel COLON_NL]
mov rdx, 2
call vec_extend
; TODO: generate function body
; push "ret\n"
mov rdi, [rsp] ; ctx
lea rdi, [rdi] ; &ctx.text
lea rsi, [rel RET_NL]
mov rdx, RET_NL_LEN
call vec_extend
pop rbx
add rsp, 88
pop rbp
ret
.panic:
call panic

74
lang/tests/codegen.rs Normal file
View file

@ -0,0 +1,74 @@
#![feature(debug_closure_helpers)]
#[path = "shared/shared.rs"]
mod util;
#[path = "shared/ast_debug.rs"]
mod ast_debug;
use util::defs::{parse_func, Ast, AstNode};
unsafe extern "C" {
unsafe fn bump_init();
unsafe fn tokeniser_init_buf(bytes: *const u8, len: usize) -> ();
}
fn main() {
unsafe {
bump_init();
}
println!("Bump allocator initialized.");
let src = b"3 + 4";
fn print_ast(src: &[u8], parser: impl FnOnce(&mut Ast) -> u64) {
unsafe {
tokeniser_init_buf(src.as_ptr(), src.len());
let mut ast = Ast {
nodes: util::vec::Vec::new(),
};
let expr_id = parser(&mut ast);
eprintln!("Parsed expression ID: {}", expr_id);
println!("{:#}", &ast);
// unsafe extern "C" fn visit_node(
// _this: *mut (),
// ast: *mut Ast,
// node_id: u64,
// scope: u64,
// ) {
// let ast = unsafe { &*ast };
// let node = ast.nodes.get(node_id as usize).unwrap();
// eprintln!("{scope}: Visiting node {node_id}: {node}");
// }
// util::defs::ast_walk_for_each(&mut ast, expr_id, core::ptr::null_mut(), visit_node);
let mut symtable = core::mem::MaybeUninit::<util::defs::SymbolTable>::uninit();
util::defs::ast_build_symtable(&mut ast, expr_id, &mut symtable);
let mut symtable = symtable.assume_init();
use util::DisplayedSliceExt;
println!(
"Symbol Table: {:#?}",
symtable.symtable.as_slice().displayed()
);
util::defs::ast_resolve_var_refs(&mut ast, &mut symtable, expr_id);
println!("{:#}", &ast);
};
}
print_ast(
b"fn main(a: u32) -> void {
let y: u32 = a + 4;
{
let y: u32 = 10;
}
let y: *u32 = &y;
return *y;
}",
|ast| unsafe { parse_func(ast) },
);
}

View file

@ -17,7 +17,7 @@ unsafe extern "C" {
pub unsafe fn ast_build_symtable(ast: *mut Ast, root_index: u64, symtable: *mut core::mem::MaybeUninit<SymbolTable>); pub unsafe fn ast_build_symtable(ast: *mut Ast, root_index: u64, symtable: *mut core::mem::MaybeUninit<SymbolTable>);
pub unsafe fn ast_walk_for_each(ast: *mut Ast, start_index: u64, ctx: *mut (), for_each: unsafe extern "C" fn(ctx: *mut (), *mut Ast, node_index: u64, scope: u64)); pub unsafe fn ast_walk_for_each(ast: *mut Ast, start_index: u64, ctx: *mut (), for_each: unsafe extern "C" fn(ctx: *mut (), *mut Ast, node_index: u64, scope: u64));
pub unsafe fn ast_resolve_var_refs(ast: *mut Ast, ctx: *mut SymbolTable, root_index: u64); pub unsafe fn ast_resolve_var_refs(ast: *mut Ast, ctx: *mut SymbolTable, root_index: u64);
pub unsafe fn codegen_function(ast: *const Ast, func_idx: usize) -> (); pub unsafe fn codegen_function(ast: *const CodegenCtx, func_idx: usize) -> ();
pub unsafe fn vec_extend(vec: *mut BlobVec, elements: *const u8, count: usize) -> (); pub unsafe fn vec_extend(vec: *mut BlobVec, elements: *const u8, count: usize) -> ();
} }
@ -192,6 +192,13 @@ pub struct SymEntry {
pub extra: u64, pub extra: u64,
} }
#[repr(C)]
#[derive(Debug)]
pub struct CodegenCtx {
pub ast: *const Ast,
pub text: Vec<u8>,
}
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
pub struct BlobVec { pub struct BlobVec {