Remove binary
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
parent
5455919d6e
commit
def0e2b8e0
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
speedcat
|
speedcat
|
||||||
speedcat.exe
|
speedcat.exe
|
||||||
speedcat.pdb
|
speedcat.pdb
|
||||||
|
test.exe
|
||||||
|
hello.ll
|
208
src/llvm_emitter.odin
Normal file
208
src/llvm_emitter.odin
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:strings"
|
||||||
|
|
||||||
|
LLVMScope :: struct {
|
||||||
|
name: cstring,
|
||||||
|
basic_block: LLVMBasicBlockRef,
|
||||||
|
definitions: map[int]LLVMValueRef,
|
||||||
|
types: map[int]LLVMTypeRef,
|
||||||
|
}
|
||||||
|
|
||||||
|
g_llvm_scope_stack := [dynamic]LLVMScope{}
|
||||||
|
|
||||||
|
llvm_scope_find_definition :: proc(name: ^[dynamic]u8) -> LLVMValueRef {
|
||||||
|
#reverse for &scope in g_llvm_scope_stack {
|
||||||
|
value, ok := scope.definitions[get_character_sum_of_dyn_arr(name)]
|
||||||
|
if ok {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm_scope_find_type :: proc(name: ^[dynamic]u8) -> LLVMTypeRef {
|
||||||
|
#reverse for &scope in g_llvm_scope_stack {
|
||||||
|
value, ok := scope.types[get_character_sum_of_dyn_arr(name)]
|
||||||
|
if ok {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm_scope_enter :: proc(name: cstring, basic_block: LLVMBasicBlockRef) {
|
||||||
|
append(&g_llvm_scope_stack, LLVMScope{
|
||||||
|
name = name,
|
||||||
|
basic_block = basic_block,
|
||||||
|
definitions = make(map[int]LLVMValueRef),
|
||||||
|
types = make(map[int]LLVMTypeRef),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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].types)
|
||||||
|
pop(&g_llvm_scope_stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm_top_scope :: proc() -> ^LLVMScope {
|
||||||
|
return &g_llvm_scope_stack[len(g_llvm_scope_stack)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, node: ^Node) {
|
||||||
|
// FIXME: Everything leaks memory.
|
||||||
|
scope_number : i32 = 0
|
||||||
|
|
||||||
|
int_32_type := LLVMInt32TypeInContext(ctx)
|
||||||
|
main_function_type := LLVMFunctionType(int_32_type, nil, 0, LLVMBool(0))
|
||||||
|
main_function := LLVMAddFunction(mod, "main", main_function_type)
|
||||||
|
|
||||||
|
get_basic_block_name :: proc(scope_num: i32) -> cstring {
|
||||||
|
return fmt.caprintf("scope_%d", scope_num)
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_llvm_integer :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, node: ^Node) -> LLVMValueRef {
|
||||||
|
bit_size := uint(node.return_type.bit_size)
|
||||||
|
value := node.value.(u64)
|
||||||
|
is_signed := node.return_type.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 {
|
||||||
|
bit_size := uint(node.return_type.bit_size)
|
||||||
|
value := node.value.(f64)
|
||||||
|
if bit_size == 64 {
|
||||||
|
return LLVMConstReal(LLVMDoubleTypeInContext(ctx), value)
|
||||||
|
} else if bit_size == 32 {
|
||||||
|
return LLVMConstReal(LLVMFloatTypeInContext(ctx), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
append(
|
||||||
|
&g_message_list,
|
||||||
|
message_create(
|
||||||
|
.Error,
|
||||||
|
fmt.aprintf("Unsupported float bit size: %d", bit_size),
|
||||||
|
node.range,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_llvm_type_from_node :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, node: ^Node) -> LLVMTypeRef {
|
||||||
|
type := node.return_type
|
||||||
|
if type == nil {
|
||||||
|
return LLVMVoidTypeInContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch type.kind {
|
||||||
|
case .Integer:
|
||||||
|
return LLVMIntTypeInContext(ctx, uint(type.bit_size))
|
||||||
|
case .Float:
|
||||||
|
if type.bit_size == 64 {
|
||||||
|
return LLVMDoubleTypeInContext(ctx)
|
||||||
|
} else if type.bit_size == 32 {
|
||||||
|
return LLVMFloatTypeInContext(ctx)
|
||||||
|
} else {
|
||||||
|
fmt.panicf("LLVM-IR: Unsupported float type bit size: {}", type.bit_size)
|
||||||
|
}
|
||||||
|
case .Array:
|
||||||
|
panic("FIXME: Implement array LLVM IR generation")
|
||||||
|
case .Pointer:
|
||||||
|
panic("FIXME: Implement pointer LLVM IR generation")
|
||||||
|
}
|
||||||
|
panic("LLVM-IR: Invalid type")
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_llvm_function_extern :: 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))
|
||||||
|
}
|
||||||
|
function_return_type := generate_llvm_type_from_node(ctx, mod, builder, fn)
|
||||||
|
|
||||||
|
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_call :: proc(
|
||||||
|
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef,
|
||||||
|
fn_call: ^Node,
|
||||||
|
) -> LLVMValueRef {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_llvm_value :: proc(
|
||||||
|
ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef,
|
||||||
|
node: ^Node,
|
||||||
|
) -> LLVMValueRef {
|
||||||
|
if node.kind == .Integer {
|
||||||
|
return generate_llvm_integer(ctx, mod, builder, node)
|
||||||
|
} else if node.kind == .Float {
|
||||||
|
return generate_llvm_float(ctx, mod, builder, node)
|
||||||
|
} else if node.kind == .FunctionCall {
|
||||||
|
return generate_llvm_function_call(ctx, mod, builder, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("FIXME: Implement other node kinds")
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_llvm_scope :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuilderRef, function: LLVMValueRef, scope: ^Node, scope_number: ^i32) {
|
||||||
|
scope_name := get_basic_block_name(scope_number^)
|
||||||
|
basic_block := LLVMAppendBasicBlockInContext(ctx, function, scope_name)
|
||||||
|
llvm_scope_enter(scope_name, basic_block)
|
||||||
|
LLVMPositionBuilderAtEnd(builder, basic_block)
|
||||||
|
scope_number^ += 1
|
||||||
|
for node in scope.children {
|
||||||
|
#partial switch node.kind {
|
||||||
|
case .Function:
|
||||||
|
panic("FIXME: Implement function delarations")
|
||||||
|
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().types[get_character_sum_of_dyn_arr(&node.value.([dynamic]u8))] = type
|
||||||
|
case .FunctionCall:
|
||||||
|
// FIXME: Add support for dot access
|
||||||
|
name := &node.children[0].value.([dynamic]u8)
|
||||||
|
fn_type := llvm_scope_find_type(name)
|
||||||
|
fn_value := llvm_scope_find_definition(name)
|
||||||
|
if fn_type == nil || fn_value == nil {
|
||||||
|
append(
|
||||||
|
&g_message_list,
|
||||||
|
message_create(
|
||||||
|
.Error,
|
||||||
|
fmt.aprintf("Function '%s' not found", name),
|
||||||
|
node.range,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fn_args := [dynamic]LLVMValueRef{}
|
||||||
|
for &arg in node.children[1:] {
|
||||||
|
value := generate_llvm_value(ctx, mod, builder, arg)
|
||||||
|
append(&fn_args, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMBuildCall2(builder, fn_type, fn_value, raw_data(fn_args[:]), len(fn_args), cstring(raw_data(name[:])))
|
||||||
|
case:
|
||||||
|
panic("FIXME: Implement other node kinds")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
llvm_scope_leave()
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_llvm_scope(ctx, mod, builder, main_function, node, &scope_number)
|
||||||
|
//basic_block := LLVMAppendBasicBlockInContext(ctx, main_function, "end")
|
||||||
|
//LLVMPositionBuilderAtEnd(builder, basic_block)
|
||||||
|
LLVMBuildRet(builder, LLVMConstInt(int_32_type, 0, LLVMBool(1)))
|
||||||
|
}
|
@ -4,43 +4,6 @@ import "core:fmt"
|
|||||||
import "core:os"
|
import "core:os"
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
// ctx := LLVMContextCreate()
|
|
||||||
// defer LLVMContextDispose(ctx)
|
|
||||||
// module := LLVMModuleCreateWithNameInContext("hello", ctx)
|
|
||||||
// defer LLVMDisposeModule(module)
|
|
||||||
// builder := LLVMCreateBuilderInContext(ctx)
|
|
||||||
|
|
||||||
// int_8_type := LLVMInt8TypeInContext(ctx)
|
|
||||||
// int_8_type_ptr := LLVMPointerType(int_8_type, 0)
|
|
||||||
// int_32_type := LLVMInt32TypeInContext(ctx)
|
|
||||||
|
|
||||||
// puts_function_args_type := []LLVMTypeRef{
|
|
||||||
// int_8_type_ptr,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// puts_function_type := LLVMFunctionType(int_32_type, raw_data(puts_function_args_type), 1, LLVMBool(0))
|
|
||||||
// puts_function := LLVMAddFunction(module, "puts", puts_function_type)
|
|
||||||
|
|
||||||
// main_function_type := LLVMFunctionType(int_32_type, nil, 0, LLVMBool(0))
|
|
||||||
// main_function := LLVMAddFunction(module, "main", main_function_type)
|
|
||||||
|
|
||||||
// entry := LLVMAppendBasicBlockInContext(ctx, main_function, "entry")
|
|
||||||
// LLVMPositionBuilderAtEnd(builder, entry)
|
|
||||||
|
|
||||||
// puts_function_args := []LLVMValueRef {
|
|
||||||
// LLVMBuildPointerCast(
|
|
||||||
// builder,
|
|
||||||
// LLVMBuildGlobalString(builder, "Hello world!\n", "hello"),
|
|
||||||
// int_8_type_ptr,
|
|
||||||
// "0",
|
|
||||||
// ),
|
|
||||||
// }
|
|
||||||
|
|
||||||
// LLVMBuildCall2(builder, puts_function_type, puts_function, raw_data(puts_function_args), len(puts_function_args), "i")
|
|
||||||
// LLVMBuildRet(builder, LLVMConstInt(int_32_type, 0, LLVMBool(0)))
|
|
||||||
|
|
||||||
// LLVMPrintModuleToFile(module, "hello.ll", nil)
|
|
||||||
|
|
||||||
handle: os.Handle
|
handle: os.Handle
|
||||||
if len(os.args) >= 2 {
|
if len(os.args) >= 2 {
|
||||||
errno: os.Errno
|
errno: os.Errno
|
||||||
|
Loading…
x
Reference in New Issue
Block a user