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^)
|
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)
|
llvm_scope_enter(scope_name, basic_block)
|
||||||
LLVMPositionBuilderAtEnd(builder, basic_block)
|
LLVMPositionBuilderAtEnd(builder, basic_block)
|
||||||
scope_number^ += 1
|
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().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
|
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:
|
case:
|
||||||
panic("FIXME: Implement other node kinds")
|
panic("FIXME: Implement other node kinds")
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,19 @@ LLVMTypeKind :: enum {
|
|||||||
LLVMTargetExtTypeKind,
|
LLVMTargetExtTypeKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVMIntPredicate :: enum {
|
||||||
|
LLVMIntEQ = 32,
|
||||||
|
LLVMIntNE,
|
||||||
|
LLVMIntUGT,
|
||||||
|
LLVMIntUGE,
|
||||||
|
LLVMIntULT,
|
||||||
|
LLVMIntULE,
|
||||||
|
LLVMIntSGT,
|
||||||
|
LLVMIntSGE,
|
||||||
|
LLVMIntSLT,
|
||||||
|
LLVMIntSLE,
|
||||||
|
}
|
||||||
|
|
||||||
@(default_calling_convention = "std")
|
@(default_calling_convention = "std")
|
||||||
foreign llvmc {
|
foreign llvmc {
|
||||||
LLVMContextCreate :: proc() -> LLVMContextRef ---
|
LLVMContextCreate :: proc() -> LLVMContextRef ---
|
||||||
@ -86,6 +99,11 @@ foreign llvmc {
|
|||||||
LLVMAddFunction :: proc(M: LLVMModuleRef, Name: cstring, FunctionType: LLVMTypeRef) -> LLVMValueRef ---
|
LLVMAddFunction :: proc(M: LLVMModuleRef, Name: cstring, FunctionType: LLVMTypeRef) -> LLVMValueRef ---
|
||||||
|
|
||||||
LLVMAppendBasicBlockInContext :: proc(C: LLVMContextRef, Fn: LLVMValueRef, Name: cstring) -> LLVMBasicBlockRef ---
|
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 ---
|
LLVMPrintModuleToFile :: proc(M: LLVMModuleRef, Filename: cstring, ErrorMessage: ^cstring) -> LLVMBool ---
|
||||||
|
|
||||||
@ -107,8 +125,16 @@ foreign llvmc {
|
|||||||
LLVMBuildAlloca :: proc(Builder: LLVMBuilderRef, Ty: LLVMTypeRef, Name: cstring) -> LLVMValueRef ---
|
LLVMBuildAlloca :: proc(Builder: LLVMBuilderRef, Ty: LLVMTypeRef, Name: cstring) -> LLVMValueRef ---
|
||||||
LLVMBuildStore :: proc(Builder: LLVMBuilderRef, Val: LLVMValueRef, Ptr: LLVMValueRef) -> LLVMValueRef ---
|
LLVMBuildStore :: proc(Builder: LLVMBuilderRef, Val: LLVMValueRef, Ptr: LLVMValueRef) -> LLVMValueRef ---
|
||||||
LLVMBuildLoad2 :: proc(Builder: LLVMBuilderRef, Ty: LLVMTypeRef, PointerVal: LLVMValueRef, Name: cstring) -> 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 ---
|
LLVMTypeOf :: proc(Val: LLVMValueRef) -> LLVMTypeRef ---
|
||||||
|
|
||||||
|
LLVMAddIncoming :: proc(PhiNode: LLVMValueRef, IncomingValues: [^]LLVMValueRef, IncomingBlocks: [^]LLVMBasicBlockRef, Count: uint) ---
|
||||||
|
|
||||||
LLVMDisposeBuilder :: proc(Builder: LLVMBuilderRef) ---
|
LLVMDisposeBuilder :: proc(Builder: LLVMBuilderRef) ---
|
||||||
LLVMDisposeModule :: proc(M: LLVMModuleRef) ---
|
LLVMDisposeModule :: proc(M: LLVMModuleRef) ---
|
||||||
LLVMContextDispose :: proc(C: LLVMContextRef) ---
|
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) {
|
type_check :: proc(ast: ^Node, parent_ast: ^Node) {
|
||||||
in_extern := false
|
in_extern := false
|
||||||
|
|
||||||
|
if ast == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
#partial switch (ast.kind) {
|
#partial switch (ast.kind) {
|
||||||
case .Integer: fallthrough
|
case .Integer: fallthrough
|
||||||
case .Float: 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])
|
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
|
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:
|
case .ExternFunction:
|
||||||
in_extern = true
|
in_extern = true
|
||||||
fallthrough
|
fallthrough
|
||||||
|
@ -14,3 +14,13 @@ fn put_i32(val: i32) i32
|
|||||||
let amogus := 500 + (put_i32 8008135)
|
let amogus := 500 + (put_i32 8008135)
|
||||||
|
|
||||||
put_i32 69 * amogus + 420
|
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