Make the compiler work on macOS

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
Slendi 2024-03-10 01:16:25 +02:00
parent 1092c68317
commit e4289d577a
5 changed files with 677 additions and 579 deletions

5
odinfmt.json Normal file
View File

@ -0,0 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/odinfmt.schema.json",
"character_width": "120"
}

View File

@ -33,27 +33,30 @@ llvm_scope_find_type :: proc(name: ^[dynamic]u8) -> LLVMTypeRef {
} }
llvm_scope_enter :: proc(name: cstring, basic_block: LLVMBasicBlockRef) { llvm_scope_enter :: proc(name: cstring, basic_block: LLVMBasicBlockRef) {
append(&g_llvm_scope_stack, LLVMScope{ append(
&g_llvm_scope_stack,
LLVMScope {
name = name, name = name,
basic_block = basic_block, basic_block = basic_block,
definitions = make(map[int]LLVMValueRef), definitions = make(map[int]LLVMValueRef),
types = make(map[int]LLVMTypeRef), types = make(map[int]LLVMTypeRef),
}) },
)
} }
llvm_scope_leave :: proc() { llvm_scope_leave :: proc() {
delete(g_llvm_scope_stack[len(g_llvm_scope_stack)-1].definitions) delete(g_llvm_scope_stack[len(g_llvm_scope_stack) - 1].definitions)
delete(g_llvm_scope_stack[len(g_llvm_scope_stack)-1].types) delete(g_llvm_scope_stack[len(g_llvm_scope_stack) - 1].types)
pop(&g_llvm_scope_stack) pop(&g_llvm_scope_stack)
} }
llvm_top_scope :: proc() -> ^LLVMScope { llvm_top_scope :: proc() -> ^LLVMScope {
return &g_llvm_scope_stack[len(g_llvm_scope_stack)-1] return &g_llvm_scope_stack[len(g_llvm_scope_stack) - 1]
} }
generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, node: ^Node) { generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, node: ^Node) {
// FIXME: Everything leaks memory. // FIXME: Everything leaks memory.
scope_number : i32 = 0 scope_number: i32 = 0
int_32_type := LLVMInt32TypeInContext(ctx) int_32_type := LLVMInt32TypeInContext(ctx)
main_function_type := LLVMFunctionType(int_32_type, nil, 0, LLVMBool(0)) main_function_type := LLVMFunctionType(int_32_type, nil, 0, LLVMBool(0))
@ -63,14 +66,24 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
return fmt.caprintf("scope_%d", scope_num) return fmt.caprintf("scope_%d", scope_num)
} }
generate_llvm_integer :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, node: ^Node) -> LLVMValueRef { generate_llvm_integer :: proc(
ctx: LLVMContextRef,
mod: LLVMModuleRef,
builder: LLVMBuilderRef,
node: ^Node,
) -> LLVMValueRef {
bit_size := uint(node.return_type.bit_size) bit_size := uint(node.return_type.bit_size)
value := node.value.(u64) value := node.value.(u64)
is_signed := node.return_type.is_signed is_signed := node.return_type.is_signed
return LLVMConstInt(LLVMIntTypeInContext(ctx, bit_size), value, LLVMBool(is_signed)) return LLVMConstInt(LLVMIntTypeInContext(ctx, bit_size), value, LLVMBool(is_signed))
} }
generate_llvm_float :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, node: ^Node) -> LLVMValueRef { generate_llvm_float :: proc(
ctx: LLVMContextRef,
mod: LLVMModuleRef,
builder: LLVMBuilderRef,
node: ^Node,
) -> LLVMValueRef {
bit_size := uint(node.return_type.bit_size) bit_size := uint(node.return_type.bit_size)
value := node.value.(f64) value := node.value.(f64)
if bit_size == 64 { if bit_size == 64 {
@ -81,16 +94,17 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
append( append(
&g_message_list, &g_message_list,
message_create( message_create(.Error, fmt.aprintf("Unsupported float bit size: %d", bit_size), node.range),
.Error,
fmt.aprintf("Unsupported float bit size: %d", bit_size),
node.range,
),
) )
return nil return nil
} }
generate_llvm_type_from_node :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, type: ^Type) -> LLVMTypeRef { generate_llvm_type_from_node :: proc(
ctx: LLVMContextRef,
mod: LLVMModuleRef,
builder: LLVMBuilderRef,
type: ^Type,
) -> LLVMTypeRef {
if type == nil { if type == nil {
return LLVMVoidTypeInContext(ctx) return LLVMVoidTypeInContext(ctx)
} }
@ -117,9 +131,15 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
} }
generate_llvm_function_extern :: proc( generate_llvm_function_extern :: proc(
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, ctx: LLVMContextRef,
fn: ^Node, scope_number: ^i32 mod: LLVMModuleRef,
) -> (type: LLVMTypeRef, value: LLVMValueRef) { builder: LLVMBuilderRef,
fn: ^Node,
scope_number: ^i32,
) -> (
type: LLVMTypeRef,
value: LLVMValueRef,
) {
function_args_type := [dynamic]LLVMTypeRef{} function_args_type := [dynamic]LLVMTypeRef{}
for arg in fn.children { for arg in fn.children {
if arg.kind != .VariableDeclaration { if arg.kind != .VariableDeclaration {
@ -129,13 +149,49 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
} }
function_return_type := generate_llvm_type_from_node(ctx, mod, builder, fn.return_type) function_return_type := generate_llvm_type_from_node(ctx, mod, builder, fn.return_type)
type = LLVMFunctionType(function_return_type, raw_data(function_args_type[:]), len(function_args_type), LLVMBool(0)) type = LLVMFunctionType(
function_return_type,
raw_data(function_args_type[:]),
len(function_args_type),
LLVMBool(0),
)
value = LLVMAddFunction(mod, strings.clone_to_cstring(string(fn.value.([dynamic]u8)[:])), type)
return
}
generate_llvm_function :: proc(
ctx: LLVMContextRef,
mod: LLVMModuleRef,
builder: LLVMBuilderRef,
fn: ^Node,
scope_number: ^i32,
) -> (
type: LLVMTypeRef,
value: LLVMValueRef,
) {
function_args_type := [dynamic]LLVMTypeRef{}
for arg in fn.children {
if arg.kind != .VariableDeclaration {
continue
}
append(&function_args_type, generate_llvm_type_from_node(ctx, mod, builder, arg.return_type))
}
function_return_type := generate_llvm_type_from_node(ctx, mod, builder, fn.return_type)
type = LLVMFunctionType(
function_return_type,
raw_data(function_args_type[:]),
len(function_args_type),
LLVMBool(0),
)
value = LLVMAddFunction(mod, strings.clone_to_cstring(string(fn.value.([dynamic]u8)[:])), type) value = LLVMAddFunction(mod, strings.clone_to_cstring(string(fn.value.([dynamic]u8)[:])), type)
return return
} }
generate_llvm_function_call :: proc( generate_llvm_function_call :: proc(
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, ctx: LLVMContextRef,
mod: LLVMModuleRef,
builder: LLVMBuilderRef,
node: ^Node, node: ^Node,
) -> LLVMValueRef { ) -> LLVMValueRef {
// FIXME: Add support for dot access // FIXME: Add support for dot access
@ -143,14 +199,7 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
fn_type := llvm_scope_find_type(name) fn_type := llvm_scope_find_type(name)
fn_value := llvm_scope_find_definition(name) fn_value := llvm_scope_find_definition(name)
if fn_type == nil || fn_value == nil { if fn_type == nil || fn_value == nil {
append( append(&g_message_list, message_create(.Error, fmt.aprintf("Function '%s' not found", name), node.range))
&g_message_list,
message_create(
.Error,
fmt.aprintf("Function '%s' not found", name),
node.range,
),
)
return nil return nil
} }
@ -160,12 +209,21 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
append(&fn_args, value) append(&fn_args, value)
} }
call := LLVMBuildCall2(builder, fn_type, fn_value, raw_data(fn_args[:]), len(fn_args), cstring(raw_data(name[:]))) call := LLVMBuildCall2(
builder,
fn_type,
fn_value,
raw_data(fn_args[:]),
len(fn_args),
cstring(raw_data(name[:])),
)
return call return call
} }
generate_llvm_value :: proc( generate_llvm_value :: proc(
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, ctx: LLVMContextRef,
mod: LLVMModuleRef,
builder: LLVMBuilderRef,
node: ^Node, node: ^Node,
) -> LLVMValueRef { ) -> LLVMValueRef {
if node.kind == .Integer { if node.kind == .Integer {
@ -186,7 +244,9 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
} }
generate_llvm_expression :: proc( generate_llvm_expression :: proc(
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, ctx: LLVMContextRef,
mod: LLVMModuleRef,
builder: LLVMBuilderRef,
node: ^Node, node: ^Node,
) -> LLVMValueRef { ) -> LLVMValueRef {
if node.kind == .BinaryExpression { if node.kind == .BinaryExpression {
@ -202,7 +262,9 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
} }
generate_llvm_binary_expression :: proc( generate_llvm_binary_expression :: proc(
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, ctx: LLVMContextRef,
mod: LLVMModuleRef,
builder: LLVMBuilderRef,
node: ^Node, node: ^Node,
) -> LLVMValueRef { ) -> LLVMValueRef {
op := node.value_token_kind op := node.value_token_kind
@ -211,7 +273,11 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
lhs := generate_llvm_expression(ctx, mod, builder, lhs_node) lhs := generate_llvm_expression(ctx, mod, builder, lhs_node)
rhs := generate_llvm_expression(ctx, mod, builder, rhs_node) rhs := generate_llvm_expression(ctx, mod, builder, rhs_node)
if lhs_node.return_type.kind != rhs_node.return_type.kind { if lhs_node.return_type.kind != rhs_node.return_type.kind {
fmt.panicf("LLVM-C: Binary expression types do not match: {} and {}", lhs_node.return_type.kind, rhs_node.return_type.kind) fmt.panicf(
"LLVM-C: Binary expression types do not match: {} and {}",
lhs_node.return_type.kind,
rhs_node.return_type.kind,
)
} }
is_float := lhs_node.return_type.kind == .Float is_float := lhs_node.return_type.kind == .Float
is_signed := lhs_node.return_type.is_signed is_signed := lhs_node.return_type.is_signed
@ -329,11 +395,7 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
if def == nil { if def == nil {
append( append(
&g_message_list, &g_message_list,
message_create( message_create(.Error, fmt.aprintf("Variable '%s' not found", name), node.range),
.Error,
fmt.aprintf("Variable '%s' not found", name),
node.range,
),
) )
return nil return nil
} }
@ -344,8 +406,12 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
} }
generate_llvm_if :: proc( generate_llvm_if :: proc(
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, function: LLVMValueRef, ctx: LLVMContextRef,
node: ^Node, scope_number: ^i32 mod: LLVMModuleRef,
builder: LLVMBuilderRef,
function: LLVMValueRef,
node: ^Node,
scope_number: ^i32,
) { ) {
condition_node := node.children[0] condition_node := node.children[0]
true_node := node.children[1] true_node := node.children[1]
@ -357,7 +423,7 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
if condition == nil { if condition == nil {
return return
} }
int_32_type : LLVMTypeRef int_32_type: LLVMTypeRef
if condition_node.return_type.kind == .Float { if condition_node.return_type.kind == .Float {
if condition_node.return_type.bit_size == 64 { if condition_node.return_type.bit_size == 64 {
int_32_type = LLVMDoubleTypeInContext(ctx) int_32_type = LLVMDoubleTypeInContext(ctx)
@ -392,8 +458,12 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
} }
generate_llvm_for :: proc( generate_llvm_for :: proc(
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, function: LLVMValueRef, ctx: LLVMContextRef,
node: ^Node, scope_number: ^i32 mod: LLVMModuleRef,
builder: LLVMBuilderRef,
function: LLVMValueRef,
node: ^Node,
scope_number: ^i32,
) { ) {
sum_nils := 0 sum_nils := 0
for i in node.children { for i in node.children {
@ -407,10 +477,12 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
While, While,
} }
loop_type : LoopType loop_type: LoopType
switch sum_nils { switch sum_nils {
case 3: loop_type = LoopType.Infinite case 3:
case 2: loop_type = LoopType.While loop_type = LoopType.Infinite
case 2:
loop_type = LoopType.While
case: case:
panic("FIXME: Implement other for loop types") panic("FIXME: Implement other for loop types")
} }
@ -447,9 +519,17 @@ 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, bb: LLVMBasicBlockRef = nil) { 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 : LLVMBasicBlockRef basic_block: LLVMBasicBlockRef
if bb != nil { if bb != nil {
basic_block = bb basic_block = bb
} else { } else {
@ -463,21 +543,30 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil
case .Block: case .Block:
generate_llvm_scope(ctx, mod, builder, function, node, scope_number) generate_llvm_scope(ctx, mod, builder, function, node, scope_number)
case .Function: case .Function:
panic("FIXME: Implement function delarations") type, value := generate_llvm_function(ctx, mod, builder, node, scope_number)
case .ExternFunction:
type, value := generate_llvm_function_extern(ctx, mod, builder, node, scope_number)
//name := LLVMGetValueName2(value, nil)
llvm_top_scope().definitions[get_character_sum_of_dyn_arr(&node.value.([dynamic]u8))] = value llvm_top_scope().definitions[get_character_sum_of_dyn_arr(&node.value.([dynamic]u8))] = value
llvm_top_scope().types[get_character_sum_of_dyn_arr(&node.value.([dynamic]u8))] = type llvm_top_scope().types[get_character_sum_of_dyn_arr(&node.value.([dynamic]u8))] = type
case .Integer: fallthrough case .ExternFunction:
case .Float: fallthrough type, value := generate_llvm_function_extern(ctx, mod, builder, node, scope_number)
case .Identifier: fallthrough llvm_top_scope().definitions[get_character_sum_of_dyn_arr(&node.value.([dynamic]u8))] = value
case .FunctionCall: fallthrough llvm_top_scope().types[get_character_sum_of_dyn_arr(&node.value.([dynamic]u8))] = type
case .Integer:
fallthrough
case .Float:
fallthrough
case .Identifier:
fallthrough
case .FunctionCall:
fallthrough
case .BinaryExpression: case .BinaryExpression:
generate_llvm_expression(ctx, mod, builder, node) generate_llvm_expression(ctx, mod, builder, node)
case .VariableDeclaration: case .VariableDeclaration:
type := generate_llvm_type_from_node(ctx, mod, builder, node.return_type) type := generate_llvm_type_from_node(ctx, mod, builder, node.return_type)
var := LLVMBuildAlloca(builder, type, strings.clone_to_cstring(string(node.children[0].value.([dynamic]u8)[:]))) var := LLVMBuildAlloca(
builder,
type,
strings.clone_to_cstring(string(node.children[0].value.([dynamic]u8)[:])),
)
if node.children[2] != nil { if node.children[2] != nil {
value := generate_llvm_expression(ctx, mod, builder, node.children[2]) value := generate_llvm_expression(ctx, mod, builder, node.children[2])
LLVMBuildStore(builder, value, var) LLVMBuildStore(builder, value, var)

View File

@ -1,6 +1,10 @@
package main package main
foreign import llvmc "LLVM-C.lib" when ODIN_OS == .Windows {
foreign import llvmc "llvm/win64/LLVM-C.lib"
} else when ODIN_OS == .Linux || ODIN_OS == .Darwin {
foreign import llvmc "system:LLVM-C"
}
LLVMBool :: distinct int LLVMBool :: distinct int
LLVMMemoryBufferRef :: distinct rawptr LLVMMemoryBufferRef :: distinct rawptr
@ -75,10 +79,10 @@ LLVMRealPredicate :: enum {
LLVMRealULT, LLVMRealULT,
LLVMRealULE, LLVMRealULE,
LLVMRealUNE, LLVMRealUNE,
LLVMRealPredicateTrue LLVMRealPredicateTrue,
}; }
@(default_calling_convention = "std") @(default_calling_convention = "c")
foreign llvmc { foreign llvmc {
LLVMContextCreate :: proc() -> LLVMContextRef --- LLVMContextCreate :: proc() -> LLVMContextRef ---
LLVMModuleCreateWithName :: proc(name: cstring) -> LLVMModuleRef --- LLVMModuleCreateWithName :: proc(name: cstring) -> LLVMModuleRef ---

View File

@ -2,7 +2,7 @@
- [x] Create a TODO list - [x] Create a TODO list
- [ ] Custom Functions (not external) - [ ] Custom Functions (not external)
- [ ] Add support for function definitions in the type checker - [x] Add support for function definitions in the type checker
- [ ] Add support for function definitions in the LLVM emitter - [ ] Add support for function definitions in the LLVM emitter
- [ ] Structures - [ ] Structures
- [ ] Add support for packed in the parser - [ ] Add support for packed in the parser