about summary refs log tree commit diff
path: root/src/bootstrap/codegen.pry
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/codegen.pry')
-rw-r--r--src/bootstrap/codegen.pry187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry
new file mode 100644
index 0000000..7293c09
--- /dev/null
+++ b/src/bootstrap/codegen.pry
@@ -0,0 +1,187 @@
+import "llvm.pry";
+
+let codegen = struct {
+	llvm_module: LLVMModuleRef,
+	llvm_context: LLVMContextRef,
+	builder: LLVMBuilderRef,
+	arena: *arena,
+};
+
+let codegen_init = (alloc: *arena) => *codegen {
+	LLVMInitializeAllTargetInfos();
+	LLVMInitializeAllTargetMCs();
+	LLVMInitializeAllTargets();
+	LLVMInitializeAllAsmPrinters();
+	LLVMInitializeAllAsmParsers();
+
+	let module = LLVMModuleCreateWithName("module");
+        let context = LLVMGetGlobalContext();
+        let builder = LLVMCreateBuilder();
+	
+	let c = cast(*codegen, arena_alloc(alloc, sizeof(codegen)));
+	
+	(*c).llvm_module = module;
+	(*c).llvm_context = context;
+	(*c).builder = builder;
+	(*c).arena = alloc;
+
+	return c;
+};
+
+let create_node = (c: *codegen, n: Node) => *Node {
+	let res = cast(*Node, arena_alloc((*c).arena, sizeof(Node)));
+	*res = n;
+	return res;
+};
+
+let Variable = struct {
+	value: LLVMValueRef,
+	type: LLVMTypeRef,
+	node: *Node,
+	node_type: *Node,
+	stack_level: *i64,
+};
+
+let codegen_create_variable = (c: *codegen, variable: Variable) => *Variable {
+	let v = cast(*Variable, arena_alloc((*c).arena, sizeof(Variable)));
+	*v = variable;
+	return v;
+};
+
+let codegen_generate_literal = (c: *codegen, literal_val: LLVMValueRef, name: *i8, node: *Node, node_type: *Node) => *Variable {
+	/* TODO: Global */
+	let v = Variable{};
+	v.value = literal_val;
+	v.type = cast(LLVMTypeRef, null);
+	v.stack_level = cast(*i64, null);
+	v.node = node;
+	v.node_type = node_type;
+	return codegen_create_variable(c, v);
+};
+
+let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *i8) => *Variable {
+	if ((*expression).type == NODE_PRIMARY_EXPRESSION_NUMBER) {
+		let n = (*cast(*NODE_PRIMARY_EXPRESSION_NUMBER_DATA, (*expression).data)).value;
+		
+		printf("X: %d\n", n);
+
+		let node_type = Node{};
+		node_type.type = NODE_TYPE_SIMPLE_TYPE;
+
+		let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA)));
+		(*d).name = "i64";
+		(*d).underlying_type = cast(*Node, null);
+		node_type.data = cast(*void, d);
+		
+		return codegen_generate_literal(c, LLVMConstInt(LLVMInt64Type(), n, 0), name, expression, create_node(c, node_type));
+	};
+	
+	if ((*expression).type == NODE_FUNCTION_DEFINITION) {
+		printf("ASS %d\n", (*expression).type);
+		assert(false); /* TODO */
+		printf("ERT\n");
+	};
+
+	assert(false);
+
+	return cast(*Variable, null);
+};
+
+let codegen_generate_assignment_statement = (c: *codegen, stmt: *NODE_ASSIGNMENT_STATEMENT_DATA) => i64 {
+	let lhs = *((*stmt).lhs);
+	let prhs = (*stmt).rhs;
+
+	if (lhs.type == NODE_PRIMARY_EXPRESSION_IDENTIFIER) {
+		let identifier = (*cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, lhs.data)).name;
+		printf("XX %s\n", identifier);
+		let variable = codegen_generate_expression_value(c, prhs, identifier);
+		assert(variable != cast(*Variable, null));
+		return 0;
+	};
+
+	assert(false);
+	return 0;
+};
+
+let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 {
+	let stmt = *statement;
+	assert(stmt.type == NODE_ASSIGNMENT_STATEMENT); /* TODO: generate other node types */
+
+	let res = codegen_generate_assignment_statement(c, cast(*NODE_ASSIGNMENT_STATEMENT_DATA, stmt.data));
+	if res != 0 {
+		return 1;
+	};
+	printf("STMT: %d\n", stmt.type);
+	return 0;
+};
+
+let codegen_generate = (c: *codegen, ast: *Node) => i64 {
+	assert((*ast).type == NODE_PROGRAM);
+
+	let program = *cast(*NODE_PROGRAM_DATA, (*ast).data);
+
+	let i = 0;
+	while i < program.statements_len {
+		let stmt = *(program.statements + cast(**Node, i));
+
+		let res = codegen_generate_statement(c, stmt);
+		if res != 0 {
+			return 1;
+		};
+
+		i = i + 1;
+	};
+
+	return 0;
+};
+
+let codegen_compile = (c: *codegen) => i64 {
+        /* Dump module */
+	LLVMDumpModule((*c).llvm_module);
+
+	/* Generate code */
+        let triple = LLVMGetDefaultTargetTriple();
+        let target_ref = cast(*LLVMTargetRef, arena_alloc((*c).arena, sizeof(*LLVMTargetRef)));
+        let message = cast(**i8, null);
+        let result = LLVMGetTargetFromTriple(triple, target_ref, message);
+        if result != 0 {
+            printf("Target output: %s\n", *message);
+            LLVMDisposeMessage(*message);
+        };
+        let target_machine = LLVMCreateTargetMachine(
+            *target_ref,
+            triple,
+            "",
+            "",
+            LLVMCodeGenLevelDefault,
+            LLVMRelocDefault,
+            LLVMCodeModelDefault,
+        );
+        LLVMDisposeMessage(triple);
+        result = LLVMVerifyModule((*c).llvm_module, LLVMAbortProcessAction, message);
+        if result != 0 {
+            printf("Verification output: %s\n", *message);
+            LLVMDisposeMessage(*message);
+        };
+
+        /* Generate the object file */
+        let filename = "bootstrap_output.o";
+        LLVMTargetMachineEmitToFile(
+            target_machine,
+            (*c).llvm_module,
+            filename,
+            LLVMObjectFile,
+            cast(**i8, null),
+        );
+        LLVMDisposeTargetMachine(target_machine);
+        printf("Object file generated: %s\n", filename);
+
+	return 0;
+};
+
+let codegen_deinit = (c: *codegen) => void {
+        LLVMDisposeModule((*c).llvm_module);
+        LLVMShutdown();
+        LLVMDisposeBuilder((*c).builder);
+	return;
+};