feature: added if statement

This commit is contained in:
Sven Vogel 2024-05-30 13:11:51 +02:00
parent a5b5a04762
commit 7e59ac3520
1 changed files with 85 additions and 5 deletions

View File

@ -118,16 +118,96 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit,
return err; 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, BackendError impl_branch(LLVMBackendCompileUnit *unit,
LLVMBuilderRef builder, LLVMLocalScope *scope, LLVMBuilderRef builder, LLVMLocalScope *scope,
const Branch *branch) { const Branch *branch) {
BackendError err = SUCCESS; BackendError err = SUCCESS;
LLVMBasicBlockRef if_cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, GArray *cond_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef));
"stmt.branch.cond"); GArray *body_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef));
// Resolve condition in block to a variable GArray *cond_values = g_array_new(FALSE, FALSE, sizeof(LLVMValueRef));
LLVMValueRef cond_result = NULL;
impl_expr(unit, scope, builder, &branch->ifBranch.conditon, &cond_result); // 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; return err;
} }