mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-22 21:54:59 -07:00
Relative pointers
This commit is contained in:
@@ -8,6 +8,7 @@ import "core:unicode/utf8"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
import "core:reflect"
|
||||
import "intrinsics"
|
||||
|
||||
|
||||
@private
|
||||
@@ -1712,6 +1713,117 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
|
||||
|
||||
case runtime.Type_Info_Opaque:
|
||||
fmt_opaque(fi, v);
|
||||
|
||||
case runtime.Type_Info_Relative_Pointer:
|
||||
ptr_any := any{v.data, info.base_integer.id};
|
||||
ptr: rawptr;
|
||||
switch i in &ptr_any {
|
||||
case u8: ptr = handle_relative_pointer(&i);
|
||||
case u16: ptr = handle_relative_pointer(&i);
|
||||
case u32: ptr = handle_relative_pointer(&i);
|
||||
case u64: ptr = handle_relative_pointer(&i);
|
||||
case i8: ptr = handle_relative_pointer(&i);
|
||||
case i16: ptr = handle_relative_pointer(&i);
|
||||
case i32: ptr = handle_relative_pointer(&i);
|
||||
case i64: ptr = handle_relative_pointer(&i);
|
||||
case u16le: ptr = handle_relative_pointer(&i);
|
||||
case u32le: ptr = handle_relative_pointer(&i);
|
||||
case u64le: ptr = handle_relative_pointer(&i);
|
||||
case i16le: ptr = handle_relative_pointer(&i);
|
||||
case i32le: ptr = handle_relative_pointer(&i);
|
||||
case i64le: ptr = handle_relative_pointer(&i);
|
||||
case u16be: ptr = handle_relative_pointer(&i);
|
||||
case u32be: ptr = handle_relative_pointer(&i);
|
||||
case u64be: ptr = handle_relative_pointer(&i);
|
||||
case i16be: ptr = handle_relative_pointer(&i);
|
||||
case i32be: ptr = handle_relative_pointer(&i);
|
||||
case i64be: ptr = handle_relative_pointer(&i);
|
||||
}
|
||||
absolute_ptr := any{ptr, info.pointer.id};
|
||||
|
||||
fmt_value(fi, absolute_ptr, verb);
|
||||
|
||||
case runtime.Type_Info_Relative_Slice:
|
||||
ptr_any := any{v.data, info.base_integer.id};
|
||||
ptr: rawptr;
|
||||
switch i in &ptr_any {
|
||||
case u8: ptr = handle_relative_pointer(&i);
|
||||
case u16: ptr = handle_relative_pointer(&i);
|
||||
case u32: ptr = handle_relative_pointer(&i);
|
||||
case u64: ptr = handle_relative_pointer(&i);
|
||||
case i8: ptr = handle_relative_pointer(&i);
|
||||
case i16: ptr = handle_relative_pointer(&i);
|
||||
case i32: ptr = handle_relative_pointer(&i);
|
||||
case i64: ptr = handle_relative_pointer(&i);
|
||||
case u16le: ptr = handle_relative_pointer(&i);
|
||||
case u32le: ptr = handle_relative_pointer(&i);
|
||||
case u64le: ptr = handle_relative_pointer(&i);
|
||||
case i16le: ptr = handle_relative_pointer(&i);
|
||||
case i32le: ptr = handle_relative_pointer(&i);
|
||||
case i64le: ptr = handle_relative_pointer(&i);
|
||||
case u16be: ptr = handle_relative_pointer(&i);
|
||||
case u32be: ptr = handle_relative_pointer(&i);
|
||||
case u64be: ptr = handle_relative_pointer(&i);
|
||||
case i16be: ptr = handle_relative_pointer(&i);
|
||||
case i32be: ptr = handle_relative_pointer(&i);
|
||||
case i64be: ptr = handle_relative_pointer(&i);
|
||||
}
|
||||
|
||||
if verb == 'p' {
|
||||
fmt_pointer(fi, ptr, 'p');
|
||||
} else if ptr == nil {
|
||||
strings.write_string(fi.buf, "[]");
|
||||
} else {
|
||||
len_ptr := uintptr(v.data) + uintptr(info.base_integer.size);
|
||||
len_any := any{rawptr(len_ptr), info.base_integer.id};
|
||||
len: int = 0;
|
||||
switch i in len_any {
|
||||
case u8: len = int(i);
|
||||
case u16: len = int(i);
|
||||
case u32: len = int(i);
|
||||
case u64: len = int(i);
|
||||
case i8: len = int(i);
|
||||
case i16: len = int(i);
|
||||
case i32: len = int(i);
|
||||
case i64: len = int(i);
|
||||
case u16le: len = int(i);
|
||||
case u32le: len = int(i);
|
||||
case u64le: len = int(i);
|
||||
case i16le: len = int(i);
|
||||
case i32le: len = int(i);
|
||||
case i64le: len = int(i);
|
||||
case u16be: len = int(i);
|
||||
case u32be: len = int(i);
|
||||
case u64be: len = int(i);
|
||||
case i16be: len = int(i);
|
||||
case i32be: len = int(i);
|
||||
case i64be: len = int(i);
|
||||
}
|
||||
|
||||
slice_type := reflect.type_info_base(info.slice).variant.(runtime.Type_Info_Slice);
|
||||
|
||||
strings.write_byte(fi.buf, '[');
|
||||
defer strings.write_byte(fi.buf, ']');
|
||||
|
||||
for i in 0..<len {
|
||||
if i > 0 do strings.write_string(fi.buf, ", ");
|
||||
|
||||
data := uintptr(ptr) + uintptr(i*slice_type.elem_size);
|
||||
fmt_arg(fi, any{rawptr(data), slice_type.elem.id}, verb);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handle_relative_pointer :: proc(ptr: ^$T) -> rawptr where intrinsics.type_is_integer(T) {
|
||||
if ptr^ == 0 {
|
||||
return nil;
|
||||
}
|
||||
when intrinsics.type_is_unsigned(T) {
|
||||
return rawptr(uintptr(ptr) + uintptr(ptr^));
|
||||
} else {
|
||||
return rawptr(uintptr(ptr) + uintptr(i64(ptr^)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ Type_Info_Bit_Field :: runtime.Type_Info_Bit_Field;
|
||||
Type_Info_Bit_Set :: runtime.Type_Info_Bit_Set;
|
||||
Type_Info_Opaque :: runtime.Type_Info_Opaque;
|
||||
Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector;
|
||||
Type_Info_Relative_Pointer :: runtime.Type_Info_Relative_Pointer;
|
||||
Type_Info_Relative_Slice :: runtime.Type_Info_Relative_Slice;
|
||||
|
||||
|
||||
Type_Kind :: enum {
|
||||
@@ -60,6 +62,8 @@ Type_Kind :: enum {
|
||||
Bit_Set,
|
||||
Opaque,
|
||||
Simd_Vector,
|
||||
Relative_Pointer,
|
||||
Relative_Slice,
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +96,8 @@ type_kind :: proc(T: typeid) -> Type_Kind {
|
||||
case Type_Info_Bit_Set: return .Bit_Set;
|
||||
case Type_Info_Opaque: return .Opaque;
|
||||
case Type_Info_Simd_Vector: return .Simd_Vector;
|
||||
case Type_Info_Relative_Pointer: return .Relative_Pointer;
|
||||
case Type_Info_Relative_Slice: return .Relative_Slice;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -184,6 +184,16 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
||||
y, ok := b.variant.(Type_Info_Simd_Vector);
|
||||
if !ok do return false;
|
||||
return x.count == y.count && x.elem == y.elem;
|
||||
|
||||
case Type_Info_Relative_Pointer:
|
||||
y, ok := b.variant.(Type_Info_Relative_Pointer);
|
||||
if !ok do return false;
|
||||
return x.base_integer == y.base_integer && x.pointer == y.pointer;
|
||||
|
||||
case Type_Info_Relative_Slice:
|
||||
y, ok := b.variant.(Type_Info_Relative_Slice);
|
||||
if !ok do return false;
|
||||
return x.base_integer == y.base_integer && x.slice == y.slice;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -322,6 +332,16 @@ is_simd_vector :: proc(info: ^Type_Info) -> bool {
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Simd_Vector);
|
||||
return ok;
|
||||
}
|
||||
is_relative_pointer :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Relative_Pointer);
|
||||
return ok;
|
||||
}
|
||||
is_relative_slice :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).variant.(Type_Info_Relative_Slice);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -567,6 +587,19 @@ write_type :: proc(buf: ^strings.Builder, ti: ^Type_Info) {
|
||||
write_byte(buf, ']');
|
||||
write_type(buf, info.elem);
|
||||
}
|
||||
|
||||
case Type_Info_Relative_Pointer:
|
||||
write_string(buf, "#relative(");
|
||||
write_type(buf, info.base_integer);
|
||||
write_string(buf, ") ");
|
||||
write_type(buf, info.pointer);
|
||||
|
||||
case Type_Info_Relative_Slice:
|
||||
write_string(buf, "#relative(");
|
||||
write_type(buf, info.base_integer);
|
||||
write_string(buf, ") ");
|
||||
write_type(buf, info.slice);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-1
@@ -143,7 +143,15 @@ Type_Info_Simd_Vector :: struct {
|
||||
elem_size: int,
|
||||
count: int,
|
||||
is_x86_mmx: bool,
|
||||
}
|
||||
};
|
||||
Type_Info_Relative_Pointer :: struct {
|
||||
pointer: ^Type_Info,
|
||||
base_integer: ^Type_Info,
|
||||
};
|
||||
Type_Info_Relative_Slice :: struct {
|
||||
slice: ^Type_Info,
|
||||
base_integer: ^Type_Info,
|
||||
};
|
||||
|
||||
Type_Info :: struct {
|
||||
size: int,
|
||||
@@ -176,6 +184,8 @@ Type_Info :: struct {
|
||||
Type_Info_Bit_Set,
|
||||
Type_Info_Opaque,
|
||||
Type_Info_Simd_Vector,
|
||||
Type_Info_Relative_Pointer,
|
||||
Type_Info_Relative_Slice,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -205,6 +215,9 @@ Typeid_Kind :: enum u8 {
|
||||
Bit_Field,
|
||||
Bit_Set,
|
||||
Opaque,
|
||||
Simd_Vector,
|
||||
Relative_Pointer,
|
||||
Relative_Slice,
|
||||
}
|
||||
#assert(len(Typeid_Kind) < 32);
|
||||
|
||||
|
||||
@@ -442,6 +442,18 @@ print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
|
||||
os.write_byte(fd, ']');
|
||||
print_type(fd, info.elem);
|
||||
}
|
||||
|
||||
case Type_Info_Relative_Pointer:
|
||||
os.write_string(fd, "#relative(");
|
||||
print_type(fd, info.base_integer);
|
||||
os.write_string(fd, ") ");
|
||||
print_type(fd, info.pointer);
|
||||
|
||||
case Type_Info_Relative_Slice:
|
||||
os.write_string(fd, "#relative(");
|
||||
print_type(fd, info.base_integer);
|
||||
os.write_string(fd, ") ");
|
||||
print_type(fd, info.slice);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
-3
@@ -599,6 +599,20 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
|
||||
}
|
||||
}
|
||||
|
||||
if (is_type_relative_pointer(dst)) {
|
||||
i64 score = check_distance_between_types(c, operand, dst->RelativePointer.pointer_type);
|
||||
if (score >= 0) {
|
||||
return score+2;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_type_relative_slice(dst)) {
|
||||
i64 score = check_distance_between_types(c, operand, dst->RelativeSlice.slice_type);
|
||||
if (score >= 0) {
|
||||
return score+2;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_type_proc(dst)) {
|
||||
if (are_types_identical(src, dst)) {
|
||||
return 3;
|
||||
@@ -3620,7 +3634,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
|
||||
case Entity_Constant:
|
||||
operand->value = entity->Constant.value;
|
||||
operand->mode = Addressing_Constant;
|
||||
if (operand->value.kind == ExactValue_Procedure) {
|
||||
if (operand->value.kind == ExactValue_Procedure) {
|
||||
Entity *proc = strip_entity_wrapping(operand->value.value_procedure);
|
||||
if (proc != nullptr) {
|
||||
operand->mode = Addressing_Value;
|
||||
@@ -5923,7 +5937,7 @@ bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count,
|
||||
|
||||
isize count = tuple->variables.count;
|
||||
tuple_index += add_dependencies_from_unpacking(c, lhs, lhs_count, tuple_index, count);
|
||||
|
||||
|
||||
add_type_and_value(c->info, val.expr, val.mode, val.type, val.value);
|
||||
} else {
|
||||
for_array(j, tuple->variables) {
|
||||
@@ -9205,7 +9219,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
o->mode = Addressing_Invalid;
|
||||
o->expr = node;
|
||||
return kind;
|
||||
}
|
||||
}
|
||||
|
||||
GB_ASSERT(e->identifier != nullptr);
|
||||
Ast *proc_ident = clone_ast(e->identifier);
|
||||
@@ -9480,6 +9494,22 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
if (t->kind == Type_Pointer && !is_type_empty_union(t->Pointer.elem)) {
|
||||
o->mode = Addressing_Variable;
|
||||
o->type = t->Pointer.elem;
|
||||
} else if (t->kind == Type_RelativePointer) {
|
||||
if (o->mode != Addressing_Variable) {
|
||||
gbString str = expr_to_string(o->expr);
|
||||
gbString typ = type_to_string(o->type);
|
||||
error(o->expr, "Cannot dereference relative pointer '%s' of type '%s' as it does not have a variable addressing mode", str, typ);
|
||||
gb_string_free(typ);
|
||||
gb_string_free(str);
|
||||
}
|
||||
|
||||
// NOTE(bill): This is required because when dereferencing, the original type has been lost
|
||||
add_type_info_type(c, o->type);
|
||||
|
||||
Type *ptr_type = base_type(t->RelativePointer.pointer_type);
|
||||
GB_ASSERT(ptr_type->kind == Type_Pointer);
|
||||
o->mode = Addressing_Variable;
|
||||
o->type = ptr_type->Pointer.elem;
|
||||
} else {
|
||||
gbString str = expr_to_string(o->expr);
|
||||
gbString typ = type_to_string(o->type);
|
||||
@@ -10001,6 +10031,12 @@ gbString write_expr_to_string(gbString str, Ast *node) {
|
||||
}
|
||||
str = gb_string_append_rune(str, '}');
|
||||
case_end;
|
||||
|
||||
case_ast_node(rt, RelativeType, node);
|
||||
str = write_expr_to_string(str, rt->tag);
|
||||
str = gb_string_appendc(str, "" );
|
||||
str = write_expr_to_string(str, rt->type);
|
||||
case_end;
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
+42
-2
@@ -329,7 +329,7 @@ void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, Type *named_t
|
||||
|
||||
auto *found_gen_types = map_get(&ctx->checker->info.gen_types, hash_pointer(original_type));
|
||||
if (found_gen_types) {
|
||||
array_add(found_gen_types, e);
|
||||
array_add(found_gen_types, e);
|
||||
} else {
|
||||
auto array = array_make<Entity *>(heap_allocator());
|
||||
array_add(&array, e);
|
||||
@@ -2501,7 +2501,7 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
|
||||
c->curr_proc_sig = type;
|
||||
c->in_proc_sig = true;
|
||||
|
||||
|
||||
|
||||
ProcCallingConvention cc = pt->calling_convention;
|
||||
if (cc == ProcCC_ForeignBlockDefault) {
|
||||
cc = ProcCC_CDecl;
|
||||
@@ -3284,6 +3284,46 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
|
||||
return true;
|
||||
case_end;
|
||||
|
||||
case_ast_node(rt, RelativeType, e);
|
||||
GB_ASSERT(rt->tag->kind == Ast_CallExpr);
|
||||
ast_node(ce, CallExpr, rt->tag);
|
||||
|
||||
Type *base_integer = nullptr;
|
||||
|
||||
if (ce->args.count != 1) {
|
||||
error(rt->type, "#relative expected 1 type argument, got %td", ce->args.count);
|
||||
} else {
|
||||
base_integer = check_type(ctx, ce->args[0]);
|
||||
if (!is_type_integer(base_integer)) {
|
||||
error(rt->type, "#relative base types must be an integer");
|
||||
base_integer = nullptr;
|
||||
} else if (type_size_of(base_integer) > 64) {
|
||||
error(rt->type, "#relative base integer types be less than or equal to 64-bits");
|
||||
base_integer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Type *relative_type = nullptr;
|
||||
Type *base_type = check_type(ctx, rt->type);
|
||||
if (!is_type_pointer(base_type) && !is_type_slice(base_type)) {
|
||||
error(rt->type, "#relative types can only be a pointer or slice");
|
||||
relative_type = base_type;
|
||||
} else if (base_integer == nullptr) {
|
||||
relative_type = base_type;
|
||||
} else {
|
||||
if (is_type_pointer(base_type)) {
|
||||
relative_type = alloc_type_relative_pointer(base_type, base_integer);
|
||||
} else if (is_type_slice(base_type)) {
|
||||
relative_type = alloc_type_relative_slice(base_type, base_integer);
|
||||
}
|
||||
}
|
||||
GB_ASSERT(relative_type != nullptr);
|
||||
|
||||
*type = relative_type;
|
||||
set_base_type(named_type, *type);
|
||||
return true;
|
||||
case_end;
|
||||
|
||||
case_ast_node(ot, OpaqueType, e);
|
||||
Type *elem = strip_opaque_type(check_type_expr(ctx, ot->type, nullptr));
|
||||
*type = alloc_type_opaque(elem);
|
||||
|
||||
@@ -1430,6 +1430,16 @@ void add_type_info_type(CheckerContext *c, Type *t) {
|
||||
add_type_info_type(c, bt->SimdVector.elem);
|
||||
break;
|
||||
|
||||
case Type_RelativePointer:
|
||||
add_type_info_type(c, bt->RelativePointer.pointer_type);
|
||||
add_type_info_type(c, bt->RelativePointer.base_integer);
|
||||
break;
|
||||
|
||||
case Type_RelativeSlice:
|
||||
add_type_info_type(c, bt->RelativeSlice.slice_type);
|
||||
add_type_info_type(c, bt->RelativeSlice.base_integer);
|
||||
break;
|
||||
|
||||
default:
|
||||
GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind);
|
||||
break;
|
||||
@@ -1626,6 +1636,16 @@ void add_min_dep_type_info(Checker *c, Type *t) {
|
||||
add_min_dep_type_info(c, bt->SimdVector.elem);
|
||||
break;
|
||||
|
||||
case Type_RelativePointer:
|
||||
add_min_dep_type_info(c, bt->RelativePointer.pointer_type);
|
||||
add_min_dep_type_info(c, bt->RelativePointer.base_integer);
|
||||
break;
|
||||
|
||||
case Type_RelativeSlice:
|
||||
add_min_dep_type_info(c, bt->RelativeSlice.slice_type);
|
||||
add_min_dep_type_info(c, bt->RelativeSlice.base_integer);
|
||||
break;
|
||||
|
||||
default:
|
||||
GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind]));
|
||||
break;
|
||||
@@ -2055,6 +2075,8 @@ void init_core_type_info(Checker *c) {
|
||||
t_type_info_bit_set = find_core_type(c, str_lit("Type_Info_Bit_Set"));
|
||||
t_type_info_opaque = find_core_type(c, str_lit("Type_Info_Opaque"));
|
||||
t_type_info_simd_vector = find_core_type(c, str_lit("Type_Info_Simd_Vector"));
|
||||
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_named_ptr = alloc_type_pointer(t_type_info_named);
|
||||
t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer);
|
||||
@@ -2081,6 +2103,8 @@ void init_core_type_info(Checker *c) {
|
||||
t_type_info_bit_set_ptr = alloc_type_pointer(t_type_info_bit_set);
|
||||
t_type_info_opaque_ptr = alloc_type_pointer(t_type_info_opaque);
|
||||
t_type_info_simd_vector_ptr = alloc_type_pointer(t_type_info_simd_vector);
|
||||
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);
|
||||
}
|
||||
|
||||
void init_mem_allocator(Checker *c) {
|
||||
|
||||
+3
-3
@@ -20,7 +20,7 @@ struct irModule {
|
||||
|
||||
PtrSet<Entity *> min_dep_set;
|
||||
Map<irValue *> values; // Key: Entity *
|
||||
StringMap<irValue *> members;
|
||||
StringMap<irValue *> members;
|
||||
Map<String> entity_names; // Key: Entity * of the typename
|
||||
Map<irDebugInfo *> debug_info; // Key: Unique pointer
|
||||
Map<irValue *> anonymous_proc_lits; // Key: Ast *
|
||||
@@ -7399,7 +7399,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
|
||||
// HACK TODO(bill): This is hack but it should be safe in virtually all cases
|
||||
irValue *v = ir_typeid(proc->module, tv.type);
|
||||
return ir_emit_conv(proc, v, t_typeid);
|
||||
}
|
||||
}
|
||||
|
||||
if (tv.value.kind != ExactValue_Invalid) {
|
||||
// NOTE(bill): Edge case
|
||||
@@ -11514,7 +11514,7 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
|
||||
case Basic_f64le:
|
||||
case Basic_f32be:
|
||||
case Basic_f64be:
|
||||
{
|
||||
{
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_float_ptr);
|
||||
|
||||
// NOTE(bill): This is matches the runtime layout
|
||||
|
||||
+152
-21
@@ -56,6 +56,10 @@ LLVMValueRef llvm_cstring(lbModule *m, String const &str) {
|
||||
|
||||
lbAddr lb_addr(lbValue addr) {
|
||||
lbAddr v = {lbAddr_Default, addr};
|
||||
if (is_type_relative_pointer(type_deref(addr.type))) {
|
||||
GB_ASSERT(is_type_pointer(addr.type));
|
||||
v.kind = lbAddr_RelativePointer;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -160,7 +164,29 @@ void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue value) {
|
||||
value.value = LLVMConstNull(lb_type(p->module, t));
|
||||
}
|
||||
|
||||
if (addr.kind == lbAddr_AtomOp_index_set) {
|
||||
if (addr.kind == lbAddr_RelativePointer) {
|
||||
Type *rel_ptr = base_type(lb_addr_type(addr));
|
||||
GB_ASSERT(rel_ptr->kind == Type_RelativePointer);
|
||||
|
||||
value = lb_emit_conv(p, value, rel_ptr->RelativePointer.pointer_type);
|
||||
|
||||
GB_ASSERT(is_type_pointer(addr.addr.type));
|
||||
lbValue ptr = lb_emit_conv(p, addr.addr, t_uintptr);
|
||||
lbValue val_ptr = lb_emit_conv(p, value, t_uintptr);
|
||||
lbValue offset = {};
|
||||
offset.value = LLVMBuildSub(p->builder, val_ptr.value, ptr.value, "");
|
||||
offset.type = t_uintptr;
|
||||
|
||||
if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) {
|
||||
offset = lb_emit_conv(p, offset, t_i64);
|
||||
}
|
||||
offset = lb_emit_conv(p, offset, rel_ptr->RelativePointer.base_integer);
|
||||
|
||||
lbValue offset_ptr = lb_emit_conv(p, addr.addr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer));
|
||||
LLVMBuildStore(p->builder, offset.value, offset_ptr.value);
|
||||
return;
|
||||
|
||||
} else if (addr.kind == lbAddr_AtomOp_index_set) {
|
||||
lbValue ptr = addr.addr;
|
||||
lbValue index = addr.index_set.index;
|
||||
Ast *node = addr.index_set.node;
|
||||
@@ -341,7 +367,34 @@ lbValue lb_emit_load(lbProcedure *p, lbValue value) {
|
||||
lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) {
|
||||
GB_ASSERT(addr.addr.value != nullptr);
|
||||
|
||||
if (addr.kind == lbAddr_Map) {
|
||||
|
||||
if (addr.kind == lbAddr_RelativePointer) {
|
||||
Type *rel_ptr = base_type(lb_addr_type(addr));
|
||||
GB_ASSERT(rel_ptr->kind == Type_RelativePointer);
|
||||
|
||||
lbValue ptr = lb_emit_conv(p, addr.addr, t_uintptr);
|
||||
lbValue offset = lb_emit_conv(p, ptr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer));
|
||||
offset = lb_emit_load(p, offset);
|
||||
|
||||
|
||||
if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) {
|
||||
offset = lb_emit_conv(p, offset, t_i64);
|
||||
}
|
||||
offset = lb_emit_conv(p, offset, t_uintptr);
|
||||
lbValue absolute_ptr = lb_emit_arith(p, Token_Add, ptr, offset, t_uintptr);
|
||||
absolute_ptr = lb_emit_conv(p, absolute_ptr, rel_ptr->RelativePointer.pointer_type);
|
||||
|
||||
lbValue cond = lb_emit_comp(p, Token_CmpEq, offset, lb_const_nil(p->module, rel_ptr->RelativePointer.base_integer));
|
||||
|
||||
// NOTE(bill): nil check
|
||||
lbValue nil_ptr = lb_const_nil(p->module, rel_ptr->RelativePointer.pointer_type);
|
||||
lbValue final_ptr = {};
|
||||
final_ptr.type = absolute_ptr.type;
|
||||
final_ptr.value = LLVMBuildSelect(p->builder, cond.value, nil_ptr.value, absolute_ptr.value, "");
|
||||
|
||||
return lb_emit_load(p, final_ptr);
|
||||
|
||||
} else if (addr.kind == lbAddr_Map) {
|
||||
Type *map_type = base_type(addr.map.type);
|
||||
lbAddr v = lb_add_local_generated(p, map_type->Map.lookup_result_type, true);
|
||||
lbValue h = lb_gen_map_header(p, addr.addr, map_type);
|
||||
@@ -1181,6 +1234,20 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
return LLVMX86MMXTypeInContext(ctx);
|
||||
}
|
||||
return LLVMVectorType(lb_type(m, type->SimdVector.elem), cast(unsigned)type->SimdVector.count);
|
||||
|
||||
case Type_RelativePointer:
|
||||
return lb_type_internal(m, type->RelativePointer.base_integer);
|
||||
|
||||
case Type_RelativeSlice:
|
||||
{
|
||||
LLVMTypeRef base_integer = lb_type_internal(m, type->RelativeSlice.base_integer);
|
||||
|
||||
unsigned field_count = 2;
|
||||
LLVMTypeRef *fields = gb_alloc_array(heap_allocator(), LLVMTypeRef, field_count);
|
||||
fields[0] = base_integer;
|
||||
fields[1] = base_integer;
|
||||
return LLVMStructTypeInContext(ctx, fields, field_count, false);
|
||||
}
|
||||
}
|
||||
|
||||
GB_PANIC("Invalid type %s", type_to_string(type));
|
||||
@@ -3970,7 +4037,7 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
|
||||
}
|
||||
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||
|
||||
|
||||
LLVMBuildRet(p->builder, res.value);
|
||||
}
|
||||
case_end;
|
||||
@@ -4323,19 +4390,23 @@ lbValue lb_typeid(lbModule *m, Type *type, Type *typeid_type) {
|
||||
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_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;
|
||||
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;
|
||||
case Type_Opaque: kind = Typeid_Opaque; break;
|
||||
case Type_SimdVector: kind = Typeid_Simd_Vector; break;
|
||||
case Type_RelativePointer: kind = Typeid_Relative_Pointer; break;
|
||||
case Type_RelativeSlice: kind = Typeid_Relative_Slice; break;
|
||||
}
|
||||
|
||||
if (is_type_cstring(type)) {
|
||||
@@ -4495,7 +4566,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value) {
|
||||
|
||||
res.value = LLVMConstArray(lb_type(m, elem), elems, cast(unsigned)count);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
switch (value.kind) {
|
||||
case ExactValue_Invalid:
|
||||
@@ -9723,6 +9794,10 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(de, DerefExpr, expr);
|
||||
if (is_type_relative_pointer(type_of_expr(de->expr))) {
|
||||
lbAddr addr = lb_build_addr(p, de->expr);
|
||||
return addr;
|
||||
}
|
||||
lbValue addr = lb_build_expr(p, de->expr);
|
||||
return lb_addr(addr);
|
||||
case_end;
|
||||
@@ -11192,6 +11267,36 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
|
||||
lb_emit_store(p, tag, res);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_RelativePointer:
|
||||
{
|
||||
tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_relative_pointer_ptr);
|
||||
LLVMValueRef vals[2] = {
|
||||
lb_get_type_info_ptr(m, t->RelativePointer.pointer_type).value,
|
||||
lb_get_type_info_ptr(m, t->RelativePointer.base_integer).value,
|
||||
};
|
||||
|
||||
lbValue res = {};
|
||||
res.type = type_deref(tag.type);
|
||||
res.value = LLVMConstNamedStruct(lb_type(m, res.type), vals, gb_count_of(vals));
|
||||
lb_emit_store(p, tag, res);
|
||||
}
|
||||
break;
|
||||
case Type_RelativeSlice:
|
||||
{
|
||||
tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_relative_slice_ptr);
|
||||
LLVMValueRef vals[2] = {
|
||||
lb_get_type_info_ptr(m, t->RelativeSlice.slice_type).value,
|
||||
lb_get_type_info_ptr(m, t->RelativeSlice.base_integer).value,
|
||||
};
|
||||
|
||||
lbValue res = {};
|
||||
res.type = type_deref(tag.type);
|
||||
res.value = LLVMConstNamedStruct(lb_type(m, res.type), vals, gb_count_of(vals));
|
||||
lb_emit_store(p, tag, res);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -11554,6 +11659,25 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
LLVMAddMergedLoadStoreMotionPass(default_function_pass_manager);
|
||||
LLVMAddPromoteMemoryToRegisterPass(default_function_pass_manager);
|
||||
// LLVMAddUnifyFunctionExitNodesPass(default_function_pass_manager);
|
||||
if (build_context.optimization_level >= 2) {
|
||||
LLVMAddAggressiveInstCombinerPass(default_function_pass_manager);
|
||||
LLVMAddEarlyCSEPass(default_function_pass_manager);
|
||||
LLVMAddEarlyCSEMemSSAPass(default_function_pass_manager);
|
||||
LLVMAddLowerExpectIntrinsicPass(default_function_pass_manager);
|
||||
|
||||
LLVMAddAlignmentFromAssumptionsPass(default_function_pass_manager);
|
||||
LLVMAddLoopRotatePass(default_function_pass_manager);
|
||||
LLVMAddDeadStoreEliminationPass(default_function_pass_manager);
|
||||
LLVMAddScalarizerPass(default_function_pass_manager);
|
||||
LLVMAddReassociatePass(default_function_pass_manager);
|
||||
LLVMAddAddDiscriminatorsPass(default_function_pass_manager);
|
||||
LLVMAddPromoteMemoryToRegisterPass(default_function_pass_manager);
|
||||
LLVMAddCorrelatedValuePropagationPass(default_function_pass_manager);
|
||||
|
||||
LLVMAddSLPVectorizePass(default_function_pass_manager);
|
||||
LLVMAddLoopVectorizePass(default_function_pass_manager);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
LLVMPassManagerRef default_function_pass_manager_without_memcpy = LLVMCreateFunctionPassManagerForModule(mod);
|
||||
@@ -11784,10 +11908,12 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
for_array(i, m->procedures_to_generate) {
|
||||
lbProcedure *p = m->procedures_to_generate[i];
|
||||
if (p->body != nullptr) { // Build Procedure
|
||||
if (p->flags & lbProcedureFlag_WithoutMemcpyPass) {
|
||||
LLVMRunFunctionPassManager(default_function_pass_manager_without_memcpy, p->value);
|
||||
} else {
|
||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
||||
for (i32 i = 0; i <= build_context.optimization_level; i++) {
|
||||
if (p->flags & lbProcedureFlag_WithoutMemcpyPass) {
|
||||
LLVMRunFunctionPassManager(default_function_pass_manager_without_memcpy, p->value);
|
||||
} else {
|
||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11799,7 +11925,12 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
defer (LLVMDisposePassManager(module_pass_manager));
|
||||
LLVMAddAlwaysInlinerPass(module_pass_manager);
|
||||
LLVMAddStripDeadPrototypesPass(module_pass_manager);
|
||||
// LLVMAddConstantMergePass(module_pass_manager);
|
||||
// if (build_context.optimization_level >= 2) {
|
||||
// LLVMAddArgumentPromotionPass(module_pass_manager);
|
||||
// LLVMAddConstantMergePass(module_pass_manager);
|
||||
// LLVMAddGlobalDCEPass(module_pass_manager);
|
||||
// LLVMAddDeadArgEliminationPass(module_pass_manager);
|
||||
// }
|
||||
|
||||
LLVMPassManagerBuilderRef pass_manager_builder = LLVMPassManagerBuilderCreate();
|
||||
defer (LLVMPassManagerBuilderDispose(pass_manager_builder));
|
||||
|
||||
@@ -28,6 +28,8 @@ enum lbAddrKind {
|
||||
lbAddr_Context,
|
||||
lbAddr_SoaVariable,
|
||||
|
||||
lbAddr_RelativePointer,
|
||||
|
||||
lbAddr_AtomOp_index_set,
|
||||
};
|
||||
|
||||
@@ -68,11 +70,11 @@ struct lbModule {
|
||||
Map<LLVMTypeRef> types; // Key: Type *
|
||||
|
||||
Map<lbValue> values; // Key: Entity *
|
||||
StringMap<lbValue> members;
|
||||
StringMap<lbProcedure *> procedures;
|
||||
StringMap<lbValue> members;
|
||||
StringMap<lbProcedure *> procedures;
|
||||
Map<Entity *> procedure_values; // Key: LLVMValueRef
|
||||
|
||||
StringMap<LLVMValueRef> const_strings;
|
||||
StringMap<LLVMValueRef> const_strings;
|
||||
|
||||
Map<lbProcedure *> anonymous_proc_lits; // Key: Ast *
|
||||
|
||||
|
||||
+16
-1
@@ -87,6 +87,7 @@ Token ast_token(Ast *node) {
|
||||
case Ast_OpaqueType: return node->OpaqueType.token;
|
||||
case Ast_PolyType: return node->PolyType.token;
|
||||
case Ast_ProcType: return node->ProcType.token;
|
||||
case Ast_RelativeType: return ast_token(node->RelativeType.tag);
|
||||
case Ast_PointerType: return node->PointerType.token;
|
||||
case Ast_ArrayType: return node->ArrayType.token;
|
||||
case Ast_DynamicArrayType: return node->DynamicArrayType.token;
|
||||
@@ -343,6 +344,10 @@ Ast *clone_ast(Ast *node) {
|
||||
n->ProcType.params = clone_ast(n->ProcType.params);
|
||||
n->ProcType.results = clone_ast(n->ProcType.results);
|
||||
break;
|
||||
case Ast_RelativeType:
|
||||
n->RelativeType.tag = clone_ast(n->RelativeType.tag);
|
||||
n->RelativeType.type = clone_ast(n->RelativeType.type);
|
||||
break;
|
||||
case Ast_PointerType:
|
||||
n->PointerType.type = clone_ast(n->PointerType.type);
|
||||
break;
|
||||
@@ -922,7 +927,12 @@ Ast *ast_proc_type(AstFile *f, Token token, Ast *params, Ast *results, u64 tags,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Ast *ast_relative_type(AstFile *f, Ast *tag, Ast *type) {
|
||||
Ast *result = alloc_ast_node(f, Ast_RelativeType);
|
||||
result->RelativeType.tag = tag;
|
||||
result->RelativeType.type = type;
|
||||
return result;
|
||||
}
|
||||
Ast *ast_pointer_type(AstFile *f, Token token, Ast *type) {
|
||||
Ast *result = alloc_ast_node(f, Ast_PointerType);
|
||||
result->PointerType.token = token;
|
||||
@@ -1825,6 +1835,11 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
|
||||
}
|
||||
return operand;
|
||||
} else if (name.string == "relative") {
|
||||
Ast *tag = ast_basic_directive(f, token, name.string);
|
||||
tag = parse_call_expr(f, tag);
|
||||
Ast *type = parse_type(f);
|
||||
return ast_relative_type(f, tag, type);
|
||||
} else {
|
||||
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
|
||||
}
|
||||
|
||||
@@ -497,6 +497,10 @@ AST_KIND(_TypeBegin, "", bool) \
|
||||
Token token; \
|
||||
Ast *type; \
|
||||
}) \
|
||||
AST_KIND(RelativeType, "relative type", struct { \
|
||||
Ast *tag; \
|
||||
Ast *type; \
|
||||
}) \
|
||||
AST_KIND(ArrayType, "array type", struct { \
|
||||
Token token; \
|
||||
Ast *count; \
|
||||
|
||||
+72
-6
@@ -126,7 +126,7 @@ enum StructSoaKind {
|
||||
|
||||
enum TypeAtomOpKind {
|
||||
TypeAtomOp_Invalid,
|
||||
|
||||
|
||||
TypeAtomOp_index_get,
|
||||
TypeAtomOp_index_set,
|
||||
TypeAtomOp_slice,
|
||||
@@ -151,7 +151,7 @@ struct TypeStruct {
|
||||
|
||||
i64 custom_align;
|
||||
Entity * names;
|
||||
|
||||
|
||||
TypeAtomOpTable *atom_op_table;
|
||||
|
||||
Type * soa_elem;
|
||||
@@ -290,8 +290,14 @@ struct TypeProc {
|
||||
Type *elem; \
|
||||
bool is_x86_mmx; \
|
||||
}) \
|
||||
|
||||
|
||||
TYPE_KIND(RelativePointer, struct { \
|
||||
Type *pointer_type; \
|
||||
Type *base_integer; \
|
||||
}) \
|
||||
TYPE_KIND(RelativeSlice, struct { \
|
||||
Type *slice_type; \
|
||||
Type *base_integer; \
|
||||
})
|
||||
|
||||
|
||||
enum TypeKind {
|
||||
@@ -358,6 +364,10 @@ enum Typeid_Kind : u8 {
|
||||
Typeid_Map,
|
||||
Typeid_Bit_Field,
|
||||
Typeid_Bit_Set,
|
||||
Typeid_Opaque,
|
||||
Typeid_Simd_Vector,
|
||||
Typeid_Relative_Pointer,
|
||||
Typeid_Relative_Slice,
|
||||
};
|
||||
|
||||
|
||||
@@ -611,6 +621,8 @@ gb_global Type *t_type_info_bit_field = nullptr;
|
||||
gb_global Type *t_type_info_bit_set = nullptr;
|
||||
gb_global Type *t_type_info_opaque = nullptr;
|
||||
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_slice = nullptr;
|
||||
|
||||
gb_global Type *t_type_info_named_ptr = nullptr;
|
||||
gb_global Type *t_type_info_integer_ptr = nullptr;
|
||||
@@ -637,6 +649,8 @@ gb_global Type *t_type_info_bit_field_ptr = nullptr;
|
||||
gb_global Type *t_type_info_bit_set_ptr = nullptr;
|
||||
gb_global Type *t_type_info_opaque_ptr = nullptr;
|
||||
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_slice_ptr = nullptr;
|
||||
|
||||
gb_global Type *t_allocator = nullptr;
|
||||
gb_global Type *t_allocator_ptr = nullptr;
|
||||
@@ -661,6 +675,9 @@ void init_map_internal_types(Type *type);
|
||||
Type * bit_set_to_int(Type *t);
|
||||
bool are_types_identical(Type *x, Type *y);
|
||||
|
||||
bool is_type_pointer(Type *t);
|
||||
bool is_type_slice(Type *t);
|
||||
bool is_type_integer(Type *t);
|
||||
|
||||
bool type_ptr_set_exists(PtrSet<Type *> *s, Type *t) {
|
||||
if (ptr_set_exists(s, t)) {
|
||||
@@ -837,9 +854,23 @@ Type *alloc_type_enum() {
|
||||
return t;
|
||||
}
|
||||
|
||||
Type *alloc_type_relative_pointer(Type *pointer_type, Type *base_integer) {
|
||||
GB_ASSERT(is_type_pointer(pointer_type));
|
||||
GB_ASSERT(is_type_integer(base_integer));
|
||||
Type *t = alloc_type(Type_RelativePointer);
|
||||
t->RelativePointer.pointer_type = pointer_type;
|
||||
t->RelativePointer.base_integer = base_integer;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Type *alloc_type_relative_slice(Type *slice_type, Type *base_integer) {
|
||||
GB_ASSERT(is_type_slice(slice_type));
|
||||
GB_ASSERT(is_type_integer(base_integer));
|
||||
Type *t = alloc_type(Type_RelativeSlice);
|
||||
t->RelativeSlice.slice_type = slice_type;
|
||||
t->RelativeSlice.base_integer = base_integer;
|
||||
return t;
|
||||
}
|
||||
|
||||
Type *alloc_type_named(String name, Type *base, Entity *type_name) {
|
||||
Type *t = alloc_type(Type_Named);
|
||||
@@ -1197,6 +1228,14 @@ bool is_type_generic(Type *t) {
|
||||
return t->kind == Type_Generic;
|
||||
}
|
||||
|
||||
bool is_type_relative_pointer(Type *t) {
|
||||
t = base_type(t);
|
||||
return t->kind == Type_RelativePointer;
|
||||
}
|
||||
bool is_type_relative_slice(Type *t) {
|
||||
t = base_type(t);
|
||||
return t->kind == Type_RelativeSlice;
|
||||
}
|
||||
|
||||
|
||||
Type *core_array_type(Type *t) {
|
||||
@@ -1756,6 +1795,10 @@ bool type_has_nil(Type *t) {
|
||||
return false;
|
||||
case Type_Opaque:
|
||||
return true;
|
||||
|
||||
case Type_RelativePointer:
|
||||
case Type_RelativeSlice:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2865,6 +2908,11 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
// IMPORTANT TODO(bill): Figure out the alignment of vector types
|
||||
return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.max_align);
|
||||
}
|
||||
|
||||
case Type_RelativePointer:
|
||||
return type_align_of_internal(t->RelativePointer.base_integer, path);
|
||||
case Type_RelativeSlice:
|
||||
return type_align_of_internal(t->RelativeSlice.base_integer, path);
|
||||
}
|
||||
|
||||
// return gb_clamp(next_pow2(type_size_of(t)), 1, build_context.max_align);
|
||||
@@ -3138,6 +3186,11 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
|
||||
Type *elem = t->SimdVector.elem;
|
||||
return count * type_size_of_internal(elem, path);
|
||||
}
|
||||
|
||||
case Type_RelativePointer:
|
||||
return type_size_of_internal(t->RelativePointer.base_integer, path);
|
||||
case Type_RelativeSlice:
|
||||
return 2*type_size_of_internal(t->RelativeSlice.base_integer, path);
|
||||
}
|
||||
|
||||
// Catch all
|
||||
@@ -3536,6 +3589,19 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
str = write_type_to_string(str, type->SimdVector.elem);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_RelativePointer:
|
||||
str = gb_string_append_fmt(str, "#relative(");
|
||||
str = write_type_to_string(str, type->RelativePointer.base_integer);
|
||||
str = gb_string_append_fmt(str, ") ");
|
||||
str = write_type_to_string(str, type->RelativePointer.pointer_type);
|
||||
break;
|
||||
case Type_RelativeSlice:
|
||||
str = gb_string_append_fmt(str, "#relative(");
|
||||
str = write_type_to_string(str, type->RelativeSlice.base_integer);
|
||||
str = gb_string_append_fmt(str, ") ");
|
||||
str = write_type_to_string(str, type->RelativeSlice.slice_type);
|
||||
break;
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
Reference in New Issue
Block a user