import "llvm.src"; 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 codegen_generate_assignment_statement = (c: *codegen, stmt: *NODE_ASSIGNMENT_STATEMENT_DATA) => i64 { println("HOLA"); 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; }; println("STMT: %d", 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 { println("Target output: %s", *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 { println("Verification output: %s", *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); println("Object file generated: %s", filename); return 0; }; let codegen_deinit = (c: *codegen) => void { LLVMDisposeModule((*c).llvm_module); LLVMShutdown(); LLVMDisposeBuilder((*c).builder); return; };