diff --git a/examples/llvm-demo/demo.odin b/examples/llvm-demo/demo.odin index e3727e610..3b8953134 100644 --- a/examples/llvm-demo/demo.odin +++ b/examples/llvm-demo/demo.odin @@ -2,29 +2,44 @@ package demo import "core:os" +// Foo :: struct { +// x, y: int, +// }; +// foo :: proc(x: int) -> (f: Foo) { +// return; +// } + main :: proc() { - Foo :: struct { - x, y: int, - }; + Foo :: enum {A=1, B, C, D}; + Foo_Set :: bit_set[Foo]; + x := Foo_Set{.A, .C}; - x := i32(1); - y := i32(2); - z := x + y; - w := z - 2; + y := [4]int{3 = 1, 0 .. 1 = 3, 2 = 9}; + z := []int{1, 2, 3, 4}; + + // @thread_local a: int; + + // x := i32(1); + // y := i32(2); + // z := x + y; + // w := z - 2; + + // foo(123); - c := 1 + 2i; - q := 1 + 2i + 3j + 4k; + // c := 1 + 2i; + // q := 1 + 2i + 3j + 4k; - s := "Hellope"; + // s := "Hellope"; - f: Foo; - pc: proc "contextless" (x: i32) -> Foo; - po: proc "odin" (x: i32) -> Foo; - e: enum{A, B, C}; - u: union{i32, bool}; - u1: union{i32}; - um: union #maybe {^int}; + // f := Foo{1, 2}; + // pc: proc "contextless" (x: i32) -> Foo; + // po: proc "odin" (x: i32) -> Foo; + // e: enum{A, B, C}; + // u: union{i32, bool}; + // u1: union{i32}; + // um: union #maybe {^int}; // os.write_string(os.stdout, "Hellope\n"); + return; } diff --git a/src/ir.cpp b/src/ir.cpp index 2f4d491e7..8171d774d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5911,34 +5911,6 @@ irValue *ir_type_info(irProcedure *proc, Type *type) { return ir_emit_array_ep(proc, ir_global_type_info_data, ir_const_i32(id)); } -// IMPORTANT NOTE(bill): This must match the same as the in core.odin -enum Typeid_Kind : u8 { - Typeid_Invalid, - Typeid_Integer, - Typeid_Rune, - Typeid_Float, - Typeid_Complex, - Typeid_Quaternion, - Typeid_String, - Typeid_Boolean, - Typeid_Any, - Typeid_Type_Id, - Typeid_Pointer, - Typeid_Procedure, - Typeid_Array, - Typeid_Enumerated_Array, - Typeid_Dynamic_Array, - Typeid_Slice, - Typeid_Tuple, - Typeid_Struct, - Typeid_Union, - Typeid_Enum, - Typeid_Map, - Typeid_Bit_Field, - Typeid_Bit_Set, -}; - - irValue *ir_typeid(irModule *m, Type *type) { type = default_type(type); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index a3f28c59f..ac4d2469a 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1014,8 +1014,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * } else if (is_type_enumerated_array(type)) { ast_node(cl, CompoundLit, value.value_compound); - Type *index_type = type->EnumeratedArray.elem; - Type *elem_type = type->Array.elem; + Type *elem_type = type->EnumeratedArray.elem; isize elem_count = cl->elems.count; if (elem_count == 0) { ir_write_str_lit(f, "zeroinitializer"); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index fd6d7a983..c818051d0 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1,109 +1,6 @@ -#include "llvm-c/Core.h" -#include "llvm-c/ExecutionEngine.h" -#include "llvm-c/Target.h" -#include "llvm-c/Analysis.h" -#include "llvm-c/Object.h" -#include "llvm-c/BitWriter.h" -#include "llvm-c/Transforms/AggressiveInstCombine.h" -#include "llvm-c/Transforms/InstCombine.h" -#include "llvm-c/Transforms/IPO.h" +#include "llvm_backend.hpp" -struct lbValue { - LLVMValueRef value; - Type *type; -}; - -struct lbModule { - LLVMModuleRef mod; - - Map values; // Key: Entity * -}; - -struct lbGenerator { - lbModule module; - CheckerInfo *info; - - gbFile output_file; - String output_base; - String output_name; -}; - -enum lbAddrKind { - lbAddr_Default, - lbAddr_Map, - lbAddr_BitField, - lbAddr_Context, - lbAddr_SoaVariable, -}; - - - -struct lbAddr { - lbAddrKind kind; - lbValue addr; - union { - struct { - lbValue key; - Type *type; - Type *result; - } map; - struct { - i32 value_index; - } bit_field; - struct { - Selection sel; - } ctx; - struct { - lbValue index; - Ast *index_expr; - } soa; - }; -}; - -struct lbBlock { - LLVMBasicBlockRef block; - Scope *scope; - isize scope_index; -}; - -struct lbProcedure { - lbProcedure *parent; - Array children; - - Entity * entity; - lbModule * module; - String name; - Type * type; - Ast * type_expr; - Ast * body; - u64 tags; - ProcInlining inlining; - bool is_foreign; - bool is_export; - bool is_entry_point; - - - LLVMValueRef value; - LLVMBuilderRef builder; - - lbValue return_ptr; - Array params; - Array blocks; - Scope * curr_scope; - i32 scope_index; - lbBlock * decl_block; - lbBlock * entry_block; - lbBlock * curr_block; -}; - -lbBlock * lb_create_block(lbProcedure *p, char const *name); -LLVMTypeRef lb_type(Type *type); -void lb_build_stmt (lbProcedure *p, Ast *stmt); -lbValue lb_build_expr (lbProcedure *p, Ast *expr); -lbValue lb_constant_nil(Type *type); - - -gb_internal lbModule *global_module = nullptr; +gb_internal gb_thread_local lbModule *global_module = nullptr; gb_internal LLVMValueRef lb_zero32 = nullptr; gb_internal LLVMValueRef lb_one32 = nullptr; @@ -129,6 +26,20 @@ void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue const &value) { LLVMBuildStore(p->builder, value.value, addr.addr.value); } + +lbValue lb_emit_load(lbProcedure *p, lbValue value) { + GB_ASSERT(value.value != nullptr); + Type *t = type_deref(value.type); + LLVMValueRef v = LLVMBuildLoad2(p->builder, lb_type(t), value.value, ""); + return lbValue{v, t}; +} + +lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) { + GB_ASSERT(addr.addr.value != nullptr); + return lb_emit_load(p, addr.addr); +} + + void lb_clone_struct_type(LLVMTypeRef dst, LLVMTypeRef src) { unsigned field_count = LLVMCountStructElementTypes(src); LLVMTypeRef *fields = gb_alloc_array(heap_allocator(), LLVMTypeRef, field_count); @@ -156,6 +67,60 @@ LLVMTypeRef lb_alignment_prefix_type_hack(i64 alignment) { return nullptr; } +String lb_mangle_name(lbModule *m, Entity *e) { + gbAllocator a = heap_allocator(); + + String name = e->token.string; + + AstPackage *pkg = e->pkg; + GB_ASSERT_MSG(pkg != nullptr, "Missing package for '%.*s'", LIT(name)); + String pkgn = pkg->name; + GB_ASSERT(!rune_is_digit(pkgn[0])); + + + isize max_len = pkgn.len + 1 + name.len + 1; + bool require_suffix_id = is_type_polymorphic(e->type, true); + if (require_suffix_id) { + max_len += 21; + } + + u8 *new_name = gb_alloc_array(a, u8, max_len); + isize new_name_len = gb_snprintf( + cast(char *)new_name, max_len, + "%.*s.%.*s", LIT(pkgn), LIT(name) + ); + if (require_suffix_id) { + char *str = cast(char *)new_name + new_name_len-1; + isize len = max_len-new_name_len; + isize extra = gb_snprintf(str, len, "-%llu", cast(unsigned long long)e->id); + new_name_len += extra-1; + } + + return make_string(new_name, new_name_len-1); +} + +String lb_get_entity_name(lbModule *m, Entity *e, String name) { + if (e != nullptr && e->kind == Entity_TypeName && e->TypeName.ir_mangled_name.len != 0) { + return e->TypeName.ir_mangled_name; + } + + + bool no_name_mangle = false; + + if (!no_name_mangle) { + name = lb_mangle_name(m, e); + } + if (name.len == 0) { + name = e->token.string; + } + + if (e != nullptr && e->kind == Entity_TypeName) { + e->TypeName.ir_mangled_name = name; + + } + return name; +} + LLVMTypeRef lb_type_internal(Type *type) { i64 size = type_size_of(type); // Check size @@ -333,7 +298,7 @@ LLVMTypeRef lb_type_internal(Type *type) { if (base->llvm_type != nullptr) { LLVMTypeKind kind = LLVMGetTypeKind(base->llvm_type); if (kind == LLVMStructTypeKind) { - type->llvm_type = LLVMStructCreateNamed(ctx, alloc_cstring(heap_allocator(), type->Named.name)); + type->llvm_type = LLVMStructCreateNamed(ctx, alloc_cstring(heap_allocator(), lb_get_entity_name(global_module, type->Named.type_name))); lb_clone_struct_type(type->llvm_type, base->llvm_type); } } @@ -342,7 +307,7 @@ LLVMTypeRef lb_type_internal(Type *type) { case Type_Struct: case Type_Union: case Type_BitField: - type->llvm_type = LLVMStructCreateNamed(ctx, alloc_cstring(heap_allocator(), type->Named.name)); + type->llvm_type = LLVMStructCreateNamed(ctx, alloc_cstring(heap_allocator(), lb_get_entity_name(global_module, type->Named.type_name))); lb_clone_struct_type(type->llvm_type, lb_type(base)); return type->llvm_type; } @@ -407,6 +372,7 @@ LLVMTypeRef lb_type_internal(Type *type) { unsigned field_count = cast(unsigned)(type->Struct.fields.count + offset); LLVMTypeRef *fields = gb_alloc_array(heap_allocator(), LLVMTypeRef, field_count); + GB_ASSERT(fields != nullptr); defer (gb_free(heap_allocator(), fields)); for_array(i, type->Struct.fields) { @@ -563,12 +529,43 @@ LLVMTypeRef lb_type(Type *type) { return llvm_type; } +void lb_add_entity(lbModule *m, Entity *e, lbValue val) { + if (e != nullptr) { + map_set(&m->values, hash_entity(e), val); + } +} +void lb_add_member(lbModule *m, String const &name, lbValue val) { + if (name.len > 0) { + map_set(&m->members, hash_string(name), val); + } +} +void lb_add_member(lbModule *m, HashKey const &key, lbValue val) { + map_set(&m->members, key, val); +} + + +LLVMAttributeRef lb_create_enum_attribute(LLVMContextRef ctx, char const *name, u64 value) { + unsigned kind = LLVMGetEnumAttributeKindForName(name, gb_strlen(name)); + return LLVMCreateEnumAttribute(ctx, kind, value); +} + +void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *name, u64 value) { + LLVMContextRef ctx = LLVMGetModuleContext(p->module->mod); + LLVMAddAttributeAtIndex(p->value, cast(unsigned)index, lb_create_enum_attribute(ctx, name, value)); +} + +void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *name) { + lb_add_proc_attribute_at_index(p, index, name, true); +} + + + lbProcedure *lb_create_procedure(lbModule *module, Entity *entity) { lbProcedure *p = gb_alloc_item(heap_allocator(), lbProcedure); p->module = module; p->entity = entity; - p->name = entity->token.string; + p->name = lb_get_entity_name(module, entity); DeclInfo *decl = entity->decl_info; @@ -576,6 +573,8 @@ lbProcedure *lb_create_procedure(lbModule *module, Entity *entity) { Type *pt = base_type(entity->type); GB_ASSERT(pt->kind == Type_Proc); + set_procedure_abi_types(heap_allocator(), entity->type); + p->type = entity->type; p->type_expr = decl->type_expr; p->body = pl->body; @@ -588,30 +587,119 @@ lbProcedure *lb_create_procedure(lbModule *module, Entity *entity) { p->children.allocator = heap_allocator(); p->params.allocator = heap_allocator(); p->blocks.allocator = heap_allocator(); + p->branch_blocks.allocator = heap_allocator(); char *name = alloc_cstring(heap_allocator(), p->name); - LLVMTypeRef ret_type = LLVMFunctionType(LLVMVoidType(), nullptr, 0, false); + LLVMTypeRef func_ptr_type = lb_type(p->type); + LLVMTypeRef func_type = LLVMGetElementType(func_ptr_type); + + p->value = LLVMAddFunction(module->mod, name, func_type); + lb_add_entity(module, entity, lbValue{p->value, p->type}); + lb_add_member(module, p->name, lbValue{p->value, p->type}); + + LLVMContextRef ctx = LLVMGetModuleContext(module->mod); + + // NOTE(bill): offset==0 is the return value + isize offset = 1; + if (pt->Proc.return_by_pointer) { + lb_add_proc_attribute_at_index(p, 1, "sret"); + lb_add_proc_attribute_at_index(p, 1, "noalias"); + offset = 2; + } + + isize parameter_index = 0; + if (pt->Proc.param_count) { + TypeTuple *params = &pt->Proc.params->Tuple; + for (isize i = 0; i < pt->Proc.param_count; i++, parameter_index++) { + Entity *e = params->variables[i]; + Type *original_type = e->type; + Type *abi_type = pt->Proc.abi_compat_params[i]; + if (e->kind != Entity_Variable) continue; + + if (i+1 == params->variables.count && pt->Proc.c_vararg) { + continue; + } + if (is_type_tuple(abi_type)) { + for_array(j, abi_type->Tuple.variables) { + Type *tft = abi_type->Tuple.variables[j]->type; + if (e->flags&EntityFlag_NoAlias) { + lb_add_proc_attribute_at_index(p, offset+parameter_index+j, "noalias"); + } + } + parameter_index += abi_type->Tuple.variables.count-1; + } else { + if (e->flags&EntityFlag_NoAlias) { + lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias"); + } + } + } + } + + if (pt->Proc.calling_convention == ProcCC_Odin) { + lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias"); + lb_add_proc_attribute_at_index(p, offset+parameter_index, "nonnull"); + lb_add_proc_attribute_at_index(p, offset+parameter_index, "nocapture"); + + } + + + return p; +} + +void lb_begin_procedure_body(lbProcedure *p) { + DeclInfo *decl = decl_info_of_entity(p->entity); + if (decl != nullptr) { + for_array(i, decl->labels) { + BlockLabel bl = decl->labels[i]; + lbBranchBlocks bb = {bl.label, nullptr, nullptr}; + array_add(&p->branch_blocks, bb); + } + } - p->value = LLVMAddFunction(module->mod, name, ret_type); p->builder = LLVMCreateBuilder(); p->decl_block = lb_create_block(p, "decls"); p->entry_block = lb_create_block(p, "entry"); p->curr_block = p->entry_block; - set_procedure_abi_types(heap_allocator(), p->type); - LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block); - return p; + GB_ASSERT(p->type != nullptr); + + if (p->type->Proc.return_by_pointer) { + // NOTE(bill): this must be parameter 0 + Type *ptr_type = alloc_type_pointer(reduce_tuple_to_single_type(p->type->Proc.results)); + Entity *e = alloc_entity_param(nullptr, make_token_ident(str_lit("agg.result")), ptr_type, false, false); + e->flags |= EntityFlag_Sret | EntityFlag_NoAlias; + + lbValue return_ptr_value = {}; + return_ptr_value.value = LLVMGetParam(p->value, 0); + return_ptr_value.type = alloc_type_pointer(p->type->Proc.abi_compat_result_type); + p->return_ptr = lb_addr(return_ptr_value); + + lb_add_entity(p->module, e, return_ptr_value); + } + + } -void lb_end_procedure(lbProcedure *p) { +void lb_end_procedure_body(lbProcedure *p) { LLVMPositionBuilderAtEnd(p->builder, p->decl_block->block); LLVMBuildBr(p->builder, p->entry_block->block); LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block); + if (p->type->Proc.result_count == 0) { + LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block); + if (!LLVMIsAReturnInst(instr)) { + LLVMBuildRetVoid(p->builder); + } + } + + p->curr_block = nullptr; + +} +void lb_end_procedure(lbProcedure *p) { LLVMDisposeBuilder(p->builder); } @@ -638,9 +726,7 @@ lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e=nullptr) { val.value = ptr; val.type = alloc_type_pointer(type); - if (e != nullptr) { - map_set(&p->module->values, hash_entity(e), val); - } + lb_add_entity(p->module, e, val); return lb_addr(val); } @@ -686,9 +772,13 @@ bool lb_init_generator(lbGenerator *gen, Checker *c) { } gen->info = &c->info; + gen->module.info = &c->info; gen->module.mod = LLVMModuleCreateWithName("odin_module"); map_init(&gen->module.values, heap_allocator()); + map_init(&gen->module.members, heap_allocator()); + map_init(&gen->module.const_strings, heap_allocator()); + map_init(&gen->module.const_string_byte_slices, heap_allocator()); global_module = &gen->module; @@ -726,6 +816,26 @@ lbValue lb_build_gep(lbProcedure *p, lbValue const &value, i32 index) { return lbValue{LLVMBuildStructGEP2(p->builder, lb_type(elem_type), value.value, index, ""), elem_type}; } +void lb_build_when_stmt(lbProcedure *p, AstWhenStmt *ws) { + TypeAndValue tv = type_and_value_of_expr(ws->cond); + GB_ASSERT(is_type_boolean(tv.type)); + GB_ASSERT(tv.value.kind == ExactValue_Bool); + if (tv.value.value_bool) { + lb_build_stmt_list(p, ws->body->BlockStmt.stmts); + } else if (ws->else_stmt) { + switch (ws->else_stmt->kind) { + case Ast_BlockStmt: + lb_build_stmt_list(p, ws->else_stmt->BlockStmt.stmts); + break; + case Ast_WhenStmt: + lb_build_when_stmt(p, &ws->else_stmt->WhenStmt); + break; + default: + GB_PANIC("Invalid 'else' statement in 'when' statement"); + break; + } + } +} void lb_build_stmt(lbProcedure *p, Ast *node) { switch (node->kind) { @@ -735,6 +845,11 @@ void lb_build_stmt(lbProcedure *p, Ast *node) { case_ast_node(us, UsingStmt, node); case_end; + case_ast_node(ws, WhenStmt, node); + lb_build_when_stmt(p, ws); + case_end; + + case_ast_node(bs, BlockStmt, node); lb_build_stmt_list(p, bs->stmts); case_end; @@ -753,7 +868,69 @@ void lb_build_stmt(lbProcedure *p, Ast *node) { } } - GB_ASSERT_MSG(!is_static, "handle static variables"); + if (is_static) { + for_array(i, vd->names) { + lbValue value = {}; + if (vd->values.count > 0) { + GB_ASSERT(vd->names.count == vd->values.count); + Ast *ast_value = vd->values[i]; + GB_ASSERT(ast_value->tav.mode == Addressing_Constant || + ast_value->tav.mode == Addressing_Invalid); + + value = lb_const_value(p->module, ast_value->tav.type, ast_value->tav.value); + } + + Ast *ident = vd->names[i]; + GB_ASSERT(!is_blank_ident(ident)); + Entity *e = entity_of_ident(ident); + GB_ASSERT(e->flags & EntityFlag_Static); + String name = e->token.string; + + String mangled_name = {}; + { + gbString str = gb_string_make_length(heap_allocator(), p->name.text, p->name.len); + str = gb_string_appendc(str, "-"); + str = gb_string_append_fmt(str, ".%.*s-%llu", LIT(name), cast(long long)e->id); + mangled_name.text = cast(u8 *)str; + mangled_name.len = gb_string_length(str); + } + + char *c_name = alloc_cstring(heap_allocator(), mangled_name); + + LLVMValueRef global = LLVMAddGlobal(p->module->mod, lb_type(e->type), c_name); + if (value.value != nullptr) { + LLVMSetInitializer(global, value.value); + } + if (e->Variable.thread_local_model != "") { + LLVMSetThreadLocal(global, true); + + String m = e->Variable.thread_local_model; + LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel; + if (m == "default") { + mode = LLVMGeneralDynamicTLSModel; + } else if (m == "localdynamic") { + mode = LLVMLocalDynamicTLSModel; + } else if (m == "initialexec") { + mode = LLVMInitialExecTLSModel; + } else if (m == "localexec") { + mode = LLVMLocalExecTLSModel; + } else { + GB_PANIC("Unhandled thread local mode %.*s", LIT(m)); + } + LLVMSetThreadLocalMode(global, mode); + } else { + LLVMSetLinkage(global, LLVMInternalLinkage); + } + + + lbValue global_val = {global, alloc_type_pointer(e->type)}; + lb_add_entity(p->module, e, global_val); + lb_add_member(p->module, mangled_name, global_val); + } + return; + } + + auto addrs = array_make(heap_allocator(), vd->names.count); @@ -765,9 +942,10 @@ void lb_build_stmt(lbProcedure *p, Ast *node) { Ast *name = vd->names[i]; if (!is_blank_ident(name)) { Entity *e = entity_of_ident(name); - addrs[i] = lb_add_local(p, e->type, e); + lbAddr local = lb_add_local(p, e->type, e); + addrs[i] = local; if (vd->values.count == 0) { - lb_addr_store(p, addrs[i], lb_constant_nil(lb_addr_type(addrs[i]))); + lb_addr_store(p, addrs[i], lb_const_nil(lb_addr_type(addrs[i]))); } } } @@ -785,12 +963,80 @@ void lb_build_stmt(lbProcedure *p, Ast *node) { for_array(i, values) { lb_addr_store(p, addrs[i], values[i]); } + case_end; + case_ast_node(as, AssignStmt, node); + case_end; + + case_ast_node(es, ExprStmt, node); + lb_build_expr(p, es->expr); + case_end; + + case_ast_node(ds, DeferStmt, node); + case_end; + + case_ast_node(rs, ReturnStmt, node); + lbValue res = {}; + + TypeTuple *tuple = &p->type->Proc.results->Tuple; + isize return_count = p->type->Proc.result_count; + isize res_count = rs->results.count; + + if (return_count == 0) { + // No return values + LLVMBuildRetVoid(p->builder); + return; + } else if (return_count == 1) { + Entity *e = tuple->variables[0]; + if (res_count == 0) { + // lbValue *found = map_get(&p->module->values, hash_entity(e)); + // GB_ASSERT(found); + // res = lb_emit_load(p, *found); + } else { + res = lb_build_expr(p, rs->results[0]); + // res = ir_emit_conv(p, v, e->type); + } + } else { + + } + + if (p->type->Proc.return_by_pointer) { + if (res.value != nullptr) { + lb_addr_store(p, p->return_ptr, res); + } else { + lb_addr_store(p, p->return_ptr, lb_const_nil(p->type->Proc.abi_compat_result_type)); + } + LLVMBuildRetVoid(p->builder); + } else { + GB_ASSERT_MSG(res.value != nullptr, "%.*s", LIT(p->name)); + LLVMBuildRet(p->builder, res.value); + } + case_end; + + case_ast_node(is, IfStmt, node); + case_end; + + case_ast_node(fs, ForStmt, node); + case_end; + + case_ast_node(rs, RangeStmt, node); + case_end; + + case_ast_node(rs, InlineRangeStmt, node); + case_end; + + case_ast_node(ss, SwitchStmt, node); + case_end; + + case_ast_node(ss, TypeSwitchStmt, node); + case_end; + + case_ast_node(bs, BranchStmt, node); case_end; } } -lbValue lb_constant_nil(Type *type) { +lbValue lb_const_nil(Type *type) { LLVMValueRef v = LLVMConstNull(lb_type(type)); return lbValue{v, type}; } @@ -801,19 +1047,212 @@ LLVMValueRef llvm_const_f32(f32 f, Type *type=t_f32) { return LLVMConstBitCast(i, lb_type(type)); } -lbValue lb_constant_value(lbModule *m, Type *type, ExactValue const &value) { + +lbValue lb_find_or_add_entity_string(lbModule *m, String const &str) { + HashKey key = hash_string(str); + lbValue *found = map_get(&m->const_strings, key); + if (found != nullptr) { + return *found; + } + lbValue v = lb_const_value(m, t_string, exact_value_string(str)); + map_set(&m->const_strings, key, v); + return v; +} + +lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str) { + HashKey key = hash_string(str); + lbValue *found = map_get(&m->const_string_byte_slices, key); + if (found != nullptr) { + return *found; + } + Type *t = t_u8_slice; + lbValue v = lb_const_value(m, t, exact_value_string(str)); + map_set(&m->const_string_byte_slices, key, v); + return v; +} + +isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=true) { + isize index = type_info_index(info, type, false); + if (index >= 0) { + auto *set = &info->minimum_dependency_type_info_set; + for_array(i, set->entries) { + if (set->entries[i].ptr == index) { + return i+1; + } + } + } + if (err_on_not_found) { + GB_PANIC("NOT FOUND ir_type_info_index %s @ index %td", type_to_string(type), index); + } + return -1; +} + +lbValue lb_typeid(lbModule *m, Type *type, Type *typeid_type=t_typeid) { + type = default_type(type); + + u64 id = cast(u64)lb_type_info_index(m->info, type); + GB_ASSERT(id >= 0); + + u64 kind = Typeid_Invalid; + u64 named = is_type_named(type) && type->kind != Type_Basic; + u64 special = 0; + u64 reserved = 0; + + Type *bt = base_type(type); + TypeKind tk = bt->kind; + switch (tk) { + case Type_Basic: { + u32 flags = bt->Basic.flags; + if (flags & BasicFlag_Boolean) kind = Typeid_Boolean; + if (flags & BasicFlag_Integer) kind = Typeid_Integer; + if (flags & BasicFlag_Unsigned) kind = Typeid_Integer; + if (flags & BasicFlag_Float) kind = Typeid_Float; + if (flags & BasicFlag_Complex) kind = Typeid_Complex; + if (flags & BasicFlag_Pointer) kind = Typeid_Pointer; + if (flags & BasicFlag_String) kind = Typeid_String; + if (flags & BasicFlag_Rune) kind = Typeid_Rune; + } break; + case Type_Pointer: kind = Typeid_Pointer; break; + case Type_Array: kind = Typeid_Array; break; + case Type_EnumeratedArray: kind = Typeid_Enumerated_Array; break; + case Type_Slice: kind = Typeid_Slice; break; + case Type_DynamicArray: kind = Typeid_Dynamic_Array; break; + case Type_Map: kind = Typeid_Map; break; + case Type_Struct: kind = Typeid_Struct; break; + case Type_Enum: kind = Typeid_Enum; break; + case Type_Union: kind = Typeid_Union; break; + case Type_Tuple: kind = Typeid_Tuple; break; + case Type_Proc: kind = Typeid_Procedure; break; + case Type_BitField: kind = Typeid_Bit_Field; break; + case Type_BitSet: kind = Typeid_Bit_Set; break; + } + + if (is_type_cstring(type)) { + special = 1; + } else if (is_type_integer(type) && !is_type_unsigned(type)) { + special = 1; + } + + u64 data = 0; + if (build_context.word_size == 4) { + data |= (id &~ (1u<<24)) << 0u; // index + data |= (kind &~ (1u<<5)) << 24u; // kind + data |= (named &~ (1u<<1)) << 29u; // kind + data |= (special &~ (1u<<1)) << 30u; // kind + data |= (reserved &~ (1u<<1)) << 31u; // kind + } else { + GB_ASSERT(build_context.word_size == 8); + data |= (id &~ (1ull<<56)) << 0ul; // index + data |= (kind &~ (1ull<<5)) << 56ull; // kind + data |= (named &~ (1ull<<1)) << 61ull; // kind + data |= (special &~ (1ull<<1)) << 62ull; // kind + data |= (reserved &~ (1ull<<1)) << 63ull; // kind + } + + + lbValue res = {}; + res.value = LLVMConstInt(lb_type(typeid_type), data, false); + res.type = typeid_type; + return res; +} + +lbValue lb_const_value(lbModule *m, Type *type, ExactValue value) { + Type *original_type = type; + lbValue res = {}; res.type = type; + type = core_type(type); + value = convert_exact_value_for_type(value, type); + + if (is_type_slice(type)) { + if (value.kind == ExactValue_String) { + GB_ASSERT(is_type_u8_slice(type)); + res.value = lb_find_or_add_entity_string_byte_slice(m, value.value_string).value; + return res; + } else { + ast_node(cl, CompoundLit, value.value_compound); + + isize count = cl->elems.count; + if (count == 0) { + return lb_const_nil(type); + } + count = gb_max(cl->max_count, count); + Type *elem = base_type(type)->Slice.elem; + Type *t = alloc_type_array(elem, count); + lbValue backing_array = lb_const_value(m, t, value); + + + isize max_len = 7+8+1; + u8 *str = cast(u8 *)gb_alloc_array(heap_allocator(), u8, max_len); + isize len = gb_snprintf(cast(char *)str, max_len, "csba$%x", m->global_array_index); + m->global_array_index++; + + String name = make_string(str, len-1); + + Entity *e = alloc_entity_constant(nullptr, make_token_ident(name), t, value); + LLVMValueRef global_data = LLVMAddGlobal(m->mod, lb_type(t), cast(char const *)str); + LLVMSetInitializer(global_data, backing_array.value); + + lbValue g = {}; + g.value = global_data; + g.type = t; + + lb_add_entity(m, e, g); + lb_add_member(m, name, g); + + { + LLVMValueRef indices[2] = {lb_zero32, lb_zero32}; + LLVMValueRef ptr = LLVMConstInBoundsGEP(global_data, indices, 2); + LLVMValueRef len = LLVMConstInt(lb_type(t_int), count, true); + LLVMValueRef values[2] = {ptr, len}; + + res.value = LLVMConstNamedStruct(lb_type(original_type), values, 2); + return res; + } + + } + } else if (is_type_array(type) && value.kind == ExactValue_String && !is_type_u8(core_array_type(type))) { + LLVMValueRef data = LLVMConstString(cast(char const *)value.value_string.text, + cast(unsigned)value.value_string.len, + false); + res.value = data; + return res; + } else if (is_type_array(type) && + value.kind != ExactValue_Invalid && + value.kind != ExactValue_String && + value.kind != ExactValue_Compound) { + + i64 count = type->Array.count; + Type *elem = type->Array.elem; + + + lbValue single_elem = lb_const_value(m, elem, value); + + LLVMValueRef *elems = gb_alloc_array(heap_allocator(), LLVMValueRef, count); + for (i64 i = 0; i < count; i++) { + elems[i] = single_elem.value; + } + + res.value = LLVMConstArray(lb_type(elem), elems, cast(unsigned)count); + return res; + } switch (value.kind) { case ExactValue_Invalid: - res.value = LLVMConstNull(lb_type(type)); + res.value = LLVMConstNull(lb_type(original_type)); return res; case ExactValue_Bool: - res.value = LLVMConstInt(lb_type(type), value.value_bool, false); + res.value = LLVMConstInt(lb_type(original_type), value.value_bool, false); return res; case ExactValue_String: { + HashKey key = hash_string(value.value_string); + lbValue *found = map_get(&m->const_strings, key); + if (found != nullptr) { + res.value = found->value; + return res; + } + LLVMValueRef indices[2] = {lb_zero32, lb_zero32}; LLVMValueRef data = LLVMConstString(cast(char const *)value.value_string.text, cast(unsigned)value.value_string.len, @@ -831,12 +1270,20 @@ lbValue lb_constant_value(lbModule *m, Type *type, ExactValue const &value) { LLVMValueRef len = LLVMConstInt(lb_type(t_int), value.value_string.len, true); LLVMValueRef values[2] = {ptr, len}; - res.value = LLVMConstNamedStruct(lb_type(type), values, 2); + res.value = LLVMConstNamedStruct(lb_type(original_type), values, 2); + + map_set(&m->const_strings, key, res); + return res; } case ExactValue_Integer: - res.value = LLVMConstIntOfArbitraryPrecision(lb_type(type), cast(unsigned)value.value_integer.len, big_int_ptr(&value.value_integer)); + if (is_type_pointer(type)) { + LLVMValueRef i = LLVMConstIntOfArbitraryPrecision(lb_type(t_uintptr), cast(unsigned)value.value_integer.len, big_int_ptr(&value.value_integer)); + res.value = LLVMConstBitCast(i, lb_type(original_type)); + } else { + res.value = LLVMConstIntOfArbitraryPrecision(lb_type(original_type), cast(unsigned)value.value_integer.len, big_int_ptr(&value.value_integer)); + } return res; case ExactValue_Float: if (type_size_of(type) == 4) { @@ -844,7 +1291,7 @@ lbValue lb_constant_value(lbModule *m, Type *type, ExactValue const &value) { res.value = llvm_const_f32(f, type); return res; } - res.value = LLVMConstReal(lb_type(type), value.value_float); + res.value = LLVMConstReal(lb_type(original_type), value.value_float); return res; case ExactValue_Complex: { @@ -860,7 +1307,7 @@ lbValue lb_constant_value(lbModule *m, Type *type, ExactValue const &value) { break; } - res.value = LLVMConstNamedStruct(lb_type(type), values, 2); + res.value = LLVMConstNamedStruct(lb_type(original_type), values, 2); return res; } break; @@ -884,38 +1331,335 @@ lbValue lb_constant_value(lbModule *m, Type *type, ExactValue const &value) { break; } - res.value = LLVMConstNamedStruct(lb_type(type), values, 4); + res.value = LLVMConstNamedStruct(lb_type(original_type), values, 4); return res; } break; case ExactValue_Pointer: - res.value = LLVMConstBitCast(LLVMConstInt(lb_type(t_uintptr), value.value_pointer, false), lb_type(type)); + res.value = LLVMConstBitCast(LLVMConstInt(lb_type(t_uintptr), value.value_pointer, false), lb_type(original_type)); return res; case ExactValue_Compound: - GB_PANIC("ExactValue_Compound"); + if (is_type_slice(type)) { + return lb_const_value(m, type, value); + } else if (is_type_array(type)) { + ast_node(cl, CompoundLit, value.value_compound); + Type *elem_type = type->Array.elem; + isize elem_count = cl->elems.count; + if (elem_count == 0) { + return lb_const_nil(original_type); + } + if (cl->elems[0]->kind == Ast_FieldValue) { + // TODO(bill): This is O(N*M) and will be quite slow; it should probably be sorted before hand + + LLVMValueRef *values = gb_alloc_array(heap_allocator(), LLVMValueRef, type->Array.count); + defer (gb_free(heap_allocator(), values)); + + isize value_index = 0; + for (i64 i = 0; i < type->Array.count; i++) { + bool found = false; + + for (isize j = 0; j < elem_count; j++) { + Ast *elem = cl->elems[j]; + ast_node(fv, FieldValue, elem); + if (is_ast_range(fv->field)) { + ast_node(ie, BinaryExpr, fv->field); + TypeAndValue lo_tav = ie->left->tav; + TypeAndValue hi_tav = ie->right->tav; + GB_ASSERT(lo_tav.mode == Addressing_Constant); + GB_ASSERT(hi_tav.mode == Addressing_Constant); + + TokenKind op = ie->op.kind; + i64 lo = exact_value_to_i64(lo_tav.value); + i64 hi = exact_value_to_i64(hi_tav.value); + if (op == Token_Ellipsis) { + hi += 1; + } + if (lo == i) { + TypeAndValue tav = fv->value->tav; + if (tav.mode != Addressing_Constant) { + break; + } + LLVMValueRef val = lb_const_value(m, elem_type, tav.value).value; + for (i64 k = lo; k < hi; k++) { + values[value_index++] = val; + } + + found = true; + i += (hi-lo-1); + break; + } + } else { + TypeAndValue index_tav = fv->field->tav; + GB_ASSERT(index_tav.mode == Addressing_Constant); + i64 index = exact_value_to_i64(index_tav.value); + if (index == i) { + TypeAndValue tav = fv->value->tav; + if (tav.mode != Addressing_Constant) { + break; + } + LLVMValueRef val = lb_const_value(m, elem_type, tav.value).value; + values[value_index++] = val; + found = true; + break; + } + } + } + + if (!found) { + values[value_index++] = LLVMConstNull(lb_type(elem_type)); + } + } + + res.value = LLVMConstArray(lb_type(elem_type), values, cast(unsigned int)type->Array.count); + return res; + } else { + GB_ASSERT_MSG(elem_count == type->Array.count, "%td != %td", elem_count, type->Array.count); + + LLVMValueRef *values = gb_alloc_array(heap_allocator(), LLVMValueRef, type->Array.count); + defer (gb_free(heap_allocator(), values)); + + for (isize i = 0; i < elem_count; i++) { + TypeAndValue tav = cl->elems[i]->tav; + GB_ASSERT(tav.mode != Addressing_Invalid); + values[i] = lb_const_value(m, elem_type, tav.value).value; + } + for (isize i = elem_count; i < type->Array.count; i++) { + values[i] = LLVMConstNull(lb_type(elem_type)); + } + + res.value = LLVMConstArray(lb_type(elem_type), values, cast(unsigned int)type->Array.count); + return res; + } + } else if (is_type_enumerated_array(type)) { + ast_node(cl, CompoundLit, value.value_compound); + Type *elem_type = type->EnumeratedArray.elem; + isize elem_count = cl->elems.count; + if (elem_count == 0) { + return lb_const_nil(original_type); + } + if (cl->elems[0]->kind == Ast_FieldValue) { + // TODO(bill): This is O(N*M) and will be quite slow; it should probably be sorted before hand + + LLVMValueRef *values = gb_alloc_array(heap_allocator(), LLVMValueRef, type->EnumeratedArray.count); + defer (gb_free(heap_allocator(), values)); + + isize value_index = 0; + + i64 total_lo = exact_value_to_i64(type->EnumeratedArray.min_value); + i64 total_hi = exact_value_to_i64(type->EnumeratedArray.max_value); + + for (i64 i = total_lo; i <= total_hi; i++) { + bool found = false; + + for (isize j = 0; j < elem_count; j++) { + Ast *elem = cl->elems[j]; + ast_node(fv, FieldValue, elem); + if (is_ast_range(fv->field)) { + ast_node(ie, BinaryExpr, fv->field); + TypeAndValue lo_tav = ie->left->tav; + TypeAndValue hi_tav = ie->right->tav; + GB_ASSERT(lo_tav.mode == Addressing_Constant); + GB_ASSERT(hi_tav.mode == Addressing_Constant); + + TokenKind op = ie->op.kind; + i64 lo = exact_value_to_i64(lo_tav.value); + i64 hi = exact_value_to_i64(hi_tav.value); + if (op == Token_Ellipsis) { + hi += 1; + } + if (lo == i) { + TypeAndValue tav = fv->value->tav; + if (tav.mode != Addressing_Constant) { + break; + } + LLVMValueRef val = lb_const_value(m, elem_type, tav.value).value; + for (i64 k = lo; k < hi; k++) { + values[value_index++] = val; + } + + found = true; + i += (hi-lo-1); + break; + } + } else { + TypeAndValue index_tav = fv->field->tav; + GB_ASSERT(index_tav.mode == Addressing_Constant); + i64 index = exact_value_to_i64(index_tav.value); + if (index == i) { + TypeAndValue tav = fv->value->tav; + if (tav.mode != Addressing_Constant) { + break; + } + LLVMValueRef val = lb_const_value(m, elem_type, tav.value).value; + values[value_index++] = val; + found = true; + break; + } + } + } + + if (!found) { + values[value_index++] = LLVMConstNull(lb_type(elem_type)); + } + } + + res.value = LLVMConstArray(lb_type(elem_type), values, cast(unsigned int)type->EnumeratedArray.count); + return res; + } else { + GB_ASSERT_MSG(elem_count == type->EnumeratedArray.count, "%td != %td", elem_count, type->EnumeratedArray.count); + + LLVMValueRef *values = gb_alloc_array(heap_allocator(), LLVMValueRef, type->EnumeratedArray.count); + defer (gb_free(heap_allocator(), values)); + + for (isize i = 0; i < elem_count; i++) { + TypeAndValue tav = cl->elems[i]->tav; + GB_ASSERT(tav.mode != Addressing_Invalid); + values[i] = lb_const_value(m, elem_type, tav.value).value; + } + for (isize i = elem_count; i < type->EnumeratedArray.count; i++) { + values[i] = LLVMConstNull(lb_type(elem_type)); + } + + res.value = LLVMConstArray(lb_type(elem_type), values, cast(unsigned int)type->EnumeratedArray.count); + return res; + } + } else if (is_type_simd_vector(type)) { + ast_node(cl, CompoundLit, value.value_compound); + + Type *elem_type = type->SimdVector.elem; + isize elem_count = cl->elems.count; + if (elem_count == 0) { + return lb_const_nil(original_type); + } + + isize total_elem_count = type->SimdVector.count; + LLVMValueRef *values = gb_alloc_array(heap_allocator(), LLVMValueRef, total_elem_count); + defer (gb_free(heap_allocator(), values)); + + for (isize i = 0; i < elem_count; i++) { + TypeAndValue tav = cl->elems[i]->tav; + GB_ASSERT(tav.mode != Addressing_Invalid); + values[i] = lb_const_value(m, elem_type, tav.value).value; + } + for (isize i = elem_count; i < type->SimdVector.count; i++) { + values[i] = LLVMConstNull(lb_type(elem_type)); + } + + res.value = LLVMConstVector(values, cast(unsigned)total_elem_count); + return res; + } else if (is_type_struct(type)) { + ast_node(cl, CompoundLit, value.value_compound); + + if (cl->elems.count == 0) { + return lb_const_nil(type); + } + + isize offset = 0; + if (type->Struct.custom_align > 0) { + offset = 1; + } + + isize value_count = type->Struct.fields.count + offset; + LLVMValueRef *values = gb_alloc_array(heap_allocator(), LLVMValueRef, value_count); + bool *visited = gb_alloc_array(heap_allocator(), bool, value_count); + defer (gb_free(heap_allocator(), values)); + defer (gb_free(heap_allocator(), visited)); + + + + if (cl->elems.count > 0) { + if (cl->elems[0]->kind == Ast_FieldValue) { + isize elem_count = cl->elems.count; + for (isize i = 0; i < elem_count; i++) { + ast_node(fv, FieldValue, cl->elems[i]); + String name = fv->field->Ident.token.string; + + TypeAndValue tav = fv->value->tav; + GB_ASSERT(tav.mode != Addressing_Invalid); + + Selection sel = lookup_field(type, name, false); + Entity *f = type->Struct.fields[sel.index[0]]; + + values[offset+f->Variable.field_index] = lb_const_value(m, f->type, tav.value).value; + visited[offset+f->Variable.field_index] = true; + } + } else { + for_array(i, cl->elems) { + Entity *f = type->Struct.fields[i]; + TypeAndValue tav = cl->elems[i]->tav; + ExactValue val = {}; + if (tav.mode != Addressing_Invalid) { + val = tav.value; + } + values[offset+f->Variable.field_index] = lb_const_value(m, f->type, val).value; + visited[offset+f->Variable.field_index] = true; + } + } + } + + for (isize i = 0; i < type->Struct.fields.count; i++) { + if (!visited[offset+i]) { + GB_ASSERT(values[offset+i] == nullptr); + values[offset+i] = lb_const_nil(type->Struct.fields[i]->type).value; + } + } + + if (type->Struct.custom_align > 0) { + values[0] = LLVMConstNull(lb_alignment_prefix_type_hack(type->Struct.custom_align)); + } + + res.value = LLVMConstNamedStruct(lb_type(original_type), values, cast(unsigned)value_count); + return res; + } else if (is_type_bit_set(type)) { + ast_node(cl, CompoundLit, value.value_compound); + if (cl->elems.count == 0) { + return lb_const_nil(original_type); + } + + i64 sz = type_size_of(type); + if (sz == 0) { + return lb_const_nil(original_type); + } + + u64 bits = 0; + for_array(i, cl->elems) { + Ast *e = cl->elems[i]; + GB_ASSERT(e->kind != Ast_FieldValue); + + TypeAndValue tav = e->tav; + if (tav.mode != Addressing_Constant) { + continue; + } + GB_ASSERT(tav.value.kind == ExactValue_Integer); + i64 v = big_int_to_i64(&tav.value.value_integer); + i64 lower = type->BitSet.lower; + bits |= 1ull< slice"); - } - - return lb_constant_value(m, type, value); + return lb_const_nil(original_type); } lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type) { @@ -1048,21 +1792,8 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) { GB_ASSERT(tv.mode != Addressing_Type); if (tv.value.kind != ExactValue_Invalid) { - // // NOTE(bill): Edge case - // if (tv.value.kind != ExactValue_Compound && - // is_type_array(tv.type)) { - // Type *elem = core_array_type(tv.type); - // ExactValue value = convert_exact_value_for_type(tv.value, elem); - // irValue *x = ir_add_module_constant(proc->module, elem, value); - // return ir_emit_conv(proc, x, tv.type); - // } - - // if (tv.value.kind == ExactValue_Typeid) { - // irValue *v = ir_typeid(proc->module, tv.value.value_typeid); - // return ir_emit_conv(proc, v, tv.type); - // } - - return lb_add_module_constant(p->module, tv.type, tv.value); + // NOTE(bill): Short on constant values + return lb_const_value(p->module, tv.type, tv.value); } @@ -1077,9 +1808,10 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) { GB_PANIC("Non-constant basic literal %.*s(%td:%td) - %.*s", LIT(pos.file), pos.line, pos.column, LIT(bd->name)); case_end; - // case_ast_node(i, Implicit, expr); - // return ir_addr_load(proc, ir_build_addr(proc, expr)); - // case_end; + case_ast_node(i, Implicit, expr); + // return ir_addr_load(proc, ir_build_addr(proc, expr)); + GB_PANIC("TODO(bill): Implicit"); + case_end; case_ast_node(u, Undef, expr); return lbValue{LLVMGetUndef(lb_type(tv.type)), tv.type}; @@ -1095,7 +1827,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) { LIT(token.pos.file), token.pos.line, token.pos.column); return {}; } else if (e->kind == Entity_Nil) { - return lb_constant_nil(tv.type); + return lb_const_nil(tv.type); } auto *found = map_get(&p->module->values, hash_entity(e)); @@ -1105,7 +1837,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) { if (kind == LLVMFunctionTypeKind) { return v; } - return lbValue{LLVMBuildLoad2(p->builder, lb_type(type_deref(v.type)), v.value, ""), e->type}; + return lb_emit_load(p, v); // } else if (e != nullptr && e->kind == Entity_Variable) { // return ir_addr_load(proc, ir_build_addr(proc, expr)); } @@ -1125,6 +1857,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) { void lb_generate_module(lbGenerator *gen) { + lbModule *m = &gen->module; LLVMModuleRef mod = gen->module.mod; CheckerInfo *info = gen->info; @@ -1136,9 +1869,6 @@ void lb_generate_module(lbGenerator *gen) { auto *min_dep_set = &info->minimum_dependency_set; - - - for_array(i, info->entities) { // arena_free_all(&temp_arena); // gbAllocator a = temp_allocator; @@ -1180,40 +1910,33 @@ void lb_generate_module(lbGenerator *gen) { continue; } + String mangled_name = lb_get_entity_name(m, e); - if (entry_point == e) { - lbProcedure *p = lb_create_procedure(&gen->module, e); + if (e->pkg->name != "demo") { + continue; + } + + switch (e->kind) { + case Entity_TypeName: + break; + case Entity_Procedure: + break; + } + + + if (e->kind == Entity_Procedure) { + lbProcedure *p = lb_create_procedure(m, e); if (p->body != nullptr) { // Build Procedure - + lb_begin_procedure_body(p); lb_build_stmt(p, p->body); - - LLVMBuildRet(p->builder, nullptr); - // LLVMBuildRetVoid(p->builder); + lb_end_procedure_body(p); } lb_end_procedure(p); } } - { - LLVMTypeRef ret_type = LLVMFunctionType(LLVMVoidType(), nullptr, 0, false); - - LLVMValueRef p = LLVMAddFunction(mod, "mainCRTStartup", ret_type); - - - LLVMBasicBlockRef entry = LLVMAppendBasicBlock(p, "entry"); - - LLVMBuilderRef b = LLVMCreateBuilder(); - defer (LLVMDisposeBuilder(b)); - - LLVMPositionBuilderAtEnd(b, entry); - - - LLVMBuildRetVoid(b); - // LLVMBuildRet(b, nullptr); - } - char *llvm_error = nullptr; defer (LLVMDisposeMessage(llvm_error)); diff --git a/src/types.cpp b/src/types.cpp index 822583fee..a6f1e2ae5 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -305,6 +305,34 @@ struct Type { bool failure; }; +// IMPORTANT NOTE(bill): This must match the same as the in core.odin +enum Typeid_Kind : u8 { + Typeid_Invalid, + Typeid_Integer, + Typeid_Rune, + Typeid_Float, + Typeid_Complex, + Typeid_Quaternion, + Typeid_String, + Typeid_Boolean, + Typeid_Any, + Typeid_Type_Id, + Typeid_Pointer, + Typeid_Procedure, + Typeid_Array, + Typeid_Enumerated_Array, + Typeid_Dynamic_Array, + Typeid_Slice, + Typeid_Tuple, + Typeid_Struct, + Typeid_Union, + Typeid_Enum, + Typeid_Map, + Typeid_Bit_Field, + Typeid_Bit_Set, +}; + + // TODO(bill): Should I add extra information here specifying the kind of selection?