diff --git a/src/llvm_emitter.odin b/src/llvm_emitter.odin index c0cdb00..ade0d14 100644 --- a/src/llvm_emitter.odin +++ b/src/llvm_emitter.odin @@ -254,6 +254,72 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil return LLVMBuildURem(builder, lhs, rhs, "modtmp") } } + case .BitwiseLeftShift: + return LLVMBuildShl(builder, lhs, rhs, "shltmp") + case .BitwiseRightShift: + if is_signed { + return LLVMBuildAShr(builder, lhs, rhs, "ashrtmp") + } else { + return LLVMBuildLShr(builder, lhs, rhs, "lshrtmp") + } + case .BitwiseAnd: + return LLVMBuildAnd(builder, lhs, rhs, "andtmp") + case .BitwiseOr: + return LLVMBuildOr(builder, lhs, rhs, "ortmp") + case .BitwiseXOR: + return LLVMBuildXor(builder, lhs, rhs, "xortmp") + case .Equals: + if is_float { + return LLVMBuildFCmp(builder, .LLVMRealOEQ, lhs, rhs, "eqtmp") + } else { + return LLVMBuildICmp(builder, .LLVMIntEQ, lhs, rhs, "eqtmp") + } + case .NotEquals: + if is_float { + return LLVMBuildFCmp(builder, .LLVMRealONE, lhs, rhs, "neqtmp") + } else { + return LLVMBuildICmp(builder, .LLVMIntNE, lhs, rhs, "neqtmp") + } + case .LessThan: + if is_float { + return LLVMBuildFCmp(builder, .LLVMRealOLT, lhs, rhs, "lttmp") + } else { + if is_signed { + return LLVMBuildICmp(builder, .LLVMIntSLT, lhs, rhs, "lttmp") + } else { + return LLVMBuildICmp(builder, .LLVMIntULT, lhs, rhs, "lttmp") + } + } + case .LessThanOrEqual: + if is_float { + return LLVMBuildFCmp(builder, .LLVMRealOLE, lhs, rhs, "letmp") + } else { + if is_signed { + return LLVMBuildICmp(builder, .LLVMIntSLE, lhs, rhs, "letmp") + } else { + return LLVMBuildICmp(builder, .LLVMIntULE, lhs, rhs, "letmp") + } + } + case .GreaterThan: + if is_float { + return LLVMBuildFCmp(builder, .LLVMRealOGT, lhs, rhs, "gttmp") + } else { + if is_signed { + return LLVMBuildICmp(builder, .LLVMIntSGT, lhs, rhs, "gttmp") + } else { + return LLVMBuildICmp(builder, .LLVMIntUGT, lhs, rhs, "gttmp") + } + } + case .GreaterThanOrEqual: + if is_float { + return LLVMBuildFCmp(builder, .LLVMRealOGE, lhs, rhs, "getmp") + } else { + if is_signed { + return LLVMBuildICmp(builder, .LLVMIntSGE, lhs, rhs, "getmp") + } else { + return LLVMBuildICmp(builder, .LLVMIntUGE, lhs, rhs, "getmp") + } + } case: fmt.panicf("LLVM-C: Unexpected binary expression kind: {}", op) } @@ -273,7 +339,16 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil if condition == nil { return } - int_32_type := LLVMInt32TypeInContext(ctx) + int_32_type : LLVMTypeRef + if condition_node.return_type.kind == .Float { + if condition_node.return_type.bit_size == 64 { + int_32_type = LLVMDoubleTypeInContext(ctx) + } else { + int_32_type = LLVMFloatTypeInContext(ctx) + } + } else { + int_32_type = LLVMIntTypeInContext(ctx, uint(condition_node.return_type.bit_size)) + } comparison_res := LLVMBuildICmp(builder, .LLVMIntNE, condition, LLVMConstInt(int_32_type, 0, LLVMBool(1)), "") true_block := LLVMAppendBasicBlockInContext(ctx, function, "") diff --git a/src/llvmc.odin b/src/llvmc.odin index 22f94ed..6225745 100644 --- a/src/llvmc.odin +++ b/src/llvmc.odin @@ -59,6 +59,25 @@ LLVMIntPredicate :: enum { LLVMIntSLE, } +LLVMRealPredicate :: enum { + LLVMRealPredicateFalse, + LLVMRealOEQ, + LLVMRealOGT, + LLVMRealOGE, + LLVMRealOLT, + LLVMRealOLE, + LLVMRealONE, + LLVMRealORD, + LLVMRealUNO, + LLVMRealUEQ, + LLVMRealUGT, + LLVMRealUGE, + LLVMRealULT, + LLVMRealULE, + LLVMRealUNE, + LLVMRealPredicateTrue +}; + @(default_calling_convention = "std") foreign llvmc { LLVMContextCreate :: proc() -> LLVMContextRef --- @@ -89,6 +108,8 @@ foreign llvmc { LLVMVoidTypeInContext :: proc(C: LLVMContextRef) -> LLVMTypeRef --- + LLVMGetTypeKind :: proc(Ty: LLVMTypeRef) -> LLVMTypeKind --- + LLVMArrayType2 :: proc(ElementType: LLVMTypeRef, ElementCount: u64) -> LLVMTypeRef --- LLVMPointerType :: proc(ElementType: LLVMTypeRef, AddressSpace: uint) -> LLVMTypeRef --- @@ -128,6 +149,16 @@ foreign llvmc { 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 --- + LLVMBuildFCmp :: proc(Builder: LLVMBuilderRef, Predicate: LLVMRealPredicate, LHS: LLVMValueRef, RHS: LLVMValueRef, Name: cstring) -> LLVMValueRef --- + + LLVMBuildAnd :: proc(Builder: LLVMBuilderRef, LHS: LLVMValueRef, RHS: LLVMValueRef, Name: cstring) -> LLVMValueRef --- + LLVMBuildOr :: proc(Builder: LLVMBuilderRef, LHS: LLVMValueRef, RHS: LLVMValueRef, Name: cstring) -> LLVMValueRef --- + LLVMBuildXor :: proc(Builder: LLVMBuilderRef, LHS: LLVMValueRef, RHS: LLVMValueRef, Name: cstring) -> LLVMValueRef --- + LLVMBuildNot :: proc(Builder: LLVMBuilderRef, Val: LLVMValueRef, Name: cstring) -> LLVMValueRef --- + LLVMBuildShl :: proc(Builder: LLVMBuilderRef, LHS: LLVMValueRef, RHS: LLVMValueRef, Name: cstring) -> LLVMValueRef --- + LLVMBuildLShr :: proc(Builder: LLVMBuilderRef, LHS: LLVMValueRef, RHS: LLVMValueRef, Name: cstring) -> LLVMValueRef --- + LLVMBuildAShr :: proc(Builder: LLVMBuilderRef, LHS: LLVMValueRef, RHS: LLVMValueRef, Name: cstring) -> LLVMValueRef --- + LLVMBuildShr :: proc(Builder: LLVMBuilderRef, LHS: LLVMValueRef, RHS: LLVMValueRef, Name: cstring) -> LLVMValueRef --- LLVMBuildPhi :: proc(Builder: LLVMBuilderRef, Ty: LLVMTypeRef, Name: cstring) -> LLVMValueRef --- diff --git a/src/type_checker.odin b/src/type_checker.odin index fd6beb0..eb41762 100644 --- a/src/type_checker.odin +++ b/src/type_checker.odin @@ -237,7 +237,10 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { ) } + ast.return_type = ast.children[0].return_type + if ast.value_token_kind == .Assign { + ast.return_type = nil if !scope_stack[len(scope_stack) - 1].variable_mutability_definitions[get_character_sum_of_dyn_arr(&ast.children[0].value.([dynamic]u8))] { append(&g_message_list, message_create( @@ -247,10 +250,12 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { ), ) } + } else if ast.value_token_kind == .Equals || ast.value_token_kind == .NotEquals || + ast.value_token_kind == .GreaterThan || ast.value_token_kind == .GreaterThanOrEqual || + ast.value_token_kind == .LessThan || ast.value_token_kind == .LessThanOrEqual { + ast.return_type = type_create_integer(1, true) } - ast.return_type = ast.children[0].return_type - // FIXME: Verify that the operation is possible case .UnaryExpression: // FIXME: Verify that the operation is possible diff --git a/test_type_checker.cat b/test_type_checker.cat index ea19a7c..d52363d 100644 --- a/test_type_checker.cat +++ b/test_type_checker.cat @@ -7,16 +7,18 @@ \name 123.0 456.0 -let arr: []i32, arr2: [69]u8, ptr: ^i32 +\let arr: []i32, arr2: [69]u8, ptr: ^i32 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 +let a b := 5 1 -if 0 { - if 0 { +if a == 5 { + if b { put_i32 123 } else { put_i32 69