}
-// Represents a code block. Not constructable outside of using a '#{}' block.
+// Represents a code block. Not constructable outside of using a '#code' directive.
Code :: struct {}
\ No newline at end of file
return null;
}
+first :: #match {
+ (arr: ^[..] $T, predicate: (T) -> bool) -> ^T {
+ first((#type [] T).{ arr.data, arr.count }, predicate);
+ },
+
+ (arr: [] $T, predicate: (T) -> bool) -> ^T {
+ for ^it: arr {
+ if predicate(*it) do return it;
+ }
+
+ return null;
+ },
+}
+
count_where :: #match {
(arr: ^[..] $T, predicate: (T) -> bool) -> u32 {
count: u32 = 0;
// Should this return something else if the member was not found?
return 0;
-}
\ No newline at end of file
+}
+
+#operator == (t1: Type_Info_Function, t2: Type_Info_Function) -> bool {
+ if t1.parameter_types.count != t2.parameter_types.count do return false;
+ if t1.return_type != t2.return_type do return false;
+ if t1.is_variadic != t2.is_variadic do return false;
+
+ while i := 0; i < t1.parameter_types.count {
+ @Robustness // This does not handle nested procedure types
+ if t1.parameter_types[i] != t2.parameter_types[i] do return false;
+ }
+
+ return true;
+}
type: type_expr;
used: bool;
- has_default: bool;
+ default: rawptr; // Pointer to the initial value of the same type as the member.
+ // null if no default value is given, or if it is not compile time known.
+
+ // As another thought. This could become a thunk that get the default value
+ // at runtime or returns the value.
}
name: str;
static bh_imap type_slice_map;
static bh_imap type_dynarr_map;
static bh_imap type_vararg_map;
+static bh_table(u64) type_func_map;
static Type* type_create(TypeKind kind, bh_allocator a, u32 extra_type_pointer_count) {
Type* type = bh_alloc(a, sizeof(Type) + sizeof(Type *) * extra_type_pointer_count);
bh_imap_init(&type_slice_map, global_heap_allocator, 255);
bh_imap_init(&type_dynarr_map, global_heap_allocator, 255);
bh_imap_init(&type_vararg_map, global_heap_allocator, 255);
+ bh_table_init(global_heap_allocator, type_func_map, 64);
fori (i, 0, Basic_Kind_Count) type_register(&basic_types[i]);
}
if (func_type->Function.params[i] == NULL) return NULL;
}
+ char* name = (char *) type_get_unique_name(func_type);
+ if (bh_table_has(u64, type_func_map, name)) {
+ u64 id = bh_table_get(u64, type_func_map, name);
+ Type* existing_type = (Type *) bh_imap_get(&type_map, id);
+
+ // LEAK LEAK LEAK the func_type that is created
+ return existing_type;
+ }
+
type_register(func_type);
+ bh_table_put(u64, type_func_map, name, func_type->id);
+
return func_type;
}
}
}
+ // CopyPaste from above in type_build_from_ast
+ char* name = (char *) type_get_unique_name(func_type);
+ if (bh_table_has(u64, type_func_map, name)) {
+ u64 id = bh_table_get(u64, type_func_map, name);
+ Type* existing_type = (Type *) bh_imap_get(&type_map, id);
+
+ // LEAK LEAK LEAK the func_type that is created
+ return existing_type;
+ }
+
type_register(func_type);
+ bh_table_put(u64, type_func_map, name, func_type->id);
+
return func_type;
}
case Type_Kind_DynArray: return bh_aprintf(global_scratch_allocator, "[..] %s", type_get_unique_name(type->DynArray.ptr_to_data->Pointer.elem));
case Type_Kind_Function: {
- char buf[512];
- fori (i, 0, 512) buf[i] = 0;
+ char buf[1024];
+ memset(buf, 0, 1024);
- strncat(buf, "(", 511);
+ strncat(buf, "(", 1023);
fori (i, 0, type->Function.param_count) {
- strncat(buf, type_get_unique_name(type->Function.params[i]), 511);
+ strncat(buf, type_get_unique_name(type->Function.params[i]), 1023);
+
+ if (i >= type->Function.needed_param_count)
+ strncat(buf, "?", 1023);
+
if (i != type->Function.param_count - 1)
- strncat(buf, ", ", 511);
+ strncat(buf, ", ", 1023);
}
- strncat(buf, ") -> ", 511);
- strncat(buf, type_get_unique_name(type->Function.return_type), 511);
+ strncat(buf, ") -> ", 1023);
+ strncat(buf, type_get_unique_name(type->Function.return_type), 1023);
+
+ return bh_aprintf(global_scratch_allocator, "%s", buf);
+ }
+
+ case Type_Kind_Compound: {
+ char buf[1024];
+ memset(buf, 0, 1024);
+
+ strncat(buf, "(", 1023);
+ fori (i, 0, type->Compound.count) {
+ strncat(buf, type_get_unique_name(type->Compound.types[i]), 1023);
+ if (i != type->Compound.count - 1)
+ strncat(buf, ", ", 1023);
+ }
+ strncat(buf, ")", 1023);
return bh_aprintf(global_scratch_allocator, "%s", buf);
}
+
default: return "unknown";
}
}
if (overload == NULL) continue;
if (overload->kind != Ast_Kind_Function) continue;
if (overload->type == NULL) continue;
+ assert(overload->type->kind == Type_Kind_Function);
// NOTE: If the arguments cannot be placed successfully in the parameters list
if (!fill_in_arguments(&args, (AstNode *) overload, NULL)) continue;
EMIT_FUNC_NO_ARGS(leave_structured_block);
static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node);
+static b32 emit_raw_data_(OnyxWasmModule* mod, ptr data, AstTyped* node);
#include "onyxwasm_intrinsics.c"
#include "onyxwasm_type_table.c"
}
static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) {
+ if (!emit_raw_data_(mod, data, node)) {
+ onyx_report_error(node->token->pos,
+ "Cannot generate constant data for '%s'.",
+ onyx_ast_node_kind_string(node->kind));
+ }
+}
+
+static b32 emit_raw_data_(OnyxWasmModule* mod, ptr data, AstTyped* node) {
+ b32 retval = 1;
+
switch (node->kind) {
case Ast_Kind_Array_Literal: {
AstArrayLiteral* al = (AstArrayLiteral *) node;
i32 elem_size = type_size_of(al->type->Array.elem);
bh_arr_each(AstTyped *, expr, al->values) {
- emit_raw_data(mod, bh_pointer_add(data, i * elem_size), *expr);
+ retval &= emit_raw_data_(mod, bh_pointer_add(data, i * elem_size), *expr);
i++;
}
AstStructLiteral* sl = (AstStructLiteral *) node;
Type* sl_type = sl->type;
- assert(sl_type->kind == Type_Kind_Struct);
+ // ROBUSTNESS: Handle cases for slices and dynamic arrays
+ if (sl_type->kind != Type_Kind_Struct) {
+ retval = 0;
+ break;
+ }
i32 i = 0;
bh_arr_each(AstTyped *, expr, sl->args.values) {
- emit_raw_data(mod, bh_pointer_add(data, sl_type->Struct.memarr[i]->offset), *expr);
+ retval &= emit_raw_data_(mod, bh_pointer_add(data, sl_type->Struct.memarr[i]->offset), *expr);
i++;
}
case Ast_Kind_Enum_Value: {
AstEnumValue* ev = (AstEnumValue *) node;
- emit_raw_data(mod, data, (AstTyped *) ev->value);
+ retval &= emit_raw_data_(mod, data, (AstTyped *) ev->value);
break;
}
case Basic_Kind_I8:
case Basic_Kind_U8:
*((i8 *) data) = (i8) ((AstNumLit *) node)->value.i;
- return;
+ return retval;
case Basic_Kind_I16:
case Basic_Kind_U16:
*((i16 *) data) = (i16) ((AstNumLit *) node)->value.i;
- return;
+ return retval;
case Basic_Kind_I32:
case Basic_Kind_U32:
*((i32 *) data) = ((AstNumLit *) node)->value.i;
- return;
+ return retval;
case Basic_Kind_I64:
case Basic_Kind_U64:
case Basic_Kind_Rawptr:
*((i64 *) data) = ((AstNumLit *) node)->value.l;
- return;
+ return retval;
case Basic_Kind_F32:
*((f32 *) data) = ((AstNumLit *) node)->value.f;
- return;
+ return retval;
case Basic_Kind_F64:
*((f64 *) data) = ((AstNumLit *) node)->value.d;
- return;
+ return retval;
default: break;
}
//fallthrough
}
- default: onyx_report_error(node->token->pos,
- "Cannot generate constant data for '%s'.",
- onyx_ast_node_kind_string(node->kind));
+
+ default: retval = 0;
}
+
+ return retval;
}
static void emit_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) {
// This is the data behind the "type_table" slice in type_info.onyx
u32 type_count = bh_arr_length(type_map.entries) + 1;
u64* table_info = bh_alloc_array(global_heap_allocator, u64, type_count); // HACK
+ memset(table_info, 0, type_count * sizeof(u64));
bh_buffer table_buffer;
bh_buffer_init(&table_buffer, global_heap_allocator, 4096);
+ // Write a "NULL" at the beginning so nothing will have to point to the first byte of the buffer.
+ bh_buffer_write_u64(&table_buffer, 0);
+
bh_arr_each(bh__imap_entry, type_entry, type_map.entries) {
u64 type_idx = type_entry->key;
Type* type = (Type *) type_entry->value;
TypeStruct* s = &type->Struct;
u32* name_locations = bh_alloc_array(global_scratch_allocator, u32, s->mem_count);
u32* param_locations = bh_alloc_array(global_scratch_allocator, u32, bh_arr_length(s->poly_sln));
+ u32* value_locations = bh_alloc_array(global_scratch_allocator, u32, s->mem_count);
+ memset(value_locations, 0, s->mem_count * sizeof(u32));
u32 i = 0;
bh_arr_each(StructMember*, pmem, s->memarr) {
}
}
+ bh_buffer_align(&table_buffer, 8);
+
+ i = 0;
+ bh_arr_each(StructMember*, pmem, s->memarr) {
+ StructMember* mem = *pmem;
+
+ if (mem->initial_value == NULL || *mem->initial_value == NULL) {
+ i++;
+ continue;
+ }
+
+ AstTyped* value = *mem->initial_value;
+ assert(value->type);
+
+ if ((value->flags & Ast_Flag_Comptime) == 0) {
+ // onyx_report_warning(value->token->pos, "Warning: skipping generating default value for '%s' in '%s' because it is not compile-time known.\n", mem->name, s->name);
+ i++;
+ continue;
+ }
+
+ u32 size = type_size_of(value->type);
+ bh_buffer_align(&table_buffer, type_alignment_of(value->type));
+
+ bh_buffer_grow(&table_buffer, table_buffer.length + size);
+ u8* buffer = table_buffer.data + table_buffer.length;
+
+ if (!emit_raw_data_(module, buffer, value)) {
+ // Failed to generate raw data
+ // onyx_report_warning(value->token->pos, "Warning: failed to generate default value for '%s' in '%s'.\n", mem->name, s->name);
+ value_locations[i++] = 0;
+
+ } else {
+ // Success
+ value_locations[i++] = table_buffer.length;
+ table_buffer.length += size;
+ }
+ }
+
bh_buffer_align(&table_buffer, 8);
u32 members_base = table_buffer.length;
bh_arr_each(StructMember*, pmem, s->memarr) {
StructMember* mem = *pmem;
- u32 name_loc = name_locations[i++];
+ u32 name_loc = name_locations[i];
+ u32 value_loc = value_locations[i++];
bh_buffer_align(&table_buffer, 8);
PATCH;
bh_buffer_write_u32(&table_buffer, mem->offset);
bh_buffer_write_u32(&table_buffer, mem->type->id);
bh_buffer_write_byte(&table_buffer, mem->used ? 1 : 0);
- bh_buffer_write_byte(&table_buffer, mem->initial_value != NULL ? 1 : 0);
+
+ bh_buffer_align(&table_buffer, 8);
+ PATCH;
+ bh_buffer_write_u64(&table_buffer, value_loc);
}
bh_buffer_align(&table_buffer, 8);
}
bh_arr_each(u32, patch_loc, base_patch_locations) {
- *(u64 *) (bh_pointer_add(table_buffer.data, *patch_loc)) += offset;
+ u64* loc = bh_pointer_add(table_buffer.data, *patch_loc);
+ if (*loc == 0) continue;
+
+ *loc += offset;
}
WasmDatum type_info_data = {