Browse Source

Remove #relative slices; Replace with #relative multi-pointers

gingerBill 2 years ago
parent
commit
c91898a888

+ 1 - 1
core/encoding/json/marshal.odin

@@ -207,7 +207,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
 	case runtime.Type_Info_Relative_Pointer:
 		return .Unsupported_Type
 
-	case runtime.Type_Info_Relative_Slice:
+	case runtime.Type_Info_Relative_Multi_Pointer:
 		return .Unsupported_Type
 		
 	case runtime.Type_Info_Matrix:

+ 3 - 24
core/fmt/fmt.odin

@@ -2535,32 +2535,11 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 
 		fmt_value(fi, absolute_ptr, verb)
 
-	case runtime.Type_Info_Relative_Slice:
+	case runtime.Type_Info_Relative_Multi_Pointer:
 		ptr := reflect.relative_pointer_to_absolute_raw(v.data, info.base_integer.id)
+		absolute_ptr := any{ptr, info.pointer.id}
 
-		if verb == 'p' {
-			fmt_pointer(fi, ptr, 'p')
-		} else if ptr == nil {
-			io.write_string(fi.writer, "[]", &fi.n)
-		} else {
-			len_ptr := uintptr(v.data) + uintptr(info.base_integer.size)
-			len_any := any{rawptr(len_ptr), info.base_integer.id}
-			len, _ := reflect.as_int(len_any)
-			slice_type := reflect.type_info_base(info.slice).variant.(runtime.Type_Info_Slice)
-
-			fi.record_level += 1
-			defer fi.record_level -= 1
-
-			io.write_byte(fi.writer, '[', &fi.n)
-			defer io.write_byte(fi.writer, ']', &fi.n)
-
-			for i in 0..<len {
-				if i > 0 { io.write_string(fi.writer, ", ", &fi.n) }
-
-				data := uintptr(ptr) + uintptr(i*slice_type.elem_size)
-				fmt_arg(fi, any{rawptr(data), slice_type.elem.id}, verb)
-			}
-		}
+		fmt_value(fi, absolute_ptr, verb)
 
 	case runtime.Type_Info_Matrix:
 		fmt_matrix(fi, v, verb, info)

+ 25 - 25
core/odin/doc-format/doc_format.odin

@@ -162,31 +162,31 @@ Attribute :: struct {
 }
 
 Type_Kind :: enum u32le {
-	Invalid            = 0,
-	Basic              = 1,
-	Named              = 2,
-	Generic            = 3,
-	Pointer            = 4,
-	Array              = 5,
-	Enumerated_Array   = 6,
-	Slice              = 7,
-	Dynamic_Array      = 8,
-	Map                = 9,
-	Struct             = 10,
-	Union              = 11,
-	Enum               = 12,
-	Tuple              = 13,
-	Proc               = 14,
-	Bit_Set            = 15,
-	Simd_Vector        = 16,
-	SOA_Struct_Fixed   = 17,
-	SOA_Struct_Slice   = 18,
-	SOA_Struct_Dynamic = 19,
-	Relative_Pointer   = 20,
-	Relative_Slice     = 21,
-	Multi_Pointer      = 22,
-	Matrix             = 23,
-	Soa_Pointer        = 24,
+	Invalid                = 0,
+	Basic                  = 1,
+	Named                  = 2,
+	Generic                = 3,
+	Pointer                = 4,
+	Array                  = 5,
+	Enumerated_Array       = 6,
+	Slice                  = 7,
+	Dynamic_Array          = 8,
+	Map                    = 9,
+	Struct                 = 10,
+	Union                  = 11,
+	Enum                   = 12,
+	Tuple                  = 13,
+	Proc                   = 14,
+	Bit_Set                = 15,
+	Simd_Vector            = 16,
+	SOA_Struct_Fixed       = 17,
+	SOA_Struct_Slice       = 18,
+	SOA_Struct_Dynamic     = 19,
+	Relative_Pointer       = 20,
+	Relative_Multi_Pointer = 21,
+	Multi_Pointer          = 22,
+	Matrix                 = 23,
+	Soa_Pointer            = 24,
 }
 
 Type_Elems_Cap :: 4

+ 59 - 60
core/reflect/reflect.odin

@@ -8,35 +8,35 @@ _ :: intrinsics
 
 Type_Info :: runtime.Type_Info
 
-Type_Info_Named            :: runtime.Type_Info_Named
-Type_Info_Integer          :: runtime.Type_Info_Integer
-Type_Info_Rune             :: runtime.Type_Info_Rune
-Type_Info_Float            :: runtime.Type_Info_Float
-Type_Info_Complex          :: runtime.Type_Info_Complex
-Type_Info_Quaternion       :: runtime.Type_Info_Quaternion
-Type_Info_String           :: runtime.Type_Info_String
-Type_Info_Boolean          :: runtime.Type_Info_Boolean
-Type_Info_Any              :: runtime.Type_Info_Any
-Type_Info_Type_Id          :: runtime.Type_Info_Type_Id
-Type_Info_Pointer          :: runtime.Type_Info_Pointer
-Type_Info_Multi_Pointer    :: runtime.Type_Info_Multi_Pointer
-Type_Info_Procedure        :: runtime.Type_Info_Procedure
-Type_Info_Array            :: runtime.Type_Info_Array
-Type_Info_Enumerated_Array :: runtime.Type_Info_Enumerated_Array
-Type_Info_Dynamic_Array    :: runtime.Type_Info_Dynamic_Array
-Type_Info_Slice            :: runtime.Type_Info_Slice
-Type_Info_Parameters       :: runtime.Type_Info_Parameters
-Type_Info_Tuple            :: runtime.Type_Info_Parameters
-Type_Info_Struct           :: runtime.Type_Info_Struct
-Type_Info_Union            :: runtime.Type_Info_Union
-Type_Info_Enum             :: runtime.Type_Info_Enum
-Type_Info_Map              :: runtime.Type_Info_Map
-Type_Info_Bit_Set          :: runtime.Type_Info_Bit_Set
-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_Info_Matrix           :: runtime.Type_Info_Matrix
-Type_Info_Soa_Pointer      :: runtime.Type_Info_Soa_Pointer
+Type_Info_Named                  :: runtime.Type_Info_Named
+Type_Info_Integer                :: runtime.Type_Info_Integer
+Type_Info_Rune                   :: runtime.Type_Info_Rune
+Type_Info_Float                  :: runtime.Type_Info_Float
+Type_Info_Complex                :: runtime.Type_Info_Complex
+Type_Info_Quaternion             :: runtime.Type_Info_Quaternion
+Type_Info_String                 :: runtime.Type_Info_String
+Type_Info_Boolean                :: runtime.Type_Info_Boolean
+Type_Info_Any                    :: runtime.Type_Info_Any
+Type_Info_Type_Id                :: runtime.Type_Info_Type_Id
+Type_Info_Pointer                :: runtime.Type_Info_Pointer
+Type_Info_Multi_Pointer          :: runtime.Type_Info_Multi_Pointer
+Type_Info_Procedure              :: runtime.Type_Info_Procedure
+Type_Info_Array                  :: runtime.Type_Info_Array
+Type_Info_Enumerated_Array       :: runtime.Type_Info_Enumerated_Array
+Type_Info_Dynamic_Array          :: runtime.Type_Info_Dynamic_Array
+Type_Info_Slice                  :: runtime.Type_Info_Slice
+Type_Info_Parameters             :: runtime.Type_Info_Parameters
+Type_Info_Tuple                  :: runtime.Type_Info_Parameters
+Type_Info_Struct                 :: runtime.Type_Info_Struct
+Type_Info_Union                  :: runtime.Type_Info_Union
+Type_Info_Enum                   :: runtime.Type_Info_Enum
+Type_Info_Map                    :: runtime.Type_Info_Map
+Type_Info_Bit_Set                :: runtime.Type_Info_Bit_Set
+Type_Info_Simd_Vector            :: runtime.Type_Info_Simd_Vector
+Type_Info_Relative_Pointer       :: runtime.Type_Info_Relative_Pointer
+Type_Info_Relative_Multi_Pointer :: runtime.Type_Info_Relative_Multi_Pointer
+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
 
@@ -69,7 +69,7 @@ Type_Kind :: enum {
 	Bit_Set,
 	Simd_Vector,
 	Relative_Pointer,
-	Relative_Slice,
+	Relative_Multi_Pointer,
 	Matrix,
 	Soa_Pointer,
 }
@@ -80,34 +80,34 @@ type_kind :: proc(T: typeid) -> Type_Kind {
 	ti := type_info_of(T)
 	if ti != nil {
 		switch _ in ti.variant {
-		case Type_Info_Named:            return .Named
-		case Type_Info_Integer:          return .Integer
-		case Type_Info_Rune:             return .Rune
-		case Type_Info_Float:            return .Float
-		case Type_Info_Complex:          return .Complex
-		case Type_Info_Quaternion:       return .Quaternion
-		case Type_Info_String:           return .String
-		case Type_Info_Boolean:          return .Boolean
-		case Type_Info_Any:              return .Any
-		case Type_Info_Type_Id:          return .Type_Id
-		case Type_Info_Pointer:          return .Pointer
-		case Type_Info_Multi_Pointer:    return .Multi_Pointer
-		case Type_Info_Procedure:        return .Procedure
-		case Type_Info_Array:            return .Array
-		case Type_Info_Enumerated_Array: return .Enumerated_Array
-		case Type_Info_Dynamic_Array:    return .Dynamic_Array
-		case Type_Info_Slice:            return .Slice
-		case Type_Info_Parameters:       return .Tuple
-		case Type_Info_Struct:           return .Struct
-		case Type_Info_Union:            return .Union
-		case Type_Info_Enum:             return .Enum
-		case Type_Info_Map:              return .Map
-		case Type_Info_Bit_Set:          return .Bit_Set
-		case Type_Info_Simd_Vector:      return .Simd_Vector
-		case Type_Info_Relative_Pointer: return .Relative_Pointer
-		case Type_Info_Relative_Slice:   return .Relative_Slice
-		case Type_Info_Matrix:           return .Matrix
-		case Type_Info_Soa_Pointer:      return .Soa_Pointer
+		case Type_Info_Named:                  return .Named
+		case Type_Info_Integer:                return .Integer
+		case Type_Info_Rune:                   return .Rune
+		case Type_Info_Float:                  return .Float
+		case Type_Info_Complex:                return .Complex
+		case Type_Info_Quaternion:             return .Quaternion
+		case Type_Info_String:                 return .String
+		case Type_Info_Boolean:                return .Boolean
+		case Type_Info_Any:                    return .Any
+		case Type_Info_Type_Id:                return .Type_Id
+		case Type_Info_Pointer:                return .Pointer
+		case Type_Info_Multi_Pointer:          return .Multi_Pointer
+		case Type_Info_Procedure:              return .Procedure
+		case Type_Info_Array:                  return .Array
+		case Type_Info_Enumerated_Array:       return .Enumerated_Array
+		case Type_Info_Dynamic_Array:          return .Dynamic_Array
+		case Type_Info_Slice:                  return .Slice
+		case Type_Info_Parameters:             return .Tuple
+		case Type_Info_Struct:                 return .Struct
+		case Type_Info_Union:                  return .Union
+		case Type_Info_Enum:                   return .Enum
+		case Type_Info_Map:                    return .Map
+		case Type_Info_Bit_Set:                return .Bit_Set
+		case Type_Info_Simd_Vector:            return .Simd_Vector
+		case Type_Info_Relative_Pointer:       return .Relative_Pointer
+		case Type_Info_Relative_Multi_Pointer: return .Relative_Multi_Pointer
+		case Type_Info_Matrix:                 return .Matrix
+		case Type_Info_Soa_Pointer:            return .Soa_Pointer
 		}
 
 	}
@@ -1457,8 +1457,6 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
 		return equal(va, vb, including_indirect_array_recursion, recursion_level+1) 
 	case Type_Info_Map:
 		return false
-	case Type_Info_Relative_Slice:
-		return false
 	case 
 		Type_Info_Boolean,
 		Type_Info_Integer, 
@@ -1474,6 +1472,7 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
 		Type_Info_Enum,
 		Type_Info_Simd_Vector,
 		Type_Info_Relative_Pointer,
+		Type_Info_Relative_Multi_Pointer,
 		Type_Info_Soa_Pointer,
 		Type_Info_Matrix:
 		return runtime.memory_compare(a.data, b.data, t.size) == 0

+ 7 - 8
core/reflect/types.odin

@@ -165,9 +165,9 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
 		y := b.variant.(Type_Info_Relative_Pointer) or_return
 		return x.base_integer == y.base_integer && x.pointer == y.pointer
 
-	case Type_Info_Relative_Slice:
-		y := b.variant.(Type_Info_Relative_Slice) or_return
-		return x.base_integer == y.base_integer && x.slice == y.slice
+	case Type_Info_Relative_Multi_Pointer:
+		y := b.variant.(Type_Info_Relative_Multi_Pointer) or_return
+		return x.base_integer == y.base_integer && x.pointer == y.pointer
 		
 	case Type_Info_Matrix:
 		y := b.variant.(Type_Info_Matrix) or_return
@@ -383,9 +383,9 @@ is_relative_pointer :: proc(info: ^Type_Info) -> bool {
 	return ok
 }
 @(require_results)
-is_relative_slice :: proc(info: ^Type_Info) -> bool {
+is_relative_multi_pointer :: proc(info: ^Type_Info) -> bool {
 	if info == nil { return false }
-	_, ok := type_info_base(info).variant.(Type_Info_Relative_Slice)
+	_, ok := type_info_base(info).variant.(Type_Info_Relative_Multi_Pointer)
 	return ok
 }
 
@@ -395,7 +395,6 @@ is_relative_slice :: proc(info: ^Type_Info) -> bool {
 
 
 
-
 write_typeid_builder :: proc(buf: ^strings.Builder, id: typeid, n_written: ^int = nil) -> (n: int, err: io.Error) {
 	return write_type_writer(strings.to_writer(buf), type_info_of(id))
 }
@@ -652,11 +651,11 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
 		io.write_string(w, ") ",         &n) or_return
 		write_type(w, info.pointer,      &n) or_return
 
-	case Type_Info_Relative_Slice:
+	case Type_Info_Relative_Multi_Pointer:
 		io.write_string(w, "#relative(", &n) or_return
 		write_type(w, info.base_integer, &n) or_return
 		io.write_string(w, ") ",         &n) or_return
-		write_type(w, info.slice,        &n) or_return
+		write_type(w, info.pointer,      &n) or_return
 		
 	case Type_Info_Matrix:
 		io.write_string(w, "matrix[",               &n) or_return

+ 5 - 5
core/runtime/core.odin

@@ -162,11 +162,11 @@ Type_Info_Simd_Vector :: struct {
 	count:      int,
 }
 Type_Info_Relative_Pointer :: struct {
-	pointer:      ^Type_Info,
+	pointer:      ^Type_Info, // ^T
 	base_integer: ^Type_Info,
 }
-Type_Info_Relative_Slice :: struct {
-	slice:        ^Type_Info,
+Type_Info_Relative_Multi_Pointer :: struct {
+	pointer:      ^Type_Info, // [^]T
 	base_integer: ^Type_Info,
 }
 Type_Info_Matrix :: struct {
@@ -219,7 +219,7 @@ Type_Info :: struct {
 		Type_Info_Bit_Set,
 		Type_Info_Simd_Vector,
 		Type_Info_Relative_Pointer,
-		Type_Info_Relative_Slice,
+		Type_Info_Relative_Multi_Pointer,
 		Type_Info_Matrix,
 		Type_Info_Soa_Pointer,
 	},
@@ -252,7 +252,7 @@ Typeid_Kind :: enum u8 {
 	Bit_Set,
 	Simd_Vector,
 	Relative_Pointer,
-	Relative_Slice,
+	Relative_Multi_Pointer,
 	Matrix,
 }
 #assert(len(Typeid_Kind) < 32)

+ 2 - 2
core/runtime/print.odin

@@ -471,11 +471,11 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
 		print_string(") ")
 		print_type(info.pointer)
 
-	case Type_Info_Relative_Slice:
+	case Type_Info_Relative_Multi_Pointer:
 		print_string("#relative(")
 		print_type(info.base_integer)
 		print_string(") ")
-		print_type(info.slice)
+		print_type(info.pointer)
 		
 	case Type_Info_Matrix:
 		print_string("matrix[")

+ 1 - 1
src/check_builtin.cpp

@@ -1748,7 +1748,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
 			mode = Addressing_Constant;
 			value = exact_value_i64(at->EnumeratedArray.count);
 			type = t_untyped_integer;
-		} else if ((is_type_slice(op_type) || is_type_relative_slice(op_type)) && id == BuiltinProc_len) {
+		} else if (is_type_slice(op_type) && id == BuiltinProc_len) {
 			mode = Addressing_Value;
 		} else if (is_type_dynamic_array(op_type)) {
 			mode = Addressing_Value;

+ 23 - 20
src/check_expr.cpp

@@ -856,8 +856,8 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
 		}
 	}
 
-	if (is_type_relative_slice(dst)) {
-		i64 score = check_distance_between_types(c, operand, dst->RelativeSlice.slice_type);
+	if (is_type_relative_multi_pointer(dst)) {
+		i64 score = check_distance_between_types(c, operand, dst->RelativeMultiPointer.pointer_type);
 		if (score >= 0) {
 			return score+2;
 		}
@@ -1005,8 +1005,8 @@ gb_internal AstPackage *get_package_of_type(Type *type) {
 		case Type_RelativePointer:
 			type = type->RelativePointer.pointer_type;
 			continue;
-		case Type_RelativeSlice:
-			type = type->RelativeSlice.slice_type;
+		case Type_RelativeMultiPointer:
+			type = type->RelativeMultiPointer.pointer_type;
 			continue;
 		}
 		return nullptr;
@@ -7366,11 +7366,11 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64
 		}
 		return true;
 
-	case Type_RelativeSlice:
+	case Type_RelativeMultiPointer:
 		{
-			Type *slice_type = base_type(t->RelativeSlice.slice_type);
-			GB_ASSERT(slice_type->kind == Type_Slice);
-			o->type = slice_type->Slice.elem;
+			Type *pointer_type = base_type(t->RelativeMultiPointer.pointer_type);
+			GB_ASSERT(pointer_type->kind == Type_MultiPointer);
+			o->type = pointer_type->MultiPointer.elem;
 			if (o->mode != Addressing_Constant) {
 				o->mode = Addressing_Variable;
 			}
@@ -9502,14 +9502,14 @@ gb_internal ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node,
 
 	if (is_const) {
 		if (is_type_array(t)) {
-			// OKay
+			// Okay
 		} else if (is_type_slice(t)) {
 			// Okay
 		} else if (is_type_enumerated_array(t)) {
 			// Okay
 		} else if (is_type_string(t)) {
 			// Okay
-		} else if (is_type_relative_slice(t)) {
+		} else if (is_type_relative_multi_pointer(t)) {
 			// Okay
 		} else if (is_type_matrix(t)) {
 			// Okay
@@ -9647,17 +9647,9 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node,
 		}
 		break;
 
-	case Type_RelativeSlice:
+	case Type_RelativeMultiPointer:
 		valid = true;
-		o->type = t->RelativeSlice.slice_type;
-		if (o->mode != Addressing_Variable) {
-			gbString str = expr_to_string(node);
-			error(node, "Cannot relative slice '%s', as value is not addressable", str);
-			gb_string_free(str);
-			o->mode = Addressing_Invalid;
-			o->expr = node;
-			return kind;
-		}
+		o->type = type_deref(o->type);
 		break;
 
 	case Type_EnumeratedArray:
@@ -9736,8 +9728,19 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node,
 			x[i:n] -> []T
 		*/
 		o->type = alloc_type_slice(t->MultiPointer.elem);
+	} else if (t->kind == Type_RelativeMultiPointer && se->high != nullptr) {
+		/*
+			x[:]   -> [^]T
+			x[i:]  -> [^]T
+			x[:n]  -> []T
+			x[i:n] -> []T
+		*/
+		Type *pointer_type = base_type(t->RelativeMultiPointer.pointer_type);
+		GB_ASSERT(pointer_type->kind == Type_MultiPointer);
+		o->type = alloc_type_slice(pointer_type->MultiPointer.elem);
 	}
 
+
 	o->mode = Addressing_Value;
 
 	if (is_type_string(t) && max_count >= 0) {

+ 4 - 4
src/check_type.cpp

@@ -2778,16 +2778,16 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
 
 		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");
+		if (!is_type_pointer(base_type) && !is_type_multi_pointer(base_type)) {
+			error(rt->type, "#relative types can only be a pointer or multi-pointer");
 			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);
+			} else if (is_type_multi_pointer(base_type)) {
+				relative_type = alloc_type_relative_multi_pointer(base_type, base_integer);
 			}
 		}
 		GB_ASSERT(relative_type != nullptr);

+ 8 - 8
src/checker.cpp

@@ -1969,9 +1969,9 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) {
 		add_type_info_type_internal(c, bt->RelativePointer.base_integer);
 		break;
 
-	case Type_RelativeSlice:
-		add_type_info_type_internal(c, bt->RelativeSlice.slice_type);
-		add_type_info_type_internal(c, bt->RelativeSlice.base_integer);
+	case Type_RelativeMultiPointer:
+		add_type_info_type_internal(c, bt->RelativeMultiPointer.pointer_type);
+		add_type_info_type_internal(c, bt->RelativeMultiPointer.base_integer);
 		break;
 
 	case Type_Matrix:
@@ -2210,9 +2210,9 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) {
 		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);
+	case Type_RelativeMultiPointer:
+		add_min_dep_type_info(c, bt->RelativeMultiPointer.pointer_type);
+		add_min_dep_type_info(c, bt->RelativeMultiPointer.base_integer);
 		break;
 
 	case Type_Matrix:
@@ -2800,7 +2800,7 @@ gb_internal 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_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_relative_multi_pointer = find_core_type(c, str_lit("Type_Info_Relative_Multi_Pointer"));
 	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"));
 
@@ -2829,7 +2829,7 @@ gb_internal void init_core_type_info(Checker *c) {
 	t_type_info_bit_set_ptr          = alloc_type_pointer(t_type_info_bit_set);
 	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);
+	t_type_info_relative_multi_pointer_ptr = alloc_type_pointer(t_type_info_relative_multi_pointer);
 	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);
 }

+ 25 - 25
src/docs_format.cpp

@@ -59,31 +59,31 @@ struct OdinDocPosition {
 };
 
 enum OdinDocTypeKind : u32 {
-	OdinDocType_Invalid          = 0,
-	OdinDocType_Basic            = 1,
-	OdinDocType_Named            = 2,
-	OdinDocType_Generic          = 3,
-	OdinDocType_Pointer          = 4,
-	OdinDocType_Array            = 5,
-	OdinDocType_EnumeratedArray  = 6,
-	OdinDocType_Slice            = 7,
-	OdinDocType_DynamicArray     = 8,
-	OdinDocType_Map              = 9,
-	OdinDocType_Struct           = 10,
-	OdinDocType_Union            = 11,
-	OdinDocType_Enum             = 12,
-	OdinDocType_Tuple            = 13,
-	OdinDocType_Proc             = 14,
-	OdinDocType_BitSet           = 15,
-	OdinDocType_SimdVector       = 16,
-	OdinDocType_SOAStructFixed   = 17,
-	OdinDocType_SOAStructSlice   = 18,
-	OdinDocType_SOAStructDynamic = 19,
-	OdinDocType_RelativePointer  = 20,
-	OdinDocType_RelativeSlice    = 21,
-	OdinDocType_MultiPointer     = 22,
-	OdinDocType_Matrix           = 23,
-	OdinDocType_SoaPointer       = 24,
+	OdinDocType_Invalid              = 0,
+	OdinDocType_Basic                = 1,
+	OdinDocType_Named                = 2,
+	OdinDocType_Generic              = 3,
+	OdinDocType_Pointer              = 4,
+	OdinDocType_Array                = 5,
+	OdinDocType_EnumeratedArray      = 6,
+	OdinDocType_Slice                = 7,
+	OdinDocType_DynamicArray         = 8,
+	OdinDocType_Map                  = 9,
+	OdinDocType_Struct               = 10,
+	OdinDocType_Union                = 11,
+	OdinDocType_Enum                 = 12,
+	OdinDocType_Tuple                = 13,
+	OdinDocType_Proc                 = 14,
+	OdinDocType_BitSet               = 15,
+	OdinDocType_SimdVector           = 16,
+	OdinDocType_SOAStructFixed       = 17,
+	OdinDocType_SOAStructSlice       = 18,
+	OdinDocType_SOAStructDynamic     = 19,
+	OdinDocType_RelativePointer      = 20,
+	OdinDocType_RelativeMultiPointer = 21,
+	OdinDocType_MultiPointer         = 22,
+	OdinDocType_Matrix               = 23,
+	OdinDocType_SoaPointer           = 24,
 };
 
 enum OdinDocTypeFlag_Basic : u32 {

+ 4 - 4
src/docs_writer.cpp

@@ -771,12 +771,12 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) {
 			doc_type.types = odin_write_slice(w, types, gb_count_of(types));
 		}
 		break;
-	case Type_RelativeSlice:
-		doc_type.kind = OdinDocType_RelativeSlice;
+	case Type_RelativeMultiPointer:
+		doc_type.kind = OdinDocType_RelativeMultiPointer;
 		{
 			OdinDocTypeIndex types[2] = {};
-			types[0] = odin_doc_type(w, type->RelativeSlice.slice_type);
-			types[1] = odin_doc_type(w, type->RelativeSlice.base_integer);
+			types[0] = odin_doc_type(w, type->RelativeMultiPointer.pointer_type);
+			types[1] = odin_doc_type(w, type->RelativeMultiPointer.base_integer);
 			doc_type.types = odin_write_slice(w, types, gb_count_of(types));
 		}
 		break;

+ 2 - 2
src/error.cpp

@@ -411,7 +411,7 @@ gb_internal void error_line_va(char const *fmt, va_list va) {
 
 gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_list va) {
 	mutex_lock(&global_error_collector.mutex);
-	global_error_collector.count++;
+	global_error_collector.count.fetch_add(1);
 	// NOTE(bill): Duplicate error, skip it
 	if (pos.line == 0) {
 		error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
@@ -425,7 +425,7 @@ gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_li
 		error_out_va(fmt, va);
 	}
 	mutex_unlock(&global_error_collector.mutex);
-	if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) {
+	if (global_error_collector.count.load() > MAX_ERROR_COLLECTOR_COUNT()) {
 		gb_exit(1);
 	}
 }

+ 0 - 1
src/llvm_backend.hpp

@@ -69,7 +69,6 @@ enum lbAddrKind {
 	lbAddr_SoaVariable,
 
 	lbAddr_RelativePointer,
-	lbAddr_RelativeSlice,
 
 	lbAddr_Swizzle,
 	lbAddr_SwizzleLarge,

+ 5 - 12
src/llvm_backend_debug.cpp

@@ -442,19 +442,12 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
 		gbString name = type_to_string(type, temporary_allocator());
 		return LLVMDIBuilderCreateTypedef(m->debug_builder, base_integer, name, gb_string_length(name), nullptr, 0, nullptr, cast(u32)(8*type_align_of(type)));
 	}
+	case Type_RelativeMultiPointer: {
+		LLVMMetadataRef base_integer = lb_debug_type(m, type->RelativeMultiPointer.base_integer);
+		gbString name = type_to_string(type, temporary_allocator());
+		return LLVMDIBuilderCreateTypedef(m->debug_builder, base_integer, name, gb_string_length(name), nullptr, 0, nullptr, cast(u32)(8*type_align_of(type)));
+	}
 
-	case Type_RelativeSlice:
-		{
-			unsigned element_count = 0;
-			LLVMMetadataRef elements[2] = {};
-			Type *base_integer = type->RelativeSlice.base_integer;
-			unsigned base_bits = cast(unsigned)(8*type_size_of(base_integer));
-			elements[0] = lb_debug_struct_field(m, str_lit("data_offset"), base_integer, 0);
-			elements[1] = lb_debug_struct_field(m, str_lit("len"), base_integer, base_bits);
-			gbString name = type_to_string(type, temporary_allocator());
-			return LLVMDIBuilderCreateStructType(m->debug_builder, nullptr, name, gb_string_length(name), nullptr, 0, 2*base_bits, base_bits, LLVMDIFlagZero, nullptr, elements, element_count, 0, nullptr, "", 0);
-		}
-		
 	case Type_Matrix: {
 		LLVMMetadataRef subscripts[1] = {};
 		subscripts[0] = LLVMDIBuilderGetOrCreateSubrange(m->debug_builder,

+ 24 - 15
src/llvm_backend_expr.cpp

@@ -2863,7 +2863,6 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
 	ast_node(ue, UnaryExpr, expr);
 	auto tv = type_and_value_of_expr(expr);
 
-
 	Ast *ue_expr = unparen_expr(ue->expr);
 	if (ue_expr->kind == Ast_IndexExpr && tv.mode == Addressing_OptionalOkPtr && is_type_tuple(tv.type)) {
 		Type *tuple = tv.type;
@@ -3803,25 +3802,32 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) {
 		lbValue v = {};
 
 		LLVMValueRef indices[1] = {index.value};
-		v.value = LLVMBuildGEP2(p->builder, lb_type(p->module, t->MultiPointer.elem), multi_ptr.value, indices, 1, "foo");
+		v.value = LLVMBuildGEP2(p->builder, lb_type(p->module, t->MultiPointer.elem), multi_ptr.value, indices, 1, "");
 		v.type = alloc_type_pointer(t->MultiPointer.elem);
 		return lb_addr(v);
 	}
 
-	case Type_RelativeSlice: {
-		lbAddr slice_addr = {};
+	case Type_RelativeMultiPointer: {
+		lbAddr rel_ptr_addr = {};
 		if (deref) {
-			slice_addr = lb_addr(lb_build_expr(p, ie->expr));
+			lbValue rel_ptr_ptr = lb_build_expr(p, ie->expr);
+			rel_ptr_addr = lb_addr(rel_ptr_ptr);
 		} else {
-			slice_addr = lb_build_addr(p, ie->expr);
+			rel_ptr_addr = lb_build_addr(p, ie->expr);
 		}
-		lbValue slice = lb_addr_load(p, slice_addr);
+		lbValue rel_ptr = lb_relative_pointer_to_pointer(p, rel_ptr_addr);
 
-		lbValue elem = lb_slice_elem(p, slice);
-		lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
-		lbValue len = lb_slice_len(p, slice);
-		lb_emit_bounds_check(p, ast_token(ie->index), index, len);
-		lbValue v = lb_emit_ptr_offset(p, elem, index);
+		lbValue index = lb_build_expr(p, ie->index);
+		index = lb_emit_conv(p, index, t_int);
+		lbValue v = {};
+
+		Type *pointer_type = base_type(t->RelativeMultiPointer.pointer_type);
+		GB_ASSERT(pointer_type->kind == Type_MultiPointer);
+		Type *elem = pointer_type->MultiPointer.elem;
+
+		LLVMValueRef indices[1] = {index.value};
+		v.value = LLVMBuildGEP2(p->builder, lb_type(p->module, elem), rel_ptr.value, indices, 1, "");
+		v.type = alloc_type_pointer(elem);
 		return lb_addr(v);
 	}
 
@@ -3925,8 +3931,11 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) {
 		return slice;
 	}
 
-	case Type_RelativeSlice:
-		GB_PANIC("TODO(bill): Type_RelativeSlice should be handled above already on the lb_addr_load");
+	case Type_RelativePointer:
+		GB_PANIC("TODO(bill): Type_RelativePointer should be handled above already on the lb_addr_load");
+		break;
+	case Type_RelativeMultiPointer:
+		GB_PANIC("TODO(bill): Type_RelativeMultiPointer should be handled above already on the lb_addr_load");
 		break;
 
 	case Type_DynamicArray: {
@@ -3996,7 +4005,7 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) {
 	}
 
 	case Type_Basic: {
-		GB_ASSERT(type == t_string);
+		GB_ASSERT_MSG(type == t_string, "got %s", type_to_string(type));
 		lbValue len = lb_string_len(p, base);
 		if (high.value == nullptr) high = len;
 

+ 85 - 118
src/llvm_backend_general.cpp

@@ -349,9 +349,10 @@ gb_internal lbAddr lb_addr(lbValue addr) {
 	if (addr.type != nullptr && is_type_relative_pointer(type_deref(addr.type))) {
 		GB_ASSERT(is_type_pointer(addr.type));
 		v.kind = lbAddr_RelativePointer;
-	} else if (addr.type != nullptr && is_type_relative_slice(type_deref(addr.type))) {
-		GB_ASSERT(is_type_pointer(addr.type));
-		v.kind = lbAddr_RelativeSlice;
+	} else if (addr.type != nullptr && is_type_relative_multi_pointer(type_deref(addr.type))) {
+		GB_ASSERT(is_type_pointer(addr.type) ||
+		          is_type_multi_pointer(addr.type));
+		v.kind = lbAddr_RelativePointer;
 	}
 	return v;
 }
@@ -424,6 +425,43 @@ gb_internal Type *lb_addr_type(lbAddr const &addr) {
 	return type_deref(addr.addr.type);
 }
 
+
+gb_internal lbValue lb_relative_pointer_to_pointer(lbProcedure *p, lbAddr const &addr) {
+	GB_ASSERT(addr.kind == lbAddr_RelativePointer);
+
+	Type *t = base_type(lb_addr_type(addr));
+	GB_ASSERT(is_type_relative_pointer(t) || is_type_relative_multi_pointer(t));
+
+	Type *pointer_type = nullptr;
+	Type *base_integer = nullptr;
+	if (t->kind == Type_RelativePointer) {
+		pointer_type = t->RelativePointer.pointer_type;
+		base_integer = t->RelativePointer.base_integer;
+	} else if (t->kind == Type_RelativeMultiPointer) {
+		pointer_type = t->RelativeMultiPointer.pointer_type;
+		base_integer = t->RelativeMultiPointer.base_integer;
+	}
+
+	lbValue ptr = lb_emit_conv(p, addr.addr, t_uintptr);
+	lbValue offset = lb_emit_conv(p, ptr, alloc_type_pointer(base_integer));
+	offset = lb_emit_load(p, offset);
+
+	if (!is_type_unsigned(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, pointer_type);
+
+	lbValue cond = lb_emit_comp(p, Token_CmpEq, offset, lb_const_nil(p->module, base_integer));
+
+	// NOTE(bill): nil check
+	lbValue nil_ptr = lb_const_nil(p->module, pointer_type);
+	lbValue final_ptr = lb_emit_select(p, cond, nil_ptr, absolute_ptr);
+	return final_ptr;
+}
+
+
 gb_internal lbValue lb_addr_get_ptr(lbProcedure *p, lbAddr const &addr) {
 	if (addr.addr.value == nullptr) {
 		GB_PANIC("Illegal addr -> nullptr");
@@ -434,28 +472,8 @@ gb_internal lbValue lb_addr_get_ptr(lbProcedure *p, lbAddr const &addr) {
 	case lbAddr_Map:
 		return lb_internal_dynamic_map_get_ptr(p, addr.addr, addr.map.key);
 
-	case 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 = lb_emit_select(p, cond, nil_ptr, absolute_ptr);
-		return final_ptr;
-	}
+	case lbAddr_RelativePointer:
+		return lb_relative_pointer_to_pointer(p, addr);
 
 	case lbAddr_SoaVariable:
 		// TODO(bill): FIX THIS HACK
@@ -477,6 +495,9 @@ gb_internal lbValue lb_addr_get_ptr(lbProcedure *p, lbAddr const &addr) {
 
 gb_internal lbValue lb_build_addr_ptr(lbProcedure *p, Ast *expr) {
 	lbAddr addr = lb_build_addr(p, expr);
+	if (addr.kind == lbAddr_RelativePointer) {
+		return addr.addr;
+	}
 	return lb_addr_get_ptr(p, addr);
 }
 
@@ -685,9 +706,20 @@ gb_internal void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) {
 
 	if (addr.kind == lbAddr_RelativePointer) {
 		Type *rel_ptr = base_type(lb_addr_type(addr));
-		GB_ASSERT(rel_ptr->kind == Type_RelativePointer);
+		GB_ASSERT(rel_ptr->kind == Type_RelativePointer ||
+		          rel_ptr->kind == Type_RelativeMultiPointer);
+		Type *pointer_type = nullptr;
+		Type *base_integer = nullptr;
 
-		value = lb_emit_conv(p, value, rel_ptr->RelativePointer.pointer_type);
+		if (rel_ptr->kind == Type_RelativePointer) {
+			pointer_type = rel_ptr->RelativePointer.pointer_type;
+			base_integer = rel_ptr->RelativePointer.base_integer;
+		} else if (rel_ptr->kind == Type_RelativeMultiPointer) {
+			pointer_type = rel_ptr->RelativeMultiPointer.pointer_type;
+			base_integer = rel_ptr->RelativeMultiPointer.base_integer;
+		}
+
+		value = lb_emit_conv(p, value, pointer_type);
 
 		GB_ASSERT(is_type_pointer(addr.addr.type));
 		lbValue ptr = lb_emit_conv(p, addr.addr, t_uintptr);
@@ -696,54 +728,20 @@ gb_internal void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) {
 		offset.value = LLVMBuildSub(p->builder, val_ptr.value, ptr.value, "");
 		offset.type = t_uintptr;
 
-		if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) {
+		if (!is_type_unsigned(base_integer)) {
 			offset = lb_emit_conv(p, offset, t_i64);
 		}
-		offset = lb_emit_conv(p, offset, rel_ptr->RelativePointer.base_integer);
+		offset = lb_emit_conv(p, offset, base_integer);
 
-		lbValue offset_ptr = lb_emit_conv(p, addr.addr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer));
+		lbValue offset_ptr = lb_emit_conv(p, addr.addr, alloc_type_pointer(base_integer));
 		offset = lb_emit_select(p,
 			lb_emit_comp(p, Token_CmpEq, val_ptr, lb_const_nil(p->module, t_uintptr)),
-			lb_const_nil(p->module, rel_ptr->RelativePointer.base_integer),
+			lb_const_nil(p->module, base_integer),
 			offset
 		);
 		LLVMBuildStore(p->builder, offset.value, offset_ptr.value);
 		return;
 
-	} else if (addr.kind == lbAddr_RelativeSlice) {
-		Type *rel_ptr = base_type(lb_addr_type(addr));
-		GB_ASSERT(rel_ptr->kind == Type_RelativeSlice);
-
-		value = lb_emit_conv(p, value, rel_ptr->RelativeSlice.slice_type);
-
-		GB_ASSERT(is_type_pointer(addr.addr.type));
-		lbValue ptr = lb_emit_conv(p, lb_emit_struct_ep(p, addr.addr, 0), t_uintptr);
-		lbValue val_ptr = lb_emit_conv(p, lb_slice_elem(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));
-		offset = lb_emit_select(p,
-			lb_emit_comp(p, Token_CmpEq, val_ptr, lb_const_nil(p->module, t_uintptr)),
-			lb_const_nil(p->module, rel_ptr->RelativePointer.base_integer),
-			offset
-		);
-		LLVMBuildStore(p->builder, offset.value, offset_ptr.value);
-
-		lbValue len = lb_slice_len(p, value);
-		len = lb_emit_conv(p, len, rel_ptr->RelativePointer.base_integer);
-
-		lbValue len_ptr = lb_emit_struct_ep(p, addr.addr, 1);
-		LLVMBuildStore(p->builder, len.value, len_ptr.value);
-
-		return;
 	} else if (addr.kind == lbAddr_Map) {
 		lb_internal_dynamic_map_set(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt);
 		return;
@@ -1020,67 +1018,43 @@ gb_internal lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) {
 
 	if (addr.kind == lbAddr_RelativePointer) {
 		Type *rel_ptr = base_type(lb_addr_type(addr));
-		GB_ASSERT(rel_ptr->kind == Type_RelativePointer);
+		Type *base_integer = nullptr;
+		Type *pointer_type = nullptr;
+		GB_ASSERT(rel_ptr->kind == Type_RelativePointer ||
+		          rel_ptr->kind == Type_RelativeMultiPointer);
+
+		if (rel_ptr->kind == Type_RelativePointer) {
+			base_integer = rel_ptr->RelativePointer.base_integer;
+			pointer_type = rel_ptr->RelativePointer.pointer_type;
+		} else if (rel_ptr->kind == Type_RelativeMultiPointer) {
+			base_integer = rel_ptr->RelativeMultiPointer.base_integer;
+			pointer_type = rel_ptr->RelativeMultiPointer.pointer_type;
+		}
 
 		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));
+		lbValue offset = lb_emit_conv(p, ptr, alloc_type_pointer(base_integer));
 		offset = lb_emit_load(p, offset);
 
 
-		if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) {
+		if (!is_type_unsigned(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);
+		absolute_ptr = lb_emit_conv(p, absolute_ptr, pointer_type);
 
-		lbValue cond = lb_emit_comp(p, Token_CmpEq, offset, lb_const_nil(p->module, rel_ptr->RelativePointer.base_integer));
+		lbValue cond = lb_emit_comp(p, Token_CmpEq, offset, lb_const_nil(p->module, base_integer));
 
 		// NOTE(bill): nil check
-		lbValue nil_ptr = lb_const_nil(p->module, rel_ptr->RelativePointer.pointer_type);
+		lbValue nil_ptr = lb_const_nil(p->module, 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_RelativeSlice) {
-		Type *rel_ptr = base_type(lb_addr_type(addr));
-		GB_ASSERT(rel_ptr->kind == Type_RelativeSlice);
-
-		lbValue offset_ptr = lb_emit_struct_ep(p, addr.addr, 0);
-		lbValue ptr = lb_emit_conv(p, offset_ptr, t_uintptr);
-		lbValue offset = lb_emit_load(p, offset_ptr);
-
-
-		if (!is_type_unsigned(rel_ptr->RelativeSlice.base_integer)) {
-			offset = lb_emit_conv(p, offset, t_i64);
+		if (rel_ptr->kind == Type_RelativeMultiPointer) {
+			return final_ptr;
 		}
-		offset = lb_emit_conv(p, offset, t_uintptr);
-		lbValue absolute_ptr = lb_emit_arith(p, Token_Add, ptr, offset, t_uintptr);
-
-		Type *slice_type = base_type(rel_ptr->RelativeSlice.slice_type);
-		GB_ASSERT(rel_ptr->RelativeSlice.slice_type->kind == Type_Slice);
-		Type *slice_elem = slice_type->Slice.elem;
-		Type *slice_elem_ptr = alloc_type_pointer(slice_elem);
-
-		absolute_ptr = lb_emit_conv(p, absolute_ptr, slice_elem_ptr);
-
-		lbValue cond = lb_emit_comp(p, Token_CmpEq, offset, lb_const_nil(p->module, rel_ptr->RelativeSlice.base_integer));
-
-		// NOTE(bill): nil check
-		lbValue nil_ptr = lb_const_nil(p->module, slice_elem_ptr);
-		lbValue data = {};
-		data.type = absolute_ptr.type;
-		data.value = LLVMBuildSelect(p->builder, cond.value, nil_ptr.value, absolute_ptr.value, "");
-
-		lbValue len = lb_emit_load(p, lb_emit_struct_ep(p, addr.addr, 1));
-		len = lb_emit_conv(p, len, t_int);
-
-		lbAddr slice = lb_add_local_generated(p, slice_type, false);
-		lb_fill_slice(p, slice, data, len);
-		return lb_addr_load(p, slice);
-
+		return lb_emit_load(p, final_ptr);
 
 	} else if (addr.kind == lbAddr_Map) {
 		Type *map_type = base_type(type_deref(addr.addr.type));
@@ -2139,17 +2113,10 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
 
 	case Type_RelativePointer:
 		return lb_type_internal(m, type->RelativePointer.base_integer);
+	case Type_RelativeMultiPointer:
+		return lb_type_internal(m, type->RelativeMultiPointer.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(permanent_allocator(), LLVMTypeRef, field_count);
-			fields[0] = base_integer;
-			fields[1] = base_integer;
-			return LLVMStructTypeInContext(ctx, fields, field_count, false);
-		}
 		
 	case Type_Matrix:
 		{

+ 2 - 2
src/llvm_backend_proc.cpp

@@ -1710,7 +1710,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
 			return lb_string_len(p, v);
 		} else if (is_type_array(t)) {
 			GB_PANIC("Array lengths are constant");
-		} else if (is_type_slice(t) || is_type_relative_slice(t)) {
+		} else if (is_type_slice(t)) {
 			return lb_slice_len(p, v);
 		} else if (is_type_dynamic_array(t)) {
 			return lb_dynamic_array_len(p, v);
@@ -1735,7 +1735,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
 			GB_PANIC("Unreachable");
 		} else if (is_type_array(t)) {
 			GB_PANIC("Array lengths are constant");
-		} else if (is_type_slice(t) || is_type_relative_slice(t)) {
+		} else if (is_type_slice(t)) {
 			return lb_slice_len(p, v);
 		} else if (is_type_dynamic_array(t)) {
 			return lb_dynamic_array_cap(p, v);

+ 7 - 5
src/llvm_backend_type.cpp

@@ -57,7 +57,7 @@ gb_internal lbValue lb_typeid(lbModule *m, Type *type) {
 	case Type_BitSet:          kind = Typeid_Bit_Set;          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;
+	case Type_RelativeMultiPointer: kind = Typeid_Relative_Multi_Pointer; break;
 	case Type_SoaPointer:      kind = Typeid_SoaPointer;       break;
 	}
 
@@ -857,12 +857,13 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup
 				lb_emit_store(p, tag, res);
 			}
 			break;
-		case Type_RelativeSlice:
+
+		case Type_RelativeMultiPointer:
 			{
-				tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_relative_slice_ptr);
+				tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_relative_multi_pointer_ptr);
 				LLVMValueRef vals[2] = {
-					lb_type_info(m, t->RelativeSlice.slice_type).value,
-					lb_type_info(m, t->RelativeSlice.base_integer).value,
+					lb_type_info(m, t->RelativeMultiPointer.pointer_type).value,
+					lb_type_info(m, t->RelativeMultiPointer.base_integer).value,
 				};
 
 				lbValue res = {};
@@ -871,6 +872,7 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup
 				lb_emit_store(p, tag, res);
 			}
 			break;
+
 		case Type_Matrix: 
 			{
 				tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_matrix_ptr);

+ 1 - 6
src/llvm_backend_utility.cpp

@@ -1124,11 +1124,6 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
 		}
 	} else if (is_type_array(t)) {
 		return lb_emit_array_epi(p, s, index);
-	} else if (is_type_relative_slice(t)) {
-		switch (index) {
-		case 0: 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;
@@ -1547,7 +1542,7 @@ gb_internal lbValue lb_slice_elem(lbProcedure *p, lbValue slice) {
 	return lb_emit_struct_ev(p, slice, 0);
 }
 gb_internal lbValue lb_slice_len(lbProcedure *p, lbValue slice) {
-	GB_ASSERT(is_type_slice(slice.type) || is_type_relative_slice(slice.type));
+	GB_ASSERT(is_type_slice(slice.type));
 	return lb_emit_struct_ev(p, slice, 1);
 }
 gb_internal lbValue lb_dynamic_array_elem(lbProcedure *p, lbValue da) {

+ 5 - 1
src/parser.cpp

@@ -2235,7 +2235,11 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
 			return parse_check_directive_for_statement(operand, name, StateFlag_no_type_assert);
 		} else if (name.string == "relative") {
 			Ast *tag = ast_basic_directive(f, token, name);
-			tag = parse_call_expr(f, tag);
+			if (f->curr_token.kind != Token_OpenParen) {
+				syntax_error(tag, "expected #relative(<integer type>) <type>");
+			} else {
+				tag = parse_call_expr(f, tag);
+			}
 			Ast *type = parse_type(f);
 			return ast_relative_type(f, tag, type);
 		} else if (name.string == "force_inline" ||

+ 0 - 4
src/tilde_builtin.cpp

@@ -44,8 +44,6 @@ gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value) {
 	case Type_Struct:
 		GB_ASSERT(is_type_soa_struct(t));
 		break;
-	case Type_RelativeSlice:
-		break;
 	}
 
 	GB_PANIC("TODO(bill): cg_builtin_len %s", type_to_string(t));
@@ -106,8 +104,6 @@ gb_internal cgValue cg_builtin_cap(cgProcedure *p, cgValue value) {
 	case Type_Struct:
 		GB_ASSERT(is_type_soa_struct(t));
 		break;
-	case Type_RelativeSlice:
-		break;
 	}
 
 	GB_PANIC("TODO(bill): cg_builtin_cap %s", type_to_string(t));

+ 3 - 3
src/tilde_const.cpp

@@ -255,9 +255,9 @@ gb_internal i64 cg_global_const_calculate_region_count_from_basic_type(Type *typ
 		return 1;
 
 	case Type_RelativePointer:
-		return 1;
-	case Type_RelativeSlice:
-		return 1; // technically 1
+	case Type_RelativeMultiPointer:
+		return 2; // allows for offsets
+
 	case Type_Matrix:
 		return 1;
 

+ 2 - 14
src/tilde_debug.cpp

@@ -457,20 +457,8 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) {
 		return tb_debug_create_array(m->mod, cg_debug_type(m, type->SimdVector.elem), type->SimdVector.count);
 	case Type_RelativePointer:
 		return cg_debug_type(m, type->RelativePointer.base_integer);
-	case Type_RelativeSlice:
-		{
-			String name = {};
-			TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text);
-
-			TB_DebugType *base_integer = cg_debug_type(m, type->RelativeSlice.base_integer);
-			TB_CharUnits bi_size = cast(TB_CharUnits)type_size_of(type->RelativeSlice.base_integer);
-			TB_DebugType **fields = tb_debug_record_begin(record, 2);
-			fields[0] = tb_debug_create_field(m->mod, base_integer, -1, "data", 0*bi_size);
-			fields[1] = tb_debug_create_field(m->mod, base_integer, -1, "len",  1*bi_size);
-
-			tb_debug_record_end(record, size, align);
-			return record;
-		}
+	case Type_RelativeMultiPointer:
+		return cg_debug_type(m, type->RelativeMultiPointer.base_integer);
 	case Type_Matrix:
 		{
 			i64 count = matrix_type_total_internal_elems(type);

+ 14 - 18
src/tilde_expr.cpp

@@ -1469,8 +1469,8 @@ gb_internal cgAddr cg_build_addr_slice_expr(cgProcedure *p, Ast *expr) {
 		return slice;
 	}
 
-	case Type_RelativeSlice:
-		GB_PANIC("TODO(bill): Type_RelativeSlice should be handled above already on the cg_addr_load");
+	case Type_RelativeMultiPointer:
+		GB_PANIC("TODO(bill): Type_RelativeMultiPointer should be handled above already on the cg_addr_load");
 		break;
 
 	case Type_DynamicArray: {
@@ -3598,22 +3598,18 @@ gb_internal cgAddr cg_build_addr_index_expr(cgProcedure *p, Ast *expr) {
 		return cg_addr(v);
 	}
 
-	case Type_RelativeSlice: {
-		GB_PANIC("TODO(bill): relative slice");
-		// lbAddr slice_addr = {};
-		// if (deref) {
-		// 	slice_addr = lb_addr(lb_build_expr(p, ie->expr));
-		// } else {
-		// 	slice_addr = lb_build_addr(p, ie->expr);
-		// }
-		// lbValue slice = lb_addr_load(p, slice_addr);
-
-		// lbValue elem = lb_slice_elem(p, slice);
-		// lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
-		// lbValue len = lb_slice_len(p, slice);
-		// lb_emit_bounds_check(p, ast_token(ie->index), index, len);
-		// lbValue v = lb_emit_ptr_offset(p, elem, index);
-		// return lb_addr(v);
+	case Type_RelativeMultiPointer: {
+		cgValue multi_ptr = {};
+		multi_ptr = cg_build_expr(p, ie->expr);
+		if (deref) {
+			multi_ptr = cg_emit_load(p, multi_ptr);
+		}
+		cgValue index = cg_build_expr(p, ie->index);
+		index = cg_emit_conv(p, index, t_int);
+
+		cgValue v = cg_emit_ptr_offset(p, multi_ptr, index);
+		v.type = alloc_type_pointer(type_deref(v.type, true));
+		return cg_addr(v);
 	}
 
 	case Type_DynamicArray: {

+ 0 - 15
src/tilde_stmt.cpp

@@ -530,21 +530,6 @@ gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) {
 		}
 	case Type_Array:
 		return cg_emit_array_epi(p, s, index);
-	case Type_RelativeSlice:
-		{
-			Type *bi = t->RelativeSlice.base_integer;
-			i64 sz = type_size_of(bi);
-			switch (index) {
-			case 0:
-			case 1:
-				result_type = bi;
-				offset = sz * index;
-				break;
-			default:
-				goto error_case;
-			}
-		}
-		break;
 	case Type_SoaPointer:
 		switch (index) {
 		case 0: result_type = alloc_type_pointer(t->SoaPointer.elem); break;

+ 23 - 23
src/tilde_type_info.cpp

@@ -75,24 +75,24 @@ gb_internal u64 cg_typeid_as_u64(cgModule *m, Type *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_MultiPointer:    kind = Typeid_Multi_Pointer;    break;
-	case Type_Array:           kind = Typeid_Array;            break;
-	case Type_Matrix:          kind = Typeid_Matrix;           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_BitSet:          kind = Typeid_Bit_Set;          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;
-	case Type_SoaPointer:      kind = Typeid_SoaPointer;       break;
+	case Type_Pointer:              kind = Typeid_Pointer;                break;
+	case Type_MultiPointer:         kind = Typeid_Multi_Pointer;          break;
+	case Type_Array:                kind = Typeid_Array;                  break;
+	case Type_Matrix:               kind = Typeid_Matrix;                 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_BitSet:               kind = Typeid_Bit_Set;                break;
+	case Type_SimdVector:           kind = Typeid_Simd_Vector;            break;
+	case Type_RelativePointer:      kind = Typeid_Relative_Pointer;       break;
+	case Type_RelativeMultiPointer: kind = Typeid_Relative_Multi_Pointer; break;
+	case Type_SoaPointer:           kind = Typeid_SoaPointer;             break;
 	}
 
 	if (is_type_cstring(type)) {
@@ -935,15 +935,15 @@ gb_internal void cg_setup_type_info_data(cgModule *m) {
 				cg_global_const_type_info_ptr(m, t->RelativePointer.base_integer, global, offset+base_integer_offset);
 			}
 			break;
-		case Type_RelativeSlice:
+		case Type_RelativeMultiPointer:
 			{
-				tag_type = t_type_info_relative_slice;
+				tag_type = t_type_info_relative_multi_pointer;
 
-				i64 slice_offset        = type_offset_of(tag_type, 0);
+				i64 pointer_offset      = type_offset_of(tag_type, 0);
 				i64 base_integer_offset = type_offset_of(tag_type, 1);
 
-				cg_global_const_type_info_ptr(m, t->RelativeSlice.slice_type,   global, offset+slice_offset);
-				cg_global_const_type_info_ptr(m, t->RelativeSlice.base_integer, global, offset+base_integer_offset);
+				cg_global_const_type_info_ptr(m, t->RelativePointer.pointer_type, global, offset+pointer_offset);
+				cg_global_const_type_info_ptr(m, t->RelativePointer.base_integer, global, offset+base_integer_offset);
 			}
 			break;
 		case Type_Matrix:

+ 28 - 27
src/types.cpp

@@ -267,8 +267,8 @@ struct TypeProc {
 		Type *pointer_type;                               \
 		Type *base_integer;                               \
 	})                                                        \
-	TYPE_KIND(RelativeSlice, struct {                         \
-		Type *slice_type;                                 \
+	TYPE_KIND(RelativeMultiPointer, struct {                  \
+		Type *pointer_type;                               \
 		Type *base_integer;                               \
 	})                                                        \
 	TYPE_KIND(Matrix, struct {                                \
@@ -349,7 +349,7 @@ enum Typeid_Kind : u8 {
 	Typeid_Bit_Set,
 	Typeid_Simd_Vector,
 	Typeid_Relative_Pointer,
-	Typeid_Relative_Slice,
+	Typeid_Relative_Multi_Pointer,
 	Typeid_Matrix,
 	Typeid_SoaPointer,
 };
@@ -635,7 +635,7 @@ gb_global Type *t_type_info_map                  = nullptr;
 gb_global Type *t_type_info_bit_set              = 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_relative_multi_pointer = nullptr;
 gb_global Type *t_type_info_matrix               = nullptr;
 gb_global Type *t_type_info_soa_pointer          = nullptr;
 
@@ -664,7 +664,7 @@ gb_global Type *t_type_info_map_ptr              = nullptr;
 gb_global Type *t_type_info_bit_set_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_type_info_relative_multi_pointer_ptr = nullptr;
 gb_global Type *t_type_info_matrix_ptr           = nullptr;
 gb_global Type *t_type_info_soa_pointer_ptr      = nullptr;
 
@@ -737,6 +737,7 @@ gb_internal Type *   bit_set_to_int(Type *t);
 gb_internal bool     are_types_identical(Type *x, Type *y);
 
 gb_internal bool  is_type_pointer(Type *t);
+gb_internal bool  is_type_multi_pointer(Type *t);
 gb_internal bool  is_type_soa_pointer(Type *t);
 gb_internal bool  is_type_proc(Type *t);
 gb_internal bool  is_type_slice(Type *t);
@@ -1035,12 +1036,12 @@ gb_internal Type *alloc_type_relative_pointer(Type *pointer_type, Type *base_int
 	return t;
 }
 
-gb_internal Type *alloc_type_relative_slice(Type *slice_type, Type *base_integer) {
-	GB_ASSERT(is_type_slice(slice_type));
+gb_internal Type *alloc_type_relative_multi_pointer(Type *pointer_type, Type *base_integer) {
+	GB_ASSERT(is_type_multi_pointer(pointer_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;
+	Type *t = alloc_type(Type_RelativeMultiPointer);
+	t->RelativeMultiPointer.pointer_type = pointer_type;
+	t->RelativeMultiPointer.base_integer = base_integer;
 	return t;
 }
 
@@ -1551,9 +1552,9 @@ gb_internal bool is_type_relative_pointer(Type *t) {
 	t = base_type(t);
 	return t->kind == Type_RelativePointer;
 }
-gb_internal bool is_type_relative_slice(Type *t) {
+gb_internal bool is_type_relative_multi_pointer(Type *t) {
 	t = base_type(t);
-	return t->kind == Type_RelativeSlice;
+	return t->kind == Type_RelativeMultiPointer;
 }
 
 gb_internal bool is_type_u8_slice(Type *t) {
@@ -1970,7 +1971,7 @@ gb_internal bool is_type_indexable(Type *t) {
 		return true;
 	case Type_EnumeratedArray:
 		return true;
-	case Type_RelativeSlice:
+	case Type_RelativeMultiPointer:
 		return true;
 	case Type_Matrix:
 		return true;
@@ -1989,7 +1990,7 @@ gb_internal bool is_type_sliceable(Type *t) {
 		return true;
 	case Type_EnumeratedArray:
 		return false;
-	case Type_RelativeSlice:
+	case Type_RelativeMultiPointer:
 		return true;
 	case Type_Matrix:
 		return false;
@@ -2195,12 +2196,12 @@ gb_internal bool is_type_polymorphic(Type *t, bool or_specialized=false) {
 		}
 		break;
 
-	case Type_RelativeSlice:
-		if (is_type_polymorphic(t->RelativeSlice.slice_type, or_specialized)) {
+	case Type_RelativeMultiPointer:
+		if (is_type_polymorphic(t->RelativeMultiPointer.pointer_type, or_specialized)) {
 			return true;
 		}
-		if (t->RelativeSlice.base_integer != nullptr &&
-		    is_type_polymorphic(t->RelativeSlice.base_integer, or_specialized)) {
+		if (t->RelativeMultiPointer.base_integer != nullptr &&
+		    is_type_polymorphic(t->RelativeMultiPointer.base_integer, or_specialized)) {
 			return true;
 		}
 		break;
@@ -2258,7 +2259,7 @@ gb_internal bool type_has_nil(Type *t) {
 		return false;
 
 	case Type_RelativePointer:
-	case Type_RelativeSlice:
+	case Type_RelativeMultiPointer:
 		return true;
 	}
 	return false;
@@ -2425,7 +2426,7 @@ gb_internal bool is_type_load_safe(Type *type) {
 		return true;
 
 	case Type_RelativePointer:
-	case Type_RelativeSlice:
+	case Type_RelativeMultiPointer:
 		return true;
 
 	case Type_Pointer:
@@ -3629,8 +3630,8 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
 
 	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);
+	case Type_RelativeMultiPointer:
+		return type_align_of_internal(t->RelativeMultiPointer.base_integer, path);
 
 	case Type_SoaPointer:
 		return build_context.int_size;
@@ -3912,8 +3913,8 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *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);
+	case Type_RelativeMultiPointer:
+		return type_size_of_internal(t->RelativeMultiPointer.base_integer, path);
 	}
 
 	// Catch all
@@ -4466,11 +4467,11 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
 		str = gb_string_append_fmt(str, ") ");
 		str = write_type_to_string(str, type->RelativePointer.pointer_type);
 		break;
-	case Type_RelativeSlice:
+	case Type_RelativeMultiPointer:
 		str = gb_string_append_fmt(str, "#relative(");
-		str = write_type_to_string(str, type->RelativeSlice.base_integer);
+		str = write_type_to_string(str, type->RelativePointer.base_integer);
 		str = gb_string_append_fmt(str, ") ");
-		str = write_type_to_string(str, type->RelativeSlice.slice_type);
+		str = write_type_to_string(str, type->RelativePointer.pointer_type);
 		break;
 		
 	case Type_Matrix: