Add support for if-else

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
Slendi 2024-03-01 14:07:11 +02:00
parent 5dc73ab5f2
commit 92c8509125
4 changed files with 104 additions and 2 deletions

View File

@ -259,9 +259,53 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
}
}
generate_llvm_scope :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, function: LLVMValueRef, scope: ^Node, scope_number: ^i32) {
generate_llvm_if :: proc(
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, function: LLVMValueRef,
node: ^Node, scope_number: ^i32
) {
condition_node := node.children[0]
true_node := node.children[1]
false_node := node.children[2]
bb := LLVMGetLastBasicBlock(function)
condition := generate_llvm_expression(ctx, mod, builder, condition_node)
if condition == nil {
return
}
int_32_type := LLVMInt32TypeInContext(ctx)
comparison_res := LLVMBuildICmp(builder, .LLVMIntNE, condition, LLVMConstInt(int_32_type, 0, LLVMBool(1)), "")
true_block := LLVMAppendBasicBlockInContext(ctx, function, "")
false_block := LLVMCreateBasicBlockInContext(ctx, "")
end_block := LLVMCreateBasicBlockInContext(ctx, "")
cond_br := LLVMBuildCondBr(builder, comparison_res, true_block, false_block)
LLVMPositionBuilderAtEnd(builder, true_block)
generate_llvm_scope(ctx, mod, builder, function, true_node, scope_number, true_block)
LLVMBuildBr(builder, end_block)
true_block = LLVMGetInsertBlock(builder)
LLVMAppendExistingBasicBlock(function, false_block)
LLVMPositionBuilderAtEnd(builder, false_block)
generate_llvm_scope(ctx, mod, builder, function, false_node, scope_number, false_block)
LLVMBuildBr(builder, end_block)
false_block = LLVMGetInsertBlock(builder)
LLVMPositionBuilderAtEnd(builder, end_block)
LLVMAppendExistingBasicBlock(function, end_block)
}
generate_llvm_scope :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, function: LLVMValueRef, scope: ^Node, scope_number: ^i32, bb: LLVMBasicBlockRef = nil) {
scope_name := get_basic_block_name(scope_number^)
basic_block := LLVMAppendBasicBlockInContext(ctx, function, scope_name)
basic_block : LLVMBasicBlockRef
if bb != nil {
basic_block = bb
} else {
basic_block = LLVMAppendBasicBlockInContext(ctx, function, scope_name)
}
llvm_scope_enter(scope_name, basic_block)
LLVMPositionBuilderAtEnd(builder, basic_block)
scope_number^ += 1
@ -289,6 +333,8 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
}
llvm_top_scope().definitions[get_character_sum_of_dyn_arr(&node.children[0].value.([dynamic]u8))] = var
llvm_top_scope().types[get_character_sum_of_dyn_arr(&node.children[0].value.([dynamic]u8))] = type
case .If:
generate_llvm_if(ctx, mod, builder, function, node, scope_number)
case:
panic("FIXME: Implement other node kinds")
}

View File

@ -46,6 +46,19 @@ LLVMTypeKind :: enum {
LLVMTargetExtTypeKind,
}
LLVMIntPredicate :: enum {
LLVMIntEQ = 32,
LLVMIntNE,
LLVMIntUGT,
LLVMIntUGE,
LLVMIntULT,
LLVMIntULE,
LLVMIntSGT,
LLVMIntSGE,
LLVMIntSLT,
LLVMIntSLE,
}
@(default_calling_convention = "std")
foreign llvmc {
LLVMContextCreate :: proc() -> LLVMContextRef ---
@ -86,6 +99,11 @@ foreign llvmc {
LLVMAddFunction :: proc(M: LLVMModuleRef, Name: cstring, FunctionType: LLVMTypeRef) -> LLVMValueRef ---
LLVMAppendBasicBlockInContext :: proc(C: LLVMContextRef, Fn: LLVMValueRef, Name: cstring) -> LLVMBasicBlockRef ---
LLVMCreateBasicBlockInContext :: proc(C: LLVMContextRef, Name: cstring) -> LLVMBasicBlockRef ---
LLVMGetLastBasicBlock :: proc(Fn: LLVMValueRef) -> LLVMBasicBlockRef ---
LLVMGetInsertBlock :: proc(Builder: LLVMBuilderRef) -> LLVMBasicBlockRef ---
LLVMInsertExistingBasicBlockAfterInsertBlock :: proc(Builder: LLVMBuilderRef, Block: LLVMBasicBlockRef) ---
LLVMAppendExistingBasicBlock :: proc(Fn: LLVMValueRef, Block: LLVMBasicBlockRef) ---
LLVMPrintModuleToFile :: proc(M: LLVMModuleRef, Filename: cstring, ErrorMessage: ^cstring) -> LLVMBool ---
@ -107,8 +125,16 @@ foreign llvmc {
LLVMBuildAlloca :: proc(Builder: LLVMBuilderRef, Ty: LLVMTypeRef, Name: cstring) -> LLVMValueRef ---
LLVMBuildStore :: proc(Builder: LLVMBuilderRef, Val: LLVMValueRef, Ptr: LLVMValueRef) -> LLVMValueRef ---
LLVMBuildLoad2 :: proc(Builder: LLVMBuilderRef, Ty: LLVMTypeRef, PointerVal: LLVMValueRef, Name: cstring) -> LLVMValueRef ---
LLVMBuildBr :: proc(Builder: LLVMBuilderRef, Dest: LLVMBasicBlockRef) -> LLVMValueRef ---
LLVMBuildCondBr :: proc(Builder: LLVMBuilderRef, If: LLVMValueRef, Then: LLVMBasicBlockRef, Else: LLVMBasicBlockRef) -> LLVMValueRef ---
LLVMBuildICmp :: proc(Builder: LLVMBuilderRef, Predicate: LLVMIntPredicate, LHS: LLVMValueRef, RHS: LLVMValueRef, Name: cstring) -> LLVMValueRef ---
LLVMBuildPhi :: proc(Builder: LLVMBuilderRef, Ty: LLVMTypeRef, Name: cstring) -> LLVMValueRef ---
LLVMTypeOf :: proc(Val: LLVMValueRef) -> LLVMTypeRef ---
LLVMAddIncoming :: proc(PhiNode: LLVMValueRef, IncomingValues: [^]LLVMValueRef, IncomingBlocks: [^]LLVMBasicBlockRef, Count: uint) ---
LLVMDisposeBuilder :: proc(Builder: LLVMBuilderRef) ---
LLVMDisposeModule :: proc(M: LLVMModuleRef) ---
LLVMContextDispose :: proc(C: LLVMContextRef) ---

View File

@ -145,6 +145,10 @@ type_check_function_call :: proc(ast: ^Node, parent_ast: ^Node, must_be_function
type_check :: proc(ast: ^Node, parent_ast: ^Node) {
in_extern := false
if ast == nil {
return
}
#partial switch (ast.kind) {
case .Integer: fallthrough
case .Float: fallthrough
@ -301,6 +305,22 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) {
ast.return_type = ast_to_type(ast.children[1])
}
scope_stack[len(scope_stack) - 1].variable_definitions[get_character_sum_of_dyn_arr(&ast.children[0].value.([dynamic]u8))] = ast.return_type
case .If:
type_check(ast.children[0], ast)
if ast.children[0].return_type == nil || ast.children[0].return_type.kind != .Integer {
append(&g_message_list,
message_create(
.Error,
fmt.aprintf("If condition must be a signed/unsigned integer"),
ast.children[0].range,
),
)
break
}
type_check(ast.children[1], ast)
if len(ast.children) == 3 {
type_check(ast.children[2], ast)
}
case .ExternFunction:
in_extern = true
fallthrough

View File

@ -14,3 +14,13 @@ fn put_i32(val: i32) i32
let amogus := 500 + (put_i32 8008135)
put_i32 69 * amogus + 420
if 0 {
if 0 {
put_i32 123
} else {
put_i32 69
}
} else {
put_i32 456
}