diff --git a/src/llvmc.odin b/src/llvmc.odin index 5a51ab8..17b10e4 100644 --- a/src/llvmc.odin +++ b/src/llvmc.odin @@ -22,6 +22,30 @@ LLVMComdatRef :: distinct rawptr LLVMJITEventListenerRef :: distinct rawptr LLVMBinaryRef :: distinct rawptr +LLVMTypeKind :: enum { + LLVMVoidTypeKind, + LLVMHalfTypeKind, + LLVMFloatTypeKind, + LLVMDoubleTypeKind, + LLVMX86_FP80TypeKind, + LLVMFP128TypeKind, + LLVMPPC_FP128TypeKind, + LLVMLabelTypeKind, + LLVMIntegerTypeKind, + LLVMFunctionTypeKind, + LLVMStructTypeKind, + LLVMArrayTypeKind, + LLVMPointerTypeKind, + LLVMVectorTypeKind, + LLVMMetadataTypeKind, + LLVMX86_MMXTypeKind, + LLVMTokenTypeKind, + LLVMScalableVectorTypeKind, + LLVMBFloatTypeKind, + LLVMX86_AMXTypeKind, + LLVMTargetExtTypeKind, +} + @(default_calling_convention = "std") foreign llvmc { LLVMContextCreate :: proc() -> LLVMContextRef --- @@ -47,9 +71,15 @@ foreign llvmc { LLVMInt64TypeInContext :: proc(C: LLVMContextRef) -> LLVMTypeRef --- LLVMIntTypeInContext :: proc(C: LLVMContextRef, n: uint) -> LLVMTypeRef --- + LLVMDoubleTypeInContext :: proc(C: LLVMContextRef) -> LLVMTypeRef --- + LLVMFloatTypeInContext :: proc(C: LLVMContextRef) -> LLVMTypeRef --- + + LLVMVoidTypeInContext :: proc(C: LLVMContextRef) -> LLVMTypeRef --- + LLVMPointerType :: proc(ElementType: LLVMTypeRef, AddressSpace: uint) -> LLVMTypeRef --- LLVMConstInt :: proc(IntTy: LLVMTypeRef, N: u64, SignExtend: LLVMBool) -> LLVMValueRef --- + LLVMConstReal :: proc(RealTy: LLVMTypeRef, N: f64) -> LLVMValueRef --- LLVMFunctionType :: proc(ReturnType: LLVMTypeRef, ParamTypes: [^]LLVMTypeRef, ParamCount: uint, IsVarArg: LLVMBool) -> LLVMTypeRef --- LLVMAddFunction :: proc(M: LLVMModuleRef, Name: cstring, FunctionType: LLVMTypeRef) -> LLVMValueRef --- @@ -58,6 +88,8 @@ foreign llvmc { LLVMPrintModuleToFile :: proc(M: LLVMModuleRef, Filename: cstring, ErrorMessage: ^cstring) -> LLVMBool --- + LLVMGetValueName2 :: proc(V: LLVMValueRef, Length: ^u64) -> cstring --- + LLVMDisposeBuilder :: proc(Builder: LLVMBuilderRef) --- LLVMDisposeModule :: proc(M: LLVMModuleRef) --- LLVMContextDispose :: proc(C: LLVMContextRef) --- diff --git a/src/main.odin b/src/main.odin index a57b8e5..834d55a 100644 --- a/src/main.odin +++ b/src/main.odin @@ -85,5 +85,15 @@ main :: proc() { } node_print(ast) + + ctx := LLVMContextCreate() + defer LLVMContextDispose(ctx) + module := LLVMModuleCreateWithNameInContext("hello", ctx) + defer LLVMDisposeModule(module) + builder := LLVMCreateBuilderInContext(ctx) + + generate_llvm(ctx, module, builder, ast) + + LLVMPrintModuleToFile(module, "hello.ll", nil) } diff --git a/src/type_checker.odin b/src/type_checker.odin index e61bfba..893e881 100644 --- a/src/type_checker.odin +++ b/src/type_checker.odin @@ -33,6 +33,9 @@ is_number :: proc(node: ^Node) -> bool { @(private = "file") ast_to_type :: proc(node: ^Node) -> ^Type { + if node == nil { + return type_create_integer(0, false) + } if node.kind == .Identifier { value := node.value.([dynamic]u8) if value[0] == 'u' { @@ -140,6 +143,8 @@ type_check_function_call :: proc(ast: ^Node, parent_ast: ^Node, must_be_function } type_check :: proc(ast: ^Node, parent_ast: ^Node) { + in_extern := false + #partial switch (ast.kind) { case .Integer: fallthrough case .Float: fallthrough @@ -296,13 +301,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 .ExternFunction: + in_extern = true + fallthrough case .Function: scope_enter() ast.return_type = ast_to_type(ast.children[0]) scope_stack[len(scope_stack) - 1].function_return_type = ast.return_type for child, i in ast.children { - if i < 2 { - continue + if in_extern == false { + if i < 2 { + continue + } + } else { + if i < 1 { + continue + } } type_check(child, ast) scope_stack[len(scope_stack) - 1].variable_definitions[get_character_sum_of_dyn_arr(&child.children[0].value.([dynamic]u8))] = child.return_type @@ -310,9 +324,6 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { } type_check(ast.children[1], ast) scope_leave() - case .ExternFunction: - ast.return_type = ast_to_type(ast.children[0]) - scope_stack[len(scope_stack) - 1].function_return_type = ast.return_type case: fmt.panicf("Unhandled node kind in type_check: {}", ast.kind) } @@ -329,7 +340,7 @@ find_function_definitions :: proc(ast_: ^Node) -> (ret: [dynamic]^FunctionType) is_extern := false #partial switch (ast.kind) { case .ExternFunction: - is_extern := true + is_extern = true fallthrough case .Function: for fn in ret { diff --git a/test_type_checker.cat b/test_type_checker.cat index b8121ee..560cb21 100644 --- a/test_type_checker.cat +++ b/test_type_checker.cat @@ -1,14 +1,14 @@ -let asdf := 0b1101 as f32 -let poop :: 12.0 + 2.0 * asdf +\let asdf := 0b1101 as f32 +\let poop :: 12.0 + 2.0 * asdf -fn name(a b: f32) i32 { - ret (a + b) as i32 -} +\fn name(a b: f32) i32 { +\ ret (a + b) as i32 +\} -fn put_32(str: []u32) +\name 123.0 456.0 -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 -put_32("Hello") +put_i32 69420