Add #soa pointer type to aid with refactoring to #soa data types

a: #soa[16]Foo
p := &a[6]
#assert(type_of(p) == #soa^#soa[16]Foo)
p^.x = 123
p.x = 123
This commit is contained in:
gingerBill
2022-08-08 15:07:00 +01:00
parent 4633591918
commit 5e3cf45df3
24 changed files with 274 additions and 23 deletions
+3
View File
@@ -147,6 +147,9 @@ marshal_to_writer :: proc(w: io.Writer, v: any) -> (err: Marshal_Error) {
case runtime.Type_Info_Multi_Pointer: case runtime.Type_Info_Multi_Pointer:
return .Unsupported_Type return .Unsupported_Type
case runtime.Type_Info_Soa_Pointer:
return .Unsupported_Type
case runtime.Type_Info_Procedure: case runtime.Type_Info_Procedure:
return .Unsupported_Type return .Unsupported_Type
+13
View File
@@ -1031,6 +1031,15 @@ fmt_pointer :: proc(fi: ^Info, p: rawptr, verb: rune) {
} }
} }
fmt_soa_pointer :: proc(fi: ^Info, p: runtime.Raw_Soa_Pointer, verb: rune) {
io.write_string(fi.writer, "#soa{0x", &fi.n)
_fmt_int(fi, u64(uintptr(p.data)), 16, false, 8*size_of(rawptr), __DIGITS_UPPER)
io.write_string(fi.writer, ", ", &fi.n)
_fmt_int(fi, u64(p.index), 10, false, 8*size_of(rawptr), __DIGITS_UPPER)
io.write_string(fi.writer, "}", &fi.n)
}
enum_value_to_string :: proc(val: any) -> (string, bool) { enum_value_to_string :: proc(val: any) -> (string, bool) {
v := val v := val
v.id = runtime.typeid_base(v.id) v.id = runtime.typeid_base(v.id)
@@ -1867,6 +1876,10 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
fmt_pointer(fi, ptr, verb) fmt_pointer(fi, ptr, verb)
} }
case runtime.Type_Info_Soa_Pointer:
ptr := (^runtime.Raw_Soa_Pointer)(v.data)^
fmt_soa_pointer(fi, ptr, verb)
case runtime.Type_Info_Multi_Pointer: case runtime.Type_Info_Multi_Pointer:
ptr := (^rawptr)(v.data)^ ptr := (^rawptr)(v.data)^
if ptr == nil { if ptr == nil {
+1
View File
@@ -8,6 +8,7 @@ Raw_Cstring :: runtime.Raw_Cstring
Raw_Slice :: runtime.Raw_Slice Raw_Slice :: runtime.Raw_Slice
Raw_Dynamic_Array :: runtime.Raw_Dynamic_Array Raw_Dynamic_Array :: runtime.Raw_Dynamic_Array
Raw_Map :: runtime.Raw_Map Raw_Map :: runtime.Raw_Map
Raw_Soa_Pointer :: runtime.Raw_Soa_Pointer
Raw_Complex64 :: struct {real, imag: f32} Raw_Complex64 :: struct {real, imag: f32}
Raw_Complex128 :: struct {real, imag: f64} Raw_Complex128 :: struct {real, imag: f64}
+1
View File
@@ -700,6 +700,7 @@ Proc_Type :: struct {
Pointer_Type :: struct { Pointer_Type :: struct {
using node: Expr, using node: Expr,
tag: ^Expr,
pointer: tokenizer.Pos, pointer: tokenizer.Pos,
elem: ^Expr, elem: ^Expr,
} }
+1
View File
@@ -286,6 +286,7 @@ clone_node :: proc(node: ^Node) -> ^Node {
r.results = auto_cast clone(r.results) r.results = auto_cast clone(r.results)
case ^Pointer_Type: case ^Pointer_Type:
r.elem = clone(r.elem) r.elem = clone(r.elem)
r.tag = clone(r.tag)
case ^Multi_Pointer_Type: case ^Multi_Pointer_Type:
r.elem = clone(r.elem) r.elem = clone(r.elem)
case ^Array_Type: case ^Array_Type:
+2
View File
@@ -186,6 +186,7 @@ Type_Kind :: enum u32le {
Relative_Slice = 21, Relative_Slice = 21,
Multi_Pointer = 22, Multi_Pointer = 22,
Matrix = 23, Matrix = 23,
Soa_Pointer = 24,
} }
Type_Elems_Cap :: 4 Type_Elems_Cap :: 4
@@ -245,6 +246,7 @@ Type :: struct {
// .Relative_Slice - 2 types: 0=slice type, 1=base integer // .Relative_Slice - 2 types: 0=slice type, 1=base integer
// .Multi_Pointer - 1 type: 0=element // .Multi_Pointer - 1 type: 0=element
// .Matrix - 1 type: 0=element // .Matrix - 1 type: 0=element
// .Soa_Pointer - 1 type: 0=element
types: Array(Type_Index), types: Array(Type_Index),
// Used by: // Used by:
+15 -1
View File
@@ -2235,7 +2235,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
return parse_call_expr(p, bd) return parse_call_expr(p, bd)
case "soa", "simd": case "soa":
bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(name)) bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(name))
bd.tok = tok bd.tok = tok
bd.name = name.text bd.name = name.text
@@ -2244,6 +2244,20 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
#partial switch t in type.derived_expr { #partial switch t in type.derived_expr {
case ^ast.Array_Type: t.tag = bd case ^ast.Array_Type: t.tag = bd
case ^ast.Dynamic_Array_Type: t.tag = bd case ^ast.Dynamic_Array_Type: t.tag = bd
case ^ast.Pointer_Type: t.tag = bd
case:
error(p, original_type.pos, "expected an array or pointer type after #%s", name.text)
}
return original_type
case "simd":
bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(name))
bd.tok = tok
bd.name = name.text
original_type := parse_type(p)
type := ast.unparen_expr(original_type)
#partial switch t in type.derived_expr {
case ^ast.Array_Type: t.tag = bd
case: case:
error(p, original_type.pos, "expected an array type after #%s", name.text) error(p, original_type.pos, "expected an array type after #%s", name.text)
} }
+5
View File
@@ -34,6 +34,7 @@ Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector
Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer
Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice
Type_Info_Matrix :: runtime.Type_Info_Matrix Type_Info_Matrix :: runtime.Type_Info_Matrix
Type_Info_Soa_Pointer :: runtime.Type_Info_Soa_Pointer
Type_Info_Enum_Value :: runtime.Type_Info_Enum_Value Type_Info_Enum_Value :: runtime.Type_Info_Enum_Value
@@ -68,6 +69,7 @@ Type_Kind :: enum {
Relative_Pointer, Relative_Pointer,
Relative_Slice, Relative_Slice,
Matrix, Matrix,
Soa_Pointer,
} }
@@ -102,6 +104,7 @@ type_kind :: proc(T: typeid) -> Type_Kind {
case Type_Info_Relative_Pointer: return .Relative_Pointer case Type_Info_Relative_Pointer: return .Relative_Pointer
case Type_Info_Relative_Slice: return .Relative_Slice case Type_Info_Relative_Slice: return .Relative_Slice
case Type_Info_Matrix: return .Matrix case Type_Info_Matrix: return .Matrix
case Type_Info_Soa_Pointer: return .Soa_Pointer
} }
} }
@@ -194,6 +197,7 @@ typeid_elem :: proc(id: typeid) -> typeid {
} }
case Type_Info_Pointer: return v.elem.id case Type_Info_Pointer: return v.elem.id
case Type_Info_Multi_Pointer: return v.elem.id case Type_Info_Multi_Pointer: return v.elem.id
case Type_Info_Soa_Pointer: return v.elem.id
case Type_Info_Array: return v.elem.id case Type_Info_Array: return v.elem.id
case Type_Info_Enumerated_Array: return v.elem.id case Type_Info_Enumerated_Array: return v.elem.id
case Type_Info_Slice: return v.elem.id case Type_Info_Slice: return v.elem.id
@@ -1419,6 +1423,7 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
Type_Info_Enum, Type_Info_Enum,
Type_Info_Simd_Vector, Type_Info_Simd_Vector,
Type_Info_Relative_Pointer, Type_Info_Relative_Pointer,
Type_Info_Soa_Pointer,
Type_Info_Matrix: Type_Info_Matrix:
return mem.compare_byte_ptrs((^byte)(a.data), (^byte)(b.data), t.size) == 0 return mem.compare_byte_ptrs((^byte)(a.data), (^byte)(b.data), t.size) == 0
+13
View File
@@ -68,6 +68,11 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
y := b.variant.(Type_Info_Multi_Pointer) or_return y := b.variant.(Type_Info_Multi_Pointer) or_return
return are_types_identical(x.elem, y.elem) return are_types_identical(x.elem, y.elem)
case Type_Info_Soa_Pointer:
y := b.variant.(Type_Info_Soa_Pointer) or_return
return are_types_identical(x.elem, y.elem)
case Type_Info_Procedure: case Type_Info_Procedure:
y := b.variant.(Type_Info_Procedure) or_return y := b.variant.(Type_Info_Procedure) or_return
switch { switch {
@@ -256,6 +261,11 @@ is_multi_pointer :: proc(info: ^Type_Info) -> bool {
_, ok := type_info_base(info).variant.(Type_Info_Multi_Pointer) _, ok := type_info_base(info).variant.(Type_Info_Multi_Pointer)
return ok return ok
} }
is_soa_pointer :: proc(info: ^Type_Info) -> bool {
if info == nil { return false }
_, ok := type_info_base(info).variant.(Type_Info_Soa_Pointer)
return ok
}
is_pointer_internally :: proc(info: ^Type_Info) -> bool { is_pointer_internally :: proc(info: ^Type_Info) -> bool {
if info == nil { return false } if info == nil { return false }
#partial switch v in info.variant { #partial switch v in info.variant {
@@ -437,6 +447,9 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
case Type_Info_Multi_Pointer: case Type_Info_Multi_Pointer:
io.write_string(w, "[^]", &n) or_return io.write_string(w, "[^]", &n) or_return
write_type(w, info.elem, &n) or_return write_type(w, info.elem, &n) or_return
case Type_Info_Soa_Pointer:
io.write_string(w, "#soa ^", &n) or_return
write_type(w, info.elem, &n) or_return
case Type_Info_Procedure: case Type_Info_Procedure:
io.write_string(w, "proc", &n) or_return io.write_string(w, "proc", &n) or_return
if info.params == nil { if info.params == nil {
+10
View File
@@ -176,6 +176,9 @@ Type_Info_Matrix :: struct {
column_count: int, column_count: int,
// Total element count = column_count * elem_stride // Total element count = column_count * elem_stride
} }
Type_Info_Soa_Pointer :: struct {
elem: ^Type_Info,
}
Type_Info_Flag :: enum u8 { Type_Info_Flag :: enum u8 {
Comparable = 0, Comparable = 0,
@@ -217,6 +220,7 @@ Type_Info :: struct {
Type_Info_Relative_Pointer, Type_Info_Relative_Pointer,
Type_Info_Relative_Slice, Type_Info_Relative_Slice,
Type_Info_Matrix, Type_Info_Matrix,
Type_Info_Soa_Pointer,
}, },
} }
@@ -403,6 +407,12 @@ Raw_Cstring :: struct {
data: [^]byte, data: [^]byte,
} }
Raw_Soa_Pointer :: struct {
data: rawptr,
index: int,
}
/* /*
// Defined internally by the compiler // Defined internally by the compiler
+3
View File
@@ -228,6 +228,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
case Type_Info_Multi_Pointer: case Type_Info_Multi_Pointer:
print_string("[^]") print_string("[^]")
print_type(info.elem) print_type(info.elem)
case Type_Info_Soa_Pointer:
print_string("#soa ^")
print_type(info.elem)
case Type_Info_Procedure: case Type_Info_Procedure:
print_string("proc") print_string("proc")
if info.params == nil { if info.params == nil {
+1 -1
View File
@@ -320,7 +320,7 @@ void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *def)
} else if (is_type_any(e->type)) { } else if (is_type_any(e->type)) {
error(init_expr, "'distinct' cannot be applied to 'any'"); error(init_expr, "'distinct' cannot be applied to 'any'");
is_distinct = false; is_distinct = false;
} else if (is_type_simd_vector(e->type)) { } else if (is_type_simd_vector(e->type) || is_type_soa_pointer(e->type)) {
gbString str = type_to_string(e->type); gbString str = type_to_string(e->type);
error(init_expr, "'distinct' cannot be applied to '%s'", str); error(init_expr, "'distinct' cannot be applied to '%s'", str);
gb_string_free(str); gb_string_free(str);
+17 -5
View File
@@ -2052,7 +2052,7 @@ bool check_is_not_addressable(CheckerContext *c, Operand *o) {
return false; return false;
} }
return o->mode != Addressing_Variable; return o->mode != Addressing_Variable && o->mode != Addressing_SoaVariable;
} }
void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *node) { void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *node) {
@@ -2069,9 +2069,6 @@ void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *node) {
error(op, "Cannot take the pointer address of '%s' which is a procedure parameter", str); error(op, "Cannot take the pointer address of '%s' which is a procedure parameter", str);
} else { } else {
switch (o->mode) { switch (o->mode) {
case Addressing_SoaVariable:
error(op, "Cannot take the pointer address of '%s' as it is an indirect index of an SOA struct", str);
break;
case Addressing_Constant: case Addressing_Constant:
error(op, "Cannot take the pointer address of '%s' which is a constant", str); error(op, "Cannot take the pointer address of '%s' which is a constant", str);
break; break;
@@ -2099,7 +2096,19 @@ void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *node) {
return; return;
} }
o->type = alloc_type_pointer(o->type); if (o->mode == Addressing_SoaVariable) {
ast_node(ue, UnaryExpr, node);
if (ast_node_expect(ue->expr, Ast_IndexExpr)) {
ast_node(ie, IndexExpr, ue->expr);
Type *soa_type = type_of_expr(ie->expr);
GB_ASSERT(is_type_soa_struct(soa_type));
o->type = alloc_type_soa_pointer(soa_type);
} else {
o->type = alloc_type_pointer(o->type);
}
} else {
o->type = alloc_type_pointer(o->type);
}
switch (o->mode) { switch (o->mode) {
case Addressing_OptionalOk: case Addressing_OptionalOk:
@@ -9378,6 +9387,9 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
if (t->kind == Type_Pointer && !is_type_empty_union(t->Pointer.elem)) { if (t->kind == Type_Pointer && !is_type_empty_union(t->Pointer.elem)) {
o->mode = Addressing_Variable; o->mode = Addressing_Variable;
o->type = t->Pointer.elem; o->type = t->Pointer.elem;
} else if (t->kind == Type_SoaPointer) {
o->mode = Addressing_SoaVariable;
o->type = type_deref(t);
} else if (t->kind == Type_RelativePointer) { } else if (t->kind == Type_RelativePointer) {
if (o->mode != Addressing_Variable) { if (o->mode != Addressing_Variable) {
gbString str = expr_to_string(o->expr); gbString str = expr_to_string(o->expr);
+24 -4
View File
@@ -2693,9 +2693,12 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
case_ast_node(ue, UnaryExpr, e); case_ast_node(ue, UnaryExpr, e);
switch (ue->op.kind) { switch (ue->op.kind) {
case Token_Pointer: case Token_Pointer:
*type = alloc_type_pointer(check_type(ctx, ue->expr)); {
set_base_type(named_type, *type); Type *elem = check_type(ctx, ue->expr);
return true; *type = alloc_type_pointer(elem);
set_base_type(named_type, *type);
return true;
}
} }
case_end; case_end;
@@ -2721,7 +2724,24 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
elem = o.type; elem = o.type;
} }
*type = alloc_type_pointer(elem); if (pt->tag != nullptr) {
GB_ASSERT(pt->tag->kind == Ast_BasicDirective);
String name = pt->tag->BasicDirective.name.string;
if (name == "soa") {
// TODO(bill): generic #soa pointers
if (is_type_soa_struct(elem)) {
*type = alloc_type_soa_pointer(elem);
} else {
error(pt->tag, "#soa pointers require an #soa record type as the element");
*type = alloc_type_pointer(elem);
}
} else {
error(pt->tag, "Invalid tag applied to pointer, got #%.*s", LIT(name));
*type = alloc_type_pointer(elem);
}
} else {
*type = alloc_type_pointer(elem);
}
set_base_type(named_type, *type); set_base_type(named_type, *type);
return true; return true;
case_end; case_end;
+11
View File
@@ -1947,6 +1947,11 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
add_type_info_type_internal(c, bt->Matrix.elem); add_type_info_type_internal(c, bt->Matrix.elem);
break; break;
case Type_SoaPointer:
add_type_info_type_internal(c, bt->SoaPointer.elem);
break;
default: default:
GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind); GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind);
break; break;
@@ -2164,6 +2169,10 @@ void add_min_dep_type_info(Checker *c, Type *t) {
add_min_dep_type_info(c, bt->Matrix.elem); add_min_dep_type_info(c, bt->Matrix.elem);
break; break;
case Type_SoaPointer:
add_min_dep_type_info(c, bt->SoaPointer.elem);
break;
default: default:
GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind])); GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind]));
break; break;
@@ -2756,6 +2765,7 @@ void init_core_type_info(Checker *c) {
t_type_info_relative_pointer = find_core_type(c, str_lit("Type_Info_Relative_Pointer")); t_type_info_relative_pointer = find_core_type(c, str_lit("Type_Info_Relative_Pointer"));
t_type_info_relative_slice = find_core_type(c, str_lit("Type_Info_Relative_Slice")); t_type_info_relative_slice = find_core_type(c, str_lit("Type_Info_Relative_Slice"));
t_type_info_matrix = find_core_type(c, str_lit("Type_Info_Matrix")); t_type_info_matrix = find_core_type(c, str_lit("Type_Info_Matrix"));
t_type_info_soa_pointer = find_core_type(c, str_lit("Type_Info_Soa_Pointer"));
t_type_info_named_ptr = alloc_type_pointer(t_type_info_named); t_type_info_named_ptr = alloc_type_pointer(t_type_info_named);
t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer); t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer);
@@ -2784,6 +2794,7 @@ void init_core_type_info(Checker *c) {
t_type_info_relative_pointer_ptr = alloc_type_pointer(t_type_info_relative_pointer); t_type_info_relative_pointer_ptr = alloc_type_pointer(t_type_info_relative_pointer);
t_type_info_relative_slice_ptr = alloc_type_pointer(t_type_info_relative_slice); t_type_info_relative_slice_ptr = alloc_type_pointer(t_type_info_relative_slice);
t_type_info_matrix_ptr = alloc_type_pointer(t_type_info_matrix); t_type_info_matrix_ptr = alloc_type_pointer(t_type_info_matrix);
t_type_info_soa_pointer_ptr = alloc_type_pointer(t_type_info_soa_pointer);
} }
void init_mem_allocator(Checker *c) { void init_mem_allocator(Checker *c) {
+1
View File
@@ -83,6 +83,7 @@ enum OdinDocTypeKind : u32 {
OdinDocType_RelativeSlice = 21, OdinDocType_RelativeSlice = 21,
OdinDocType_MultiPointer = 22, OdinDocType_MultiPointer = 22,
OdinDocType_Matrix = 23, OdinDocType_Matrix = 23,
OdinDocType_SoaPointer = 24,
}; };
enum OdinDocTypeFlag_Basic : u32 { enum OdinDocTypeFlag_Basic : u32 {
+4
View File
@@ -532,6 +532,10 @@ OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) {
doc_type.kind = OdinDocType_MultiPointer; doc_type.kind = OdinDocType_MultiPointer;
doc_type.types = odin_doc_type_as_slice(w, type->MultiPointer.elem); doc_type.types = odin_doc_type_as_slice(w, type->MultiPointer.elem);
break; break;
case Type_SoaPointer:
doc_type.kind = OdinDocType_SoaPointer;
doc_type.types = odin_doc_type_as_slice(w, type->SoaPointer.elem);
break;
case Type_Array: case Type_Array:
doc_type.kind = OdinDocType_Array; doc_type.kind = OdinDocType_Array;
doc_type.elem_count_len = 1; doc_type.elem_count_len = 1;
+28 -3
View File
@@ -2803,7 +2803,15 @@ lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, lbValue x) {
return {}; return {};
} }
lbValue lb_make_soa_pointer(lbProcedure *p, Type *type, lbValue const &addr, lbValue const &index) {
lbAddr v = lb_add_local_generated(p, type, false);
lbValue ptr = lb_emit_struct_ep(p, v.addr, 0);
lbValue idx = lb_emit_struct_ep(p, v.addr, 1);
lb_emit_store(p, ptr, addr);
lb_emit_store(p, idx, index);
return lb_addr_load(p, v);
}
lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
ast_node(ue, UnaryExpr, expr); ast_node(ue, UnaryExpr, expr);
@@ -2842,7 +2850,17 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
lb_emit_store(p, gep1, ok); lb_emit_store(p, gep1, ok);
return lb_addr_load(p, res); return lb_addr_load(p, res);
} if (ue_expr->kind == Ast_CompoundLit) { } else if (is_type_soa_pointer(tv.type)) {
ast_node(ie, IndexExpr, ue_expr);
lbValue addr = lb_build_addr_ptr(p, ie->expr);
lbValue index = lb_build_expr(p, ie->index);
if (!build_context.no_bounds_check) {
// TODO(bill): soa bounds checking
}
return lb_make_soa_pointer(p, tv.type, addr, index);
} else if (ue_expr->kind == Ast_CompoundLit) {
lbValue v = lb_build_expr(p, ue->expr); lbValue v = lb_build_expr(p, ue->expr);
Type *type = v.type; Type *type = v.type;
@@ -3604,6 +3622,7 @@ lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
// NOTE(bill): just patch the index in place // NOTE(bill): just patch the index in place
sel.index[0] = addr.swizzle.indices[sel.index[0]]; sel.index[0] = addr.swizzle.indices[sel.index[0]];
} }
lbValue a = lb_addr_get_ptr(p, addr); lbValue a = lb_addr_get_ptr(p, addr);
a = lb_emit_deep_field_gep(p, a, sel); a = lb_emit_deep_field_gep(p, a, sel);
return lb_addr(a); return lb_addr(a);
@@ -4093,10 +4112,16 @@ lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
case_end; case_end;
case_ast_node(de, DerefExpr, expr); case_ast_node(de, DerefExpr, expr);
if (is_type_relative_pointer(type_of_expr(de->expr))) { Type *t = type_of_expr(de->expr);
if (is_type_relative_pointer(t)) {
lbAddr addr = lb_build_addr(p, de->expr); lbAddr addr = lb_build_addr(p, de->expr);
addr.relative.deref = true; addr.relative.deref = true;
return addr;\ return addr;
} else if (is_type_soa_pointer(t)) {
lbValue value = lb_build_expr(p, de->expr);
lbValue ptr = lb_emit_struct_ev(p, value, 0);
lbValue idx = lb_emit_struct_ev(p, value, 1);
return lb_addr_soa_variable(ptr, idx, nullptr);
} }
lbValue addr = lb_build_expr(p, de->expr); lbValue addr = lb_build_expr(p, de->expr);
return lb_addr(addr); return lb_addr(addr);
+15
View File
@@ -916,7 +916,13 @@ lbValue lb_emit_load(lbProcedure *p, lbValue value) {
Type *t = vt->MultiPointer.elem; Type *t = vt->MultiPointer.elem;
LLVMValueRef v = LLVMBuildLoad2(p->builder, llvm_addr_type(value), value.value, ""); LLVMValueRef v = LLVMBuildLoad2(p->builder, llvm_addr_type(value), value.value, "");
return lbValue{v, t}; return lbValue{v, t};
} else if (is_type_soa_pointer(value.type)) {
lbValue ptr = lb_emit_struct_ev(p, value, 0);
lbValue idx = lb_emit_struct_ev(p, value, 1);
lbAddr addr = lb_addr_soa_variable(ptr, idx, nullptr);
return lb_addr_load(p, addr);
} }
GB_ASSERT(is_type_pointer(value.type)); GB_ASSERT(is_type_pointer(value.type));
Type *t = type_deref(value.type); Type *t = type_deref(value.type);
LLVMValueRef v = LLVMBuildLoad2(p->builder, llvm_addr_type(value), value.value, ""); LLVMValueRef v = LLVMBuildLoad2(p->builder, llvm_addr_type(value), value.value, "");
@@ -2055,6 +2061,15 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
m->internal_type_level += 1; m->internal_type_level += 1;
return t; return t;
} }
case Type_SoaPointer:
{
unsigned field_count = 2;
LLVMTypeRef *fields = gb_alloc_array(permanent_allocator(), LLVMTypeRef, field_count);
fields[0] = LLVMPointerType(lb_type(m, type->Pointer.elem), 0);
fields[1] = LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.word_size);
return LLVMStructTypeInContext(ctx, fields, field_count, false);
}
} }
+15
View File
@@ -57,6 +57,7 @@ lbValue lb_typeid(lbModule *m, Type *type) {
case Type_SimdVector: kind = Typeid_Simd_Vector; break; case Type_SimdVector: kind = Typeid_Simd_Vector; break;
case Type_RelativePointer: kind = Typeid_Relative_Pointer; break; case Type_RelativePointer: kind = Typeid_Relative_Pointer; break;
case Type_RelativeSlice: kind = Typeid_Relative_Slice; break; case Type_RelativeSlice: kind = Typeid_Relative_Slice; break;
case Type_SoaPointer: kind = Typeid_SoaPointer; break;
} }
if (is_type_cstring(type)) { if (is_type_cstring(type)) {
@@ -445,6 +446,20 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
lb_emit_store(p, tag, res); lb_emit_store(p, tag, res);
break; break;
} }
case Type_SoaPointer: {
tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_soa_pointer_ptr);
lbValue gep = lb_get_type_info_ptr(m, t->SoaPointer.elem);
LLVMValueRef vals[1] = {
gep.value,
};
lbValue res = {};
res.type = type_deref(tag.type);
res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals));
lb_emit_store(p, tag, res);
break;
}
case Type_Array: { case Type_Array: {
tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_array_ptr); tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_array_ptr);
i64 ez = type_size_of(t->Array.elem); i64 ez = type_size_of(t->Array.elem);
+34 -1
View File
@@ -1007,6 +1007,11 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
case 0: result_type = t->RelativeSlice.base_integer; break; case 0: result_type = t->RelativeSlice.base_integer; break;
case 1: result_type = t->RelativeSlice.base_integer; break; case 1: result_type = t->RelativeSlice.base_integer; break;
} }
} else if (is_type_soa_pointer(t)) {
switch (index) {
case 0: result_type = alloc_type_pointer(t->SoaPointer.elem); break;
case 1: result_type = t_int; break;
}
} else { } else {
GB_PANIC("TODO(bill): struct_gep type: %s, %d", type_to_string(s.type), index); GB_PANIC("TODO(bill): struct_gep type: %s, %d", type_to_string(s.type), index);
} }
@@ -1137,6 +1142,13 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) {
result_type = t->Array.elem; result_type = t->Array.elem;
break; break;
case Type_SoaPointer:
switch (index) {
case 0: result_type = alloc_type_pointer(t->SoaPointer.elem); break;
case 1: result_type = t_int; break;
}
break;
default: default:
GB_PANIC("TODO(bill): struct_ev type: %s, %d", type_to_string(s.type), index); GB_PANIC("TODO(bill): struct_ev type: %s, %d", type_to_string(s.type), index);
break; break;
@@ -1164,7 +1176,28 @@ lbValue lb_emit_deep_field_gep(lbProcedure *p, lbValue e, Selection sel) {
} }
type = core_type(type); type = core_type(type);
if (is_type_quaternion(type)) { if (type->kind == Type_SoaPointer) {
lbValue addr = lb_emit_struct_ep(p, e, 0);
lbValue index = lb_emit_struct_ep(p, e, 1);
addr = lb_emit_load(p, addr);
index = lb_emit_load(p, index);
i32 first_index = sel.index[0];
Selection sub_sel = sel;
sub_sel.index.data += 1;
sub_sel.index.count -= 1;
lbValue arr = lb_emit_struct_ep(p, addr, first_index);
Type *t = base_type(type_deref(addr.type));
GB_ASSERT(is_type_soa_struct(t));
if (t->Struct.soa_kind == StructSoa_Fixed) {
e = lb_emit_array_ep(p, arr, index);
} else {
e = lb_emit_ptr_offset(p, lb_emit_load(p, arr), index);
}
} else if (is_type_quaternion(type)) {
e = lb_emit_struct_ep(p, e, index); e = lb_emit_struct_ep(p, e, index);
} else if (is_type_raw_union(type)) { } else if (is_type_raw_union(type)) {
type = get_struct_field_type(type, index); type = get_struct_field_type(type, index);
+4 -2
View File
@@ -356,6 +356,7 @@ Ast *clone_ast(Ast *node) {
break; break;
case Ast_PointerType: case Ast_PointerType:
n->PointerType.type = clone_ast(n->PointerType.type); n->PointerType.type = clone_ast(n->PointerType.type);
n->PointerType.tag = clone_ast(n->PointerType.tag);
break; break;
case Ast_MultiPointerType: case Ast_MultiPointerType:
n->MultiPointerType.type = clone_ast(n->MultiPointerType.type); n->MultiPointerType.type = clone_ast(n->MultiPointerType.type);
@@ -2167,10 +2168,11 @@ Ast *parse_operand(AstFile *f, bool lhs) {
Ast *original_type = parse_type(f); Ast *original_type = parse_type(f);
Ast *type = unparen_expr(original_type); Ast *type = unparen_expr(original_type);
switch (type->kind) { switch (type->kind) {
case Ast_ArrayType: type->ArrayType.tag = tag; break; case Ast_ArrayType: type->ArrayType.tag = tag; break;
case Ast_DynamicArrayType: type->DynamicArrayType.tag = tag; break; case Ast_DynamicArrayType: type->DynamicArrayType.tag = tag; break;
case Ast_PointerType: type->PointerType.tag = tag; break;
default: default:
syntax_error(type, "Expected an array type after #%.*s, got %.*s", LIT(name.string), LIT(ast_strings[type->kind])); syntax_error(type, "Expected an array or pointer type after #%.*s, got %.*s", LIT(name.string), LIT(ast_strings[type->kind]));
break; break;
} }
return original_type; return original_type;
+2 -1
View File
@@ -650,7 +650,8 @@ AST_KIND(_TypeBegin, "", bool) \
}) \ }) \
AST_KIND(PointerType, "pointer type", struct { \ AST_KIND(PointerType, "pointer type", struct { \
Token token; \ Token token; \
Ast *type; \ Ast *type; \
Ast *tag; \
}) \ }) \
AST_KIND(RelativeType, "relative type", struct { \ AST_KIND(RelativeType, "relative type", struct { \
Ast *tag; \ Ast *tag; \
+51 -5
View File
@@ -278,7 +278,8 @@ struct TypeProc {
Type *generic_row_count; \ Type *generic_row_count; \
Type *generic_column_count; \ Type *generic_column_count; \
i64 stride_in_bytes; \ i64 stride_in_bytes; \
}) }) \
TYPE_KIND(SoaPointer, struct { Type *elem; })
enum TypeKind { enum TypeKind {
@@ -350,6 +351,7 @@ enum Typeid_Kind : u8 {
Typeid_Relative_Pointer, Typeid_Relative_Pointer,
Typeid_Relative_Slice, Typeid_Relative_Slice,
Typeid_Matrix, Typeid_Matrix,
Typeid_SoaPointer,
}; };
// IMPORTANT NOTE(bill): This must match the same as the in core.odin // IMPORTANT NOTE(bill): This must match the same as the in core.odin
@@ -644,6 +646,7 @@ gb_global Type *t_type_info_simd_vector = nullptr;
gb_global Type *t_type_info_relative_pointer = nullptr; gb_global Type *t_type_info_relative_pointer = nullptr;
gb_global Type *t_type_info_relative_slice = nullptr; gb_global Type *t_type_info_relative_slice = nullptr;
gb_global Type *t_type_info_matrix = nullptr; gb_global Type *t_type_info_matrix = nullptr;
gb_global Type *t_type_info_soa_pointer = nullptr;
gb_global Type *t_type_info_named_ptr = nullptr; gb_global Type *t_type_info_named_ptr = nullptr;
gb_global Type *t_type_info_integer_ptr = nullptr; gb_global Type *t_type_info_integer_ptr = nullptr;
@@ -672,6 +675,7 @@ gb_global Type *t_type_info_simd_vector_ptr = nullptr;
gb_global Type *t_type_info_relative_pointer_ptr = nullptr; gb_global Type *t_type_info_relative_pointer_ptr = nullptr;
gb_global Type *t_type_info_relative_slice_ptr = nullptr; gb_global Type *t_type_info_relative_slice_ptr = nullptr;
gb_global Type *t_type_info_matrix_ptr = nullptr; gb_global Type *t_type_info_matrix_ptr = nullptr;
gb_global Type *t_type_info_soa_pointer_ptr = nullptr;
gb_global Type *t_allocator = nullptr; gb_global Type *t_allocator = nullptr;
gb_global Type *t_allocator_ptr = nullptr; gb_global Type *t_allocator_ptr = nullptr;
@@ -735,6 +739,7 @@ Type * bit_set_to_int(Type *t);
bool are_types_identical(Type *x, Type *y); bool are_types_identical(Type *x, Type *y);
bool is_type_pointer(Type *t); bool is_type_pointer(Type *t);
bool is_type_soa_pointer(Type *t);
bool is_type_proc(Type *t); bool is_type_proc(Type *t);
bool is_type_slice(Type *t); bool is_type_slice(Type *t);
bool is_type_integer(Type *t); bool is_type_integer(Type *t);
@@ -917,6 +922,13 @@ Type *alloc_type_multi_pointer(Type *elem) {
return t; return t;
} }
Type *alloc_type_soa_pointer(Type *elem) {
Type *t = alloc_type(Type_SoaPointer);
t->SoaPointer.elem = elem;
return t;
}
Type *alloc_type_array(Type *elem, i64 count, Type *generic_count = nullptr) { Type *alloc_type_array(Type *elem, i64 count, Type *generic_count = nullptr) {
if (generic_count != nullptr) { if (generic_count != nullptr) {
Type *t = alloc_type(Type_Array); Type *t = alloc_type(Type_Array);
@@ -1109,11 +1121,17 @@ Type *type_deref(Type *t) {
if (bt == nullptr) { if (bt == nullptr) {
return nullptr; return nullptr;
} }
if (bt->kind == Type_Pointer) { switch (bt->kind) {
case Type_Pointer:
return bt->Pointer.elem; return bt->Pointer.elem;
} case Type_RelativePointer:
if (bt->kind == Type_RelativePointer) {
return type_deref(bt->RelativePointer.pointer_type); return type_deref(bt->RelativePointer.pointer_type);
case Type_SoaPointer:
{
Type *elem = base_type(bt->SoaPointer.elem);
GB_ASSERT(elem->kind == Type_Struct && elem->Struct.soa_kind != StructSoa_None);
return elem->Struct.soa_elem;
}
} }
} }
return t; return t;
@@ -1327,6 +1345,10 @@ bool is_type_pointer(Type *t) {
} }
return t->kind == Type_Pointer; return t->kind == Type_Pointer;
} }
bool is_type_soa_pointer(Type *t) {
t = base_type(t);
return t->kind == Type_SoaPointer;
}
bool is_type_multi_pointer(Type *t) { bool is_type_multi_pointer(Type *t) {
t = base_type(t); t = base_type(t);
return t->kind == Type_MultiPointer; return t->kind == Type_MultiPointer;
@@ -1804,7 +1826,7 @@ bool is_type_dereferenceable(Type *t) {
if (is_type_rawptr(t)) { if (is_type_rawptr(t)) {
return false; return false;
} }
return is_type_pointer(t); return is_type_pointer(t) || is_type_soa_pointer(t);
} }
@@ -2079,6 +2101,9 @@ bool is_type_polymorphic(Type *t, bool or_specialized=false) {
case Type_Pointer: case Type_Pointer:
return is_type_polymorphic(t->Pointer.elem, or_specialized); return is_type_polymorphic(t->Pointer.elem, or_specialized);
case Type_SoaPointer:
return is_type_polymorphic(t->SoaPointer.elem, or_specialized);
case Type_EnumeratedArray: case Type_EnumeratedArray:
if (is_type_polymorphic(t->EnumeratedArray.index, or_specialized)) { if (is_type_polymorphic(t->EnumeratedArray.index, or_specialized)) {
return true; return true;
@@ -2196,6 +2221,7 @@ bool type_has_nil(Type *t) {
case Type_Slice: case Type_Slice:
case Type_Proc: case Type_Proc:
case Type_Pointer: case Type_Pointer:
case Type_SoaPointer:
case Type_MultiPointer: case Type_MultiPointer:
case Type_DynamicArray: case Type_DynamicArray:
case Type_Map: case Type_Map:
@@ -2262,6 +2288,8 @@ bool is_type_comparable(Type *t) {
return true; return true;
case Type_Pointer: case Type_Pointer:
return true; return true;
case Type_SoaPointer:
return true;
case Type_MultiPointer: case Type_MultiPointer:
return true; return true;
case Type_Enum: case Type_Enum:
@@ -2335,6 +2363,7 @@ bool is_type_simple_compare(Type *t) {
case Type_Pointer: case Type_Pointer:
case Type_MultiPointer: case Type_MultiPointer:
case Type_SoaPointer:
case Type_Proc: case Type_Proc:
case Type_BitSet: case Type_BitSet:
return true; return true;
@@ -2558,6 +2587,12 @@ bool are_types_identical_internal(Type *x, Type *y, bool check_tuple_names) {
} }
break; break;
case Type_SoaPointer:
if (y->kind == Type_SoaPointer) {
return are_types_identical(x->SoaPointer.elem, y->SoaPointer.elem);
}
break;
case Type_Named: case Type_Named:
if (y->kind == Type_Named) { if (y->kind == Type_Named) {
return x->Named.type_name == y->Named.type_name; return x->Named.type_name == y->Named.type_name;
@@ -3475,6 +3510,9 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
return type_align_of_internal(t->RelativePointer.base_integer, path); return type_align_of_internal(t->RelativePointer.base_integer, path);
case Type_RelativeSlice: case Type_RelativeSlice:
return type_align_of_internal(t->RelativeSlice.base_integer, path); return type_align_of_internal(t->RelativeSlice.base_integer, path);
case Type_SoaPointer:
return build_context.word_size;
} }
// return gb_clamp(next_pow2(type_size_of(t)), 1, build_context.max_align); // return gb_clamp(next_pow2(type_size_of(t)), 1, build_context.max_align);
@@ -3580,6 +3618,9 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
case Type_MultiPointer: case Type_MultiPointer:
return build_context.word_size; return build_context.word_size;
case Type_SoaPointer:
return build_context.word_size*2;
case Type_Array: { case Type_Array: {
i64 count, align, size, alignment; i64 count, align, size, alignment;
count = t->Array.count; count = t->Array.count;
@@ -4017,6 +4058,11 @@ gbString write_type_to_string(gbString str, Type *type, bool shorthand=false) {
str = write_type_to_string(str, type->Pointer.elem); str = write_type_to_string(str, type->Pointer.elem);
break; break;
case Type_SoaPointer:
str = gb_string_appendc(str, "#soa ^");
str = write_type_to_string(str, type->SoaPointer.elem);
break;
case Type_MultiPointer: case Type_MultiPointer:
str = gb_string_appendc(str, "[^]"); str = gb_string_appendc(str, "[^]");
str = write_type_to_string(str, type->Pointer.elem); str = write_type_to_string(str, type->Pointer.elem);