From d3693dca73dfc726aed32908691437abe614e5cf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 6 Jun 2018 00:39:39 -0400 Subject: [PATCH] Pointer Reform: update @typeInfo * add assertion for trying to do @typeInfo on global error set * remove TypeInfo.Slice * add TypeInfo.Pointer.Size with possible values - One - Many - Slice See #770 --- src/analyze.cpp | 2 +- src/codegen.cpp | 11 ++++-- src/ir.cpp | 80 +++++++++++++++++++++++++--------------- std/fmt/index.zig | 31 ++++++++++------ test/cases/type_info.zig | 33 +++++++++++++---- 5 files changed, 102 insertions(+), 55 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 15f08aa3fe..93373f6ec2 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5981,7 +5981,7 @@ size_t type_id_index(TypeTableEntry *entry) { return 7; case TypeTableEntryIdStruct: if (entry->data.structure.is_slice) - return 25; + return 6; return 8; case TypeTableEntryIdComptimeFloat: return 9; diff --git a/src/codegen.cpp b/src/codegen.cpp index a977c34daf..7f95f335d1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6481,7 +6481,6 @@ static void define_builtin_compile_vars(CodeGen *g) { const TypeTableEntryId id = type_id_at_index(i); buf_appendf(contents, " %s,\n", type_id_name(id)); } - buf_appendf(contents, " Slice,\n"); buf_appendf(contents, "};\n\n"); } { @@ -6494,7 +6493,6 @@ static void define_builtin_compile_vars(CodeGen *g) { " Int: Int,\n" " Float: Float,\n" " Pointer: Pointer,\n" - " Slice: Slice,\n" " Array: Array,\n" " Struct: Struct,\n" " ComptimeFloat: void,\n" @@ -6524,13 +6522,18 @@ static void define_builtin_compile_vars(CodeGen *g) { " };\n" "\n" " pub const Pointer = struct {\n" + " size: Size,\n" " is_const: bool,\n" " is_volatile: bool,\n" " alignment: u32,\n" " child: type,\n" - " };\n" "\n" - " pub const Slice = Pointer;\n" + " pub const Size = enum {\n" + " One,\n" + " Many,\n" + " Slice,\n" + " };\n" + " };\n" "\n" " pub const Array = struct {\n" " len: usize,\n" diff --git a/src/ir.cpp b/src/ir.cpp index a6686aae76..3486e8c047 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16222,8 +16222,7 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop return true; } -static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) -{ +static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) { assert(type_entry != nullptr); assert(!type_is_invalid(type_entry)); @@ -16248,38 +16247,67 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t enum_field_val->data.x_struct.fields = inner_fields; }; - const auto create_ptr_like_type_info = [ira](const char *name, TypeTableEntry *ptr_type_entry) { + const auto create_ptr_like_type_info = [ira](TypeTableEntry *ptr_type_entry) { + TypeTableEntry *attrs_type; + uint32_t size_enum_index; + if (is_slice(ptr_type_entry)) { + attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry; + size_enum_index = 2; + } else if (ptr_type_entry->id == TypeTableEntryIdPointer) { + attrs_type = ptr_type_entry; + size_enum_index = (ptr_type_entry->data.pointer.ptr_len == PtrLenSingle) ? 0 : 1; + } else { + zig_unreachable(); + } + + TypeTableEntry *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer"); + ensure_complete_type(ira->codegen, type_info_pointer_type); + assert(!type_is_invalid(type_info_pointer_type)); + ConstExprValue *result = create_const_vals(1); result->special = ConstValSpecialStatic; - result->type = ir_type_info_get_type(ira, name); + result->type = type_info_pointer_type; - ConstExprValue *fields = create_const_vals(4); + ConstExprValue *fields = create_const_vals(5); result->data.x_struct.fields = fields; - // is_const: bool - ensure_field_index(result->type, "is_const", 0); + // size: Size + ensure_field_index(result->type, "size", 0); + TypeTableEntry *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type); + ensure_complete_type(ira->codegen, type_info_pointer_size_type); + assert(!type_is_invalid(type_info_pointer_size_type)); fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_bool; - fields[0].data.x_bool = ptr_type_entry->data.pointer.is_const; - // is_volatile: bool - ensure_field_index(result->type, "is_volatile", 1); + fields[0].type = type_info_pointer_size_type; + bigint_init_unsigned(&fields[0].data.x_enum_tag, size_enum_index); + + // is_const: bool + ensure_field_index(result->type, "is_const", 1); fields[1].special = ConstValSpecialStatic; fields[1].type = ira->codegen->builtin_types.entry_bool; - fields[1].data.x_bool = ptr_type_entry->data.pointer.is_volatile; - // alignment: u32 - ensure_field_index(result->type, "alignment", 2); + fields[1].data.x_bool = attrs_type->data.pointer.is_const; + // is_volatile: bool + ensure_field_index(result->type, "is_volatile", 2); fields[2].special = ConstValSpecialStatic; - fields[2].type = ira->codegen->builtin_types.entry_u32; - bigint_init_unsigned(&fields[2].data.x_bigint, ptr_type_entry->data.pointer.alignment); - // child: type - ensure_field_index(result->type, "child", 3); + fields[2].type = ira->codegen->builtin_types.entry_bool; + fields[2].data.x_bool = attrs_type->data.pointer.is_volatile; + // alignment: u32 + ensure_field_index(result->type, "alignment", 3); fields[3].special = ConstValSpecialStatic; - fields[3].type = ira->codegen->builtin_types.entry_type; - fields[3].data.x_type = ptr_type_entry->data.pointer.child_type; + fields[3].type = ira->codegen->builtin_types.entry_u32; + bigint_init_unsigned(&fields[3].data.x_bigint, attrs_type->data.pointer.alignment); + // child: type + ensure_field_index(result->type, "child", 4); + fields[4].special = ConstValSpecialStatic; + fields[4].type = ira->codegen->builtin_types.entry_type; + fields[4].data.x_type = attrs_type->data.pointer.child_type; return result; }; + if (type_entry == ira->codegen->builtin_types.entry_global_error_set) { + zig_panic("TODO implement @typeInfo for global error set"); + } + ConstExprValue *result = nullptr; switch (type_entry->id) { @@ -16348,7 +16376,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t } case TypeTableEntryIdPointer: { - result = create_ptr_like_type_info("Pointer", type_entry); + result = create_ptr_like_type_info(type_entry); break; } case TypeTableEntryIdArray: @@ -16621,15 +16649,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t case TypeTableEntryIdStruct: { if (type_entry->data.structure.is_slice) { - Buf ptr_field_name = BUF_INIT; - buf_init_from_str(&ptr_field_name, "ptr"); - TypeTableEntry *ptr_type = type_entry->data.structure.fields_by_name.get(&ptr_field_name)->type_entry; - ensure_complete_type(ira->codegen, ptr_type); - if (type_is_invalid(ptr_type)) - return nullptr; - buf_deinit(&ptr_field_name); - - result = create_ptr_like_type_info("Slice", ptr_type); + result = create_ptr_like_type_info(type_entry); break; } diff --git a/std/fmt/index.zig b/std/fmt/index.zig index 047a154bb8..bbf48df0cf 100644 --- a/std/fmt/index.zig +++ b/std/fmt/index.zig @@ -97,7 +97,11 @@ pub fn formatType( output: fn (@typeOf(context), []const u8) Errors!void, ) Errors!void { const T = @typeOf(value); - switch (@typeId(T)) { + if (T == error) { + try output(context, "error."); + return output(context, @errorName(value)); + } + switch (@typeInfo(T)) { builtin.TypeId.Int, builtin.TypeId.Float => { return formatValue(value, fmt, context, Errors, output); }, @@ -125,12 +129,13 @@ pub fn formatType( try output(context, "error."); return output(context, @errorName(value)); }, - builtin.TypeId.Pointer => { - switch (@typeId(T.Child)) { - builtin.TypeId.Array => { - if (T.Child.Child == u8) { + builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) { + builtin.TypeInfo.Pointer.Size.One => switch (@typeInfo(ptr_info.child)) { + builtin.TypeId.Array => |info| { + if (info.child == u8) { return formatText(value, fmt, context, Errors, output); } + return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); }, builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => { const has_cust_fmt = comptime cf: { @@ -154,14 +159,16 @@ pub fn formatType( return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); }, else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)), - } - }, - else => if (@canImplicitCast([]const u8, value)) { - const casted_value = ([]const u8)(value); - return output(context, casted_value); - } else { - @compileError("Unable to format type '" ++ @typeName(T) ++ "'"); + }, + builtin.TypeInfo.Pointer.Size.Many => { + return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); + }, + builtin.TypeInfo.Pointer.Size.Slice => { + const casted_value = ([]const u8)(value); + return output(context, casted_value); + }, }, + else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), } } diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig index 921ff785a7..b452c8e9f6 100644 --- a/test/cases/type_info.zig +++ b/test/cases/type_info.zig @@ -39,12 +39,28 @@ test "type info: pointer type info" { fn testPointer() void { const u32_ptr_info = @typeInfo(*u32); assert(TypeId(u32_ptr_info) == TypeId.Pointer); + assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); assert(u32_ptr_info.Pointer.is_const == false); assert(u32_ptr_info.Pointer.is_volatile == false); - assert(u32_ptr_info.Pointer.alignment == 4); + assert(u32_ptr_info.Pointer.alignment == @alignOf(u32)); assert(u32_ptr_info.Pointer.child == u32); } +test "type info: unknown length pointer type info" { + testUnknownLenPtr(); + comptime testUnknownLenPtr(); +} + +fn testUnknownLenPtr() void { + const u32_ptr_info = @typeInfo([*]const volatile f64); + assert(TypeId(u32_ptr_info) == TypeId.Pointer); + assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); + assert(u32_ptr_info.Pointer.is_const == true); + assert(u32_ptr_info.Pointer.is_volatile == true); + assert(u32_ptr_info.Pointer.alignment == @alignOf(f64)); + assert(u32_ptr_info.Pointer.child == f64); +} + test "type info: slice type info" { testSlice(); comptime testSlice(); @@ -52,11 +68,12 @@ test "type info: slice type info" { fn testSlice() void { const u32_slice_info = @typeInfo([]u32); - assert(TypeId(u32_slice_info) == TypeId.Slice); - assert(u32_slice_info.Slice.is_const == false); - assert(u32_slice_info.Slice.is_volatile == false); - assert(u32_slice_info.Slice.alignment == 4); - assert(u32_slice_info.Slice.child == u32); + assert(TypeId(u32_slice_info) == TypeId.Pointer); + assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); + assert(u32_slice_info.Pointer.is_const == false); + assert(u32_slice_info.Pointer.is_volatile == false); + assert(u32_slice_info.Pointer.alignment == 4); + assert(u32_slice_info.Pointer.child == u32); } test "type info: array type info" { @@ -149,11 +166,11 @@ fn testUnion() void { assert(TypeId(typeinfo_info) == TypeId.Union); assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); assert(typeinfo_info.Union.tag_type == TypeId); - assert(typeinfo_info.Union.fields.len == 26); + assert(typeinfo_info.Union.fields.len == 25); assert(typeinfo_info.Union.fields[4].enum_field != null); assert((??typeinfo_info.Union.fields[4].enum_field).value == 4); assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); - assert(typeinfo_info.Union.defs.len == 21); + assert(typeinfo_info.Union.defs.len == 20); const TestNoTagUnion = union { Foo: void,