b32 used : 1;
} StructMember;
+typedef struct TypeWithOffset TypeWithOffset;
+struct TypeWithOffset {
+ Type* type;
+ u32 offset;
+};
+
#define TYPE_KINDS \
TYPE_KIND(Basic, TypeBasic) \
TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \
bh_table(StructMember) members; \
bh_arr(StructMember *) memarr; \
bh_arr(struct AstPolySolution) poly_sln; \
+ bh_arr(TypeWithOffset) linear_members; \
}) \
TYPE_KIND(Compound, struct { \
u32 count; \
u32 size; \
+ bh_arr(TypeWithOffset) linear_members; \
Type* types[]; \
}) \
TYPE_KIND(Array, struct { u32 size; u32 count; Type *elem; }) \
Type* type_make_dynarray(bh_allocator alloc, Type* of);
Type* type_make_varargs(bh_allocator alloc, Type* of);
+void build_linear_types_with_offset(Type* type, bh_arr(TypeWithOffset)* pdest, u32 offset);
+
const char* type_get_unique_name(Type* type);
const char* type_get_name(Type* type);
u32 type_get_alignment_log2(Type* type);
b32 type_lookup_member(Type* type, char* member, StructMember* smem);
b32 type_lookup_member_by_idx(Type* type, i32 idx, StructMember* smem);
+i32 type_linear_member_count(Type* type);
+b32 type_linear_member_lookup(Type* type, i32 idx, TypeWithOffset* two);
+
b32 type_struct_is_simple(Type* type);
b32 type_is_pointer(Type* type);
size = bh_max(s_node->min_size, size);
s_type->Struct.size = size;
+ s_type->Struct.linear_members = NULL;
+ bh_arr_new(global_heap_allocator, s_type->Struct.linear_members, s_type->Struct.mem_count);
+ build_linear_types_with_offset(s_type, &s_type->Struct.linear_members, 0);
+
return s_type;
}
bh_align(comp_type->Compound.size, 4);
+ comp_type->Compound.linear_members = NULL;
+ bh_arr_new(global_heap_allocator, comp_type->Compound.linear_members, comp_type->Compound.count);
+ build_linear_types_with_offset(comp_type, &comp_type->Compound.linear_members, 0);
+
return comp_type;
}
}
bh_align(comp_type->Compound.size, 4);
+
+ comp_type->Compound.linear_members = NULL;
+ bh_arr_new(global_heap_allocator, comp_type->Compound.linear_members, comp_type->Compound.count);
+ build_linear_types_with_offset(comp_type, &comp_type->Compound.linear_members, 0);
return comp_type;
}
return va_type;
}
+void build_linear_types_with_offset(Type* type, bh_arr(TypeWithOffset)* pdest, u32 offset) {
+ if (type_is_structlike_strict(type)) {
+ u32 mem_count = type_structlike_mem_count(type);
+ StructMember smem;
+ fori (i, 0, mem_count) {
+ type_lookup_member_by_idx(type, i, &smem);
+ build_linear_types_with_offset(smem.type, pdest, offset + smem.offset);
+ }
+
+ } else if (type->kind == Type_Kind_Compound) {
+ u32 elem_offset = 0;
+ fori (i, 0, type->Compound.count) {
+ build_linear_types_with_offset(type->Compound.types[i], pdest, offset + elem_offset);
+ elem_offset += bh_max(type_size_of(type->Compound.types[i]), 4);
+ }
+
+ } else {
+ bh_arr(TypeWithOffset) dest = *pdest;
+
+ TypeWithOffset two;
+ two.type = type;
+ two.offset = offset;
+ bh_arr_push(dest, two);
+
+ *pdest = dest;
+ }
+}
+
const char* type_get_unique_name(Type* type) {
if (type == NULL) return "unknown";
}
}
+i32 type_linear_member_count(Type* type) {
+ switch (type->kind) {
+ case Type_Kind_Slice:
+ case Type_Kind_VarArgs: return 2;
+ case Type_Kind_DynArray: return 3;
+ case Type_Kind_Compound: return bh_arr_length(type->Compound.linear_members);
+ case Type_Kind_Struct: return bh_arr_length(type->Struct.linear_members);
+ default: return 0;
+ }
+}
+
+b32 type_linear_member_lookup(Type* type, i32 idx, TypeWithOffset* two) {
+ switch (type->kind) {
+ case Type_Kind_Slice:
+ case Type_Kind_VarArgs: {
+ if (idx == 0) {
+ two->type = type->Slice.ptr_to_data;
+ two->offset = 0;
+ }
+ if (idx == 1) {
+ two->type = &basic_types[Basic_Kind_U32];
+ two->offset = 8;
+ }
+
+ return 1;
+ }
+ case Type_Kind_DynArray: {
+ if (idx == 0) {
+ two->type = type->DynArray.ptr_to_data;
+ two->offset = 0;
+ }
+ if (idx == 1) {
+ two->type = &basic_types[Basic_Kind_U32];
+ two->offset = 8;
+ }
+ if (idx == 2) {
+ two->type = &basic_types[Basic_Kind_U32];
+ two->offset = 12;
+ }
+
+ return 1;
+ }
+ case Type_Kind_Compound: *two = type->Compound.linear_members[idx]; return 1;
+ case Type_Kind_Struct: *two = type->Struct.linear_members[idx]; return 1;
+ default: return 0;
+ }
+}
+
b32 type_struct_is_simple(Type* type) {
if (type->kind != Type_Kind_Struct) return 0;
case Ast_Kind_Type_Compound: {
if (elem.actual->kind != Type_Kind_Compound) break;
- if (bh_arr_length(elem.actual->Compound.types) != bh_arr_length(((AstCompoundType *) elem.type_expr)->types)) break;
+ if (elem.actual->Compound.count != (u32) bh_arr_length(((AstCompoundType *) elem.type_expr)->types)) break;
AstCompoundType* ct = (AstCompoundType *) elem.type_expr;
u64 loc_idx = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
WIL(WI_LOCAL_SET, loc_idx);
- StructMember smem;
+ bh_arr(u64) temp_locals = NULL;
+ bh_arr_new(global_heap_allocator, temp_locals, 4);
- u32 mem_count = type_structlike_mem_count(type);
- forir (i, mem_count - 1, 0) {
- type_lookup_member_by_idx(type, i, &smem);
+ TypeWithOffset two;
- if (type_is_structlike_strict(smem.type)) {
- if (bh_arr_last(code).type == WI_LOCAL_SET && (u64) bh_arr_last(code).data.l == loc_idx) {
- bh_arr_last(code).type = WI_LOCAL_TEE;
- } else {
- WIL(WI_LOCAL_GET, loc_idx);
- }
+ u32 elem_count = type_linear_member_count(type);
+ forir (i, elem_count - 1, 0) {
+ type_linear_member_lookup(type, i, &two);
- emit_struct_store(mod, &code, smem.type, offset + smem.offset);
+ WasmType wt = onyx_type_to_wasm_type(two.type);
+ u64 tmp_idx = local_raw_allocate(mod->local_alloc, wt);
- } else {
- WasmType wt = onyx_type_to_wasm_type(smem.type);
- u64 tmp_idx = local_raw_allocate(mod->local_alloc, wt);
+ bh_arr_push(temp_locals, tmp_idx);
+ WIL(WI_LOCAL_SET, tmp_idx);
+ }
- WIL(WI_LOCAL_SET, tmp_idx);
- WIL(WI_LOCAL_GET, loc_idx);
- WIL(WI_LOCAL_GET, tmp_idx);
+ fori (i, 0, elem_count) {
+ type_linear_member_lookup(type, i, &two);
- emit_store_instruction(mod, &code, smem.type, offset + smem.offset);
+ u64 tmp_idx = bh_arr_pop(temp_locals);
+ WIL(WI_LOCAL_GET, loc_idx);
+ WIL(WI_LOCAL_GET, tmp_idx);
+ emit_store_instruction(mod, &code, two.type, offset + two.offset);
- local_raw_free(mod->local_alloc, wt);
- }
+ WasmType wt = onyx_type_to_wasm_type(two.type);
+ local_raw_free(mod->local_alloc, wt);
}
+ bh_arr_free(temp_locals);
local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
*pcode = code;