Add support for if-else
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
parent
5dc73ab5f2
commit
92c8509125
@ -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")
|
||||
}
|
||||
|
@ -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) ---
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user