From 7e59ac35207dd961898603193b5d63b59e3b8738 Mon Sep 17 00:00:00 2001 From: servostar Date: Thu, 30 May 2024 13:11:51 +0200 Subject: [PATCH] feature: added if statement --- src/llvm/stmt.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 5 deletions(-) diff --git a/src/llvm/stmt.c b/src/llvm/stmt.c index 5b317e2..9d23c07 100644 --- a/src/llvm/stmt.c +++ b/src/llvm/stmt.c @@ -118,16 +118,96 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit, return err; } +BackendError +impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Expression *cond, + Block *block, LLVMBasicBlockRef *cond_block, LLVMBasicBlockRef *body_block, + LLVMValueRef *llvm_cond) { + BackendError err; + + *cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, + "stmt.branch.cond"); + LLVMPositionBuilderAtEnd(builder, *cond_block); + // Resolve condition in block to a variable + err = impl_expr(unit, scope, builder, cond, llvm_cond); + if (err.kind == Success) { + // build body of loop + err = impl_basic_block(unit, builder, scope, block, body_block); + } + + return err; +} + BackendError impl_branch(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, const Branch *branch) { BackendError err = SUCCESS; - LLVMBasicBlockRef if_cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, - "stmt.branch.cond"); - // Resolve condition in block to a variable - LLVMValueRef cond_result = NULL; - impl_expr(unit, scope, builder, &branch->ifBranch.conditon, &cond_result); + GArray *cond_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef)); + GArray *body_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef)); + GArray *cond_values = g_array_new(FALSE, FALSE, sizeof(LLVMValueRef)); + + // add If to arrays + { + LLVMBasicBlockRef cond_block = NULL; + LLVMBasicBlockRef body_block = NULL; + LLVMValueRef cond_value = NULL; + + err = impl_cond_block(unit, builder, scope, &branch->ifBranch.conditon, &branch->ifBranch.block, &cond_block, + &body_block, &cond_value); + + g_array_append_val(cond_blocks, cond_block); + g_array_append_val(body_blocks, body_block); + g_array_append_val(cond_values, cond_value); + } + + // generate else if(s) + for (size_t i = 0; i < branch->elseIfBranches->len; i++) { + LLVMBasicBlockRef cond_block = NULL; + LLVMBasicBlockRef body_block = NULL; + LLVMValueRef cond_value = NULL; + + ElseIf *elseIf = ((ElseIf *) branch->elseIfBranches->data) + i; + + err = impl_cond_block(unit, builder, scope, &elseIf->conditon, &elseIf->block, &cond_block, + &body_block, &cond_value); + + g_array_append_val(cond_blocks, cond_block); + g_array_append_val(body_blocks, body_block); + g_array_append_val(cond_values, cond_value); + } + + // else block + if (branch->elseBranch.nodePtr != NULL) { + LLVMBasicBlockRef else_block = NULL; + err = impl_basic_block(unit, builder, scope, &branch->elseBranch.block, &else_block); + g_array_append_val(cond_blocks, else_block); + } + + LLVMBasicBlockRef after_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, + "stmt.branch.after"); + LLVMPositionBuilderAtEnd(builder, after_block); + // in case no else block is present + // make the after block the else + if (branch->elseBranch.nodePtr == NULL) { + g_array_append_val(cond_blocks, after_block); + } + + for (size_t i = 0; i < cond_blocks->len - 1; i++) { + LLVMBasicBlockRef next_block = ((LLVMBasicBlockRef*) cond_blocks->data)[i + 1]; + LLVMBasicBlockRef cond_block = ((LLVMBasicBlockRef*) cond_blocks->data)[i]; + LLVMBasicBlockRef body_block = ((LLVMBasicBlockRef*) body_blocks->data)[i]; + LLVMValueRef cond_value = ((LLVMValueRef*) cond_values->data)[i]; + + LLVMPositionBuilderAtEnd(builder, cond_block); + LLVMBuildCondBr(builder, cond_value, body_block, next_block); + + LLVMPositionBuilderAtEnd(builder, body_block); + LLVMBuildBr(builder, after_block); + } + + g_array_free(cond_blocks, TRUE); + g_array_free(body_blocks, TRUE); + g_array_free(cond_values, TRUE); return err; }