From 7eab62325b539be4aacb17fd64f5b4445c8409e7 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 24 Apr 2018 01:49:22 +0300 Subject: [PATCH 01/35] One step towards @typeInfo --- src/all_types.hpp | 8 +++ src/codegen.cpp | 153 ++++++++++++++++++++++++++++++++++++++++++++++ src/ir.cpp | 47 ++++++++++++++ src/ir_print.cpp | 9 +++ 4 files changed, 217 insertions(+) diff --git a/src/all_types.hpp b/src/all_types.hpp index d1b2ad61d260..332fc5204eec 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1293,6 +1293,7 @@ enum BuiltinFnId { BuiltinFnIdMemberType, BuiltinFnIdMemberName, BuiltinFnIdField, + BuiltinFnIdTypeInfo, BuiltinFnIdTypeof, BuiltinFnIdAddWithOverflow, BuiltinFnIdSubWithOverflow, @@ -2037,6 +2038,7 @@ enum IrInstructionId { IrInstructionIdTagType, IrInstructionIdFieldParentPtr, IrInstructionIdOffsetOf, + IrInstructionIdTypeInfo, IrInstructionIdTypeId, IrInstructionIdSetEvalBranchQuota, IrInstructionIdPtrTypeOf, @@ -2858,6 +2860,12 @@ struct IrInstructionOffsetOf { IrInstruction *field_name; }; +struct IrInstructionTypeInfo { + IrInstruction base; + + IrInstruction *type_value; +}; + struct IrInstructionTypeId { IrInstruction base; diff --git a/src/codegen.cpp b/src/codegen.cpp index 2d8c385f44dd..ea2d9f463e0f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4502,6 +4502,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdDeclRef: case IrInstructionIdSwitchVar: case IrInstructionIdOffsetOf: + case IrInstructionIdTypeInfo: case IrInstructionIdTypeId: case IrInstructionIdSetEvalBranchQuota: case IrInstructionIdPtrTypeOf: @@ -6125,6 +6126,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2); create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2); create_builtin_fn(g, BuiltinFnIdField, "field", 2); + create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1); create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4); @@ -6344,6 +6346,157 @@ static void define_builtin_compile_vars(CodeGen *g) { } buf_appendf(contents, "};\n\n"); } + { + buf_appendf(contents, + "pub const IntInfo = struct {\n" + " is_signed: bool,\n" + " bits: u8,\n" + "};\n" + "\n" + "pub const FloatInfo = struct {\n" + " bits: u8,\n" + "};\n" + "\n" + "pub const PointerInfo = struct {\n" + " is_const: bool,\n" + " is_volatile: bool,\n" + " alignment: u32,\n" + " child: &TypeInfo,\n" + "};\n" + "\n" + "pub const ArrayInfo = struct {\n" + " len: u64,\n" + " child: &TypeInfo,\n" + "};\n" + "\n" + "pub const ContainerLayout = enum {\n" + " Auto,\n" + " Extern,\n" + " Packed,\n" + "};\n" + "\n" + "pub const StructFieldInfo = struct {\n" + " name: []const u8,\n" + " offset: usize,\n" + " type_info: TypeInfo,\n" + "};\n" + "\n" + "pub const StructInfo = struct {\n" + " layout: ContainerLayout,\n" + " fields: []StructFieldInfo,\n" + "};\n" + "\n" + "pub const NullableInfo = struct {\n" + " child: &TypeInfo,\n" + "};\n" + "\n" + "pub const ErrorUnionInfo = struct {\n" + " error_set: ErrorSetInfo,\n" + " payload: &TypeInfo,\n" + "};\n" + "\n" + "pub const ErrorInfo = struct {\n" + " name: []const u8,\n" + " value: usize,\n" + "};\n" + "\n" + "pub const ErrorSetInfo = struct {\n" + " errors: []ErrorInfo,\n" + "};\n" + "\n" + "pub const EnumFieldInfo = struct {\n" + " name: []const u8,\n" + " value: usize,\n" + "};\n" + "\n" + "pub const EnumInfo = struct {\n" + " layout: ContainerLayout,\n" + " tag_type: IntInfo,\n" + " fields: []EnumFieldInfo,\n" + "};\n" + "\n" + "pub const UnionFieldInfo = struct {\n" + " name: []const u8,\n" + " enum_field: EnumFieldInfo,\n" + " type_info: TypeInfo,\n" + "};\n" + "\n" + "pub const UnionInfo = struct {\n" + " layout: ContainerLayout,\n" + " tag_type: ?EnumInfo,\n" + " fields: []UnionFieldInfo,\n" + "};\n" + "\n" + "pub const CallingConvention = enum {\n" + " Unspecified,\n" + " C,\n" + " Cold,\n" + " Naked,\n" + " Stdcall,\n" + " Async,\n" + "};\n" + "\n" + "pub const FnArgInfo = struct {\n" + " is_comptime: bool,\n" + " name: []const u8,\n" + " type_info: TypeInfo,\n" + "};\n" + "\n" + "pub const FnInfo = struct {\n" + " calling_convention: CallingConvention,\n" + " is_generic: bool,\n" + " is_varargs: bool,\n" + " return_type: &TypeInfo,\n" + " args: []FnArgInfo,\n" + "};\n" + "\n" + "pub const BoundFnInfo = struct {\n" + " bound_type: &TypeInfo,\n" + " fn_info: FnInfo,\n" + "};\n" + "\n" + "pub const PromiseInfo = struct {\n" + " child: ?&TypeInfo,\n" + "};\n" + "\n" + "pub const TypeInfo = union(TypeId) {\n" + " Type: void,\n" + " Void: void,\n" + " Bool: void,\n" + " NoReturn: void,\n" + " Int: IntInfo,\n" + " Float: FloatInfo,\n" + " Pointer: PointerInfo,\n" + " Array: ArrayInfo,\n" + " Struct: StructInfo,\n" + " FloatLiteral: void,\n" + " IntLiteral: void,\n" + " UndefinedLiteral: void,\n" + " NullLiteral: void,\n" + " Nullable: NullableInfo,\n" + " ErrorUnion: ErrorUnionInfo,\n" + " ErrorSet: ErrorSetInfo,\n" + " Enum: EnumInfo,\n" + " Union: UnionInfo,\n" + " Fn: FnInfo,\n" + " Namespace: void,\n" + " Block: void,\n" + " BoundFn: BoundFnInfo,\n" + " ArgTuple: void,\n" + " Opaque: void,\n" + " Promise: PromiseInfo,\n" + "};\n\n"); + assert(ContainerLayoutAuto == 0); + assert(ContainerLayoutExtern == 1); + assert(ContainerLayoutPacked == 2); + + assert(CallingConventionUnspecified == 0); + assert(CallingConventionC == 1); + assert(CallingConventionCold == 2); + assert(CallingConventionNaked == 3); + assert(CallingConventionStdcall == 4); + assert(CallingConventionAsync == 5); + } { buf_appendf(contents, "pub const FloatMode = enum {\n" diff --git a/src/ir.cpp b/src/ir.cpp index cd00fc623087..69897f3b91ea 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -615,6 +615,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOffsetOf *) { return IrInstructionIdOffsetOf; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) { + return IrInstructionIdTypeInfo; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeId *) { return IrInstructionIdTypeId; } @@ -2440,6 +2444,16 @@ static IrInstruction *ir_build_offset_of(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } +static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *type_value) { + IrInstructionTypeInfo *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_value = type_value; + + ir_ref_instruction(type_value, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { @@ -4080,6 +4094,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_load_ptr(irb, scope, node, ptr_instruction); } + case BuiltinFnIdTypeInfo: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value); + return ir_lval_wrap(irb, scope, type_info, lval); + } case BuiltinFnIdBreakpoint: return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval); case BuiltinFnIdReturnAddress: @@ -15669,6 +15693,26 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira, return ira->codegen->builtin_types.entry_num_lit_int; } +static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, + IrInstructionTypeInfo *instruction) +{ + IrInstruction *type_value = instruction->type_value->other; + TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); + if (type_is_invalid(type_entry)) + return ira->codegen->builtin_types.entry_invalid; + + ConstExprValue *var_value = get_builtin_value(ira->codegen, "TypeInfo"); + assert(var_value->type->id == TypeTableEntryIdMetaType); + TypeTableEntry *result_type = var_value->data.x_type; + + // TODO: Check if we need to explicitely make a &const TypeInfo here, I think we don't. + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); + out_val->data.x_struct.fields = create_const_vals(1); + // TODO: Fill the struct + zig_panic("Building TypeInfo..."); + return result_type; +} + static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira, IrInstructionTypeId *instruction) { @@ -18555,6 +18599,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction); case IrInstructionIdOffsetOf: return ir_analyze_instruction_offset_of(ira, (IrInstructionOffsetOf *)instruction); + case IrInstructionIdTypeInfo: + return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction); case IrInstructionIdTypeId: return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction); case IrInstructionIdSetEvalBranchQuota: @@ -18821,6 +18867,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdTagName: case IrInstructionIdFieldParentPtr: case IrInstructionIdOffsetOf: + case IrInstructionIdTypeInfo: case IrInstructionIdTypeId: case IrInstructionIdAlignCast: case IrInstructionIdOpaqueType: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index a77ae244d43f..9678120f1dcd 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -966,6 +966,12 @@ static void ir_print_offset_of(IrPrint *irp, IrInstructionOffsetOf *instruction) fprintf(irp->f, ")"); } +static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction) { + fprintf(irp->f, "@typeInfo("); + ir_print_other_instruction(irp, instruction->type_value); + fprintf(irp->f, ")"); +} + static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) { fprintf(irp->f, "@typeId("); ir_print_other_instruction(irp, instruction->type_value); @@ -1536,6 +1542,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdOffsetOf: ir_print_offset_of(irp, (IrInstructionOffsetOf *)instruction); break; + case IrInstructionIdTypeInfo: + ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction); + break; case IrInstructionIdTypeId: ir_print_type_id(irp, (IrInstructionTypeId *)instruction); break; From fb88f5a0d21f68632a8c712e14a9640f9c4f6cb3 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 24 Apr 2018 11:20:33 +0300 Subject: [PATCH 02/35] @typeInfo with void payloads now works! --- src/ir.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 69897f3b91ea..52136ec9c81f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15705,11 +15705,32 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, assert(var_value->type->id == TypeTableEntryIdMetaType); TypeTableEntry *result_type = var_value->data.x_type; - // TODO: Check if we need to explicitely make a &const TypeInfo here, I think we don't. ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); - out_val->data.x_struct.fields = create_const_vals(1); - // TODO: Fill the struct - zig_panic("Building TypeInfo..."); + bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry->id)); + out_val->data.x_union.parent.id = ConstParentIdNone; + + switch (type_entry->id) { + case TypeTableEntryIdInvalid: + zig_unreachable(); + case TypeTableEntryIdMetaType: + case TypeTableEntryIdVoid: + case TypeTableEntryIdBool: + case TypeTableEntryIdUnreachable: + case TypeTableEntryIdNumLitFloat: + case TypeTableEntryIdNumLitInt: + case TypeTableEntryIdUndefLit: + case TypeTableEntryIdNullLit: + case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: + case TypeTableEntryIdArgTuple: + case TypeTableEntryIdOpaque: + // TODO: Check out this is the way to handle voids; + out_val->data.x_union.payload = nullptr; + break; + default: + zig_panic("@typeInfo unsupported for %s", buf_ptr(&type_entry->name)); + } + return result_type; } From ec2a3ed500d4ba269c87b3ad0efe7bcc89eb2057 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 24 Apr 2018 15:03:46 +0300 Subject: [PATCH 03/35] Attempt at adding comptime union field access --- src/codegen.cpp | 1 + src/ir.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index ea2d9f463e0f..60a459f822d3 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6347,6 +6347,7 @@ static void define_builtin_compile_vars(CodeGen *g) { buf_appendf(contents, "};\n\n"); } { + // TODO: Add method info where methods are supported. buf_appendf(contents, "pub const IntInfo = struct {\n" " is_signed: bool,\n" diff --git a/src/ir.cpp b/src/ir.cpp index 52136ec9c81f..2212efb1016e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13473,6 +13473,41 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ } else if (bare_type->id == TypeTableEntryIdUnion) { TypeUnionField *field = find_union_type_field(bare_type, field_name); if (field) { + if (instr_is_comptime(container_ptr)) { + ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); + if (!ptr_val) + return ira->codegen->invalid_instruction; + + if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { + ConstExprValue *union_val = const_ptr_pointee(ira->codegen, ptr_val); + if (type_is_invalid(union_val->type)) + return ira->codegen->invalid_instruction; + + TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag); + if (actual_field == nullptr) + zig_unreachable(); + + if (field != actual_field) { + ir_add_error_node(ira, source_instr->source_node, + buf_sprintf("accessing union field '%s' while field '%s' is set", buf_ptr(field_name), + buf_ptr(actual_field->name))); + return ira->codegen->invalid_instruction; + } + + ConstExprValue *payload_val = union_val->data.x_union.payload; + TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, payload_val->type, is_const, is_volatile, + get_abi_alignment(ira->codegen, payload_val->type), 0, 0); + + IrInstruction *result = ir_get_const(ira, source_instr); + ConstExprValue *const_val = &result->value; + const_val->data.x_ptr.special = ConstPtrSpecialRef; + const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut; + const_val->data.x_ptr.data.ref.pointee = payload_val; + const_val->type = ptr_type; + return result; + } + } + IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field); result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, get_abi_alignment(ira->codegen, field->type_entry), 0, 0); @@ -15706,8 +15741,12 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, TypeTableEntry *result_type = var_value->data.x_type; ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); + // TODO: Do I need those? probably set in ir_build_const_from + //out_val->special = ConstValSpecialStatic; + //out_val->type = result_type; + bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry->id)); - out_val->data.x_union.parent.id = ConstParentIdNone; + //out_val->data.x_union.parent.id = ConstParentIdNone; switch (type_entry->id) { case TypeTableEntryIdInvalid: @@ -15724,9 +15763,34 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, case TypeTableEntryIdBlock: case TypeTableEntryIdArgTuple: case TypeTableEntryIdOpaque: - // TODO: Check out this is the way to handle voids; out_val->data.x_union.payload = nullptr; break; + case TypeTableEntryIdInt: + { + // Error from 'ir_resolve_const': "unable to evaluate constant expression" + ConstExprValue *payload = create_const_vals(1); + out_val->data.x_union.payload = payload; + + payload->special = ConstValSpecialStatic; + payload->type = get_builtin_value(ira->codegen, "IntInfo")->type; + + ConstExprValue *fields = create_const_vals(2); + payload->data.x_struct.fields = fields; + + payload->data.x_struct.parent.id = ConstParentIdUnion; + payload->data.x_struct.parent.data.p_union.union_val = out_val; + + // TODO: See what happens if we don't set the field type (set it to nullptr) + fields[0].special = ConstValSpecialStatic; + fields[0].type = ira->codegen->builtin_types.entry_bool; + fields[0].data.x_bool = type_entry->data.integral.is_signed; + + fields[1].special = ConstValSpecialStatic; + fields[1].type = ira->codegen->builtin_types.entry_u8; + bigint_init_unsigned(&fields[1].data.x_bigint, type_entry->data.integral.bit_count); + + break; + } default: zig_panic("@typeInfo unsupported for %s", buf_ptr(&type_entry->name)); } From e9309d3b1310863d9571486b071b7a34bea1fb60 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 24 Apr 2018 15:17:34 +0300 Subject: [PATCH 04/35] Fixed IntInfo generation. --- src/ir.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 2212efb1016e..39e48ac33b33 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15772,7 +15772,10 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, out_val->data.x_union.payload = payload; payload->special = ConstValSpecialStatic; - payload->type = get_builtin_value(ira->codegen, "IntInfo")->type; + + ConstExprValue *int_info_type = get_builtin_value(ira->codegen, "IntInfo"); + assert(int_info_type->type->id == TypeTableEntryIdMetaType); + payload->type = int_info_type->data.x_type; ConstExprValue *fields = create_const_vals(2); payload->data.x_struct.fields = fields; From 0e5fb035e3d12879b4bd7a23578fdb8932deb4d1 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 24 Apr 2018 16:23:22 +0300 Subject: [PATCH 05/35] Added (broken) pointer info, float info --- src/ir.cpp | 155 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 125 insertions(+), 30 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 39e48ac33b33..3ba9bc4772c6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15728,27 +15728,13 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira, return ira->codegen->builtin_types.entry_num_lit_int; } -static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, - IrInstructionTypeInfo *instruction) +static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *parent, TypeTableEntry *type_entry) { - IrInstruction *type_value = instruction->type_value->other; - TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); - if (type_is_invalid(type_entry)) - return ira->codegen->builtin_types.entry_invalid; + assert(type_entry != nullptr); + assert(!type_is_invalid(type_entry)); - ConstExprValue *var_value = get_builtin_value(ira->codegen, "TypeInfo"); - assert(var_value->type->id == TypeTableEntryIdMetaType); - TypeTableEntry *result_type = var_value->data.x_type; - - ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); - // TODO: Do I need those? probably set in ir_build_const_from - //out_val->special = ConstValSpecialStatic; - //out_val->type = result_type; - - bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry->id)); - //out_val->data.x_union.parent.id = ConstParentIdNone; - - switch (type_entry->id) { + switch (type_entry->id) + { case TypeTableEntryIdInvalid: zig_unreachable(); case TypeTableEntryIdMetaType: @@ -15763,14 +15749,11 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, case TypeTableEntryIdBlock: case TypeTableEntryIdArgTuple: case TypeTableEntryIdOpaque: - out_val->data.x_union.payload = nullptr; - break; + // TODO: Construct a valid void payload. + return nullptr; case TypeTableEntryIdInt: { - // Error from 'ir_resolve_const': "unable to evaluate constant expression" ConstExprValue *payload = create_const_vals(1); - out_val->data.x_union.payload = payload; - payload->special = ConstValSpecialStatic; ConstExprValue *int_info_type = get_builtin_value(ira->codegen, "IntInfo"); @@ -15780,23 +15763,135 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, ConstExprValue *fields = create_const_vals(2); payload->data.x_struct.fields = fields; - payload->data.x_struct.parent.id = ConstParentIdUnion; - payload->data.x_struct.parent.data.p_union.union_val = out_val; + if (parent->type->id == TypeTableEntryIdStruct) + { + payload->data.x_struct.parent.id = ConstParentIdStruct; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else if (parent->type->id == TypeTableEntryIdUnion) + { + payload->data.x_struct.parent.id = ConstParentIdUnion; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else + { + payload->data.x_struct.parent.id = ConstParentIdNone; + } - // TODO: See what happens if we don't set the field type (set it to nullptr) + // is_signed: bool fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_bool; fields[0].data.x_bool = type_entry->data.integral.is_signed; - + // bits: u8 fields[1].special = ConstValSpecialStatic; fields[1].type = ira->codegen->builtin_types.entry_u8; bigint_init_unsigned(&fields[1].data.x_bigint, type_entry->data.integral.bit_count); - break; + return payload; + } + case TypeTableEntryIdFloat: + { + ConstExprValue *payload = create_const_vals(1); + payload->special = ConstValSpecialStatic; + + ConstExprValue *float_info_type = get_builtin_value(ira->codegen, "FloatInfo"); + assert(float_info_type->type->id == TypeTableEntryIdMetaType); + payload->type = float_info_type->data.x_type; + + ConstExprValue *fields = create_const_vals(1); + payload->data.x_struct.fields = fields; + + if (parent->type->id == TypeTableEntryIdStruct) + { + payload->data.x_struct.parent.id = ConstParentIdStruct; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else if (parent->type->id == TypeTableEntryIdUnion) + { + payload->data.x_struct.parent.id = ConstParentIdUnion; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else + { + payload->data.x_struct.parent.id = ConstParentIdNone; + } + // bits: u8 + fields[0].special = ConstValSpecialStatic; + fields[0].type = ira->codegen->builtin_types.entry_u8; + bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.floating.bit_count); + + return payload; + } + case TypeTableEntryIdPointer: + { + ConstExprValue *payload = create_const_vals(1); + payload->special = ConstValSpecialStatic; + + ConstExprValue *pointer_info_type = get_builtin_value(ira->codegen, "PointerInfo"); + assert(pointer_info_type->type->id == TypeTableEntryIdMetaType); + payload->type = pointer_info_type->data.x_type; + + ConstExprValue *fields = create_const_vals(4); + payload->data.x_struct.fields = fields; + + if (parent->type->id == TypeTableEntryIdStruct) + { + payload->data.x_struct.parent.id = ConstParentIdStruct; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else if (parent->type->id == TypeTableEntryIdUnion) + { + payload->data.x_struct.parent.id = ConstParentIdUnion; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else + { + payload->data.x_struct.parent.id = ConstParentIdNone; + } + // is_const: bool + fields[0].special = ConstValSpecialStatic; + fields[0].type = ira->codegen->builtin_types.entry_bool; + fields[0].data.x_bool = type_entry->data.pointer.is_const; + // is_volatile: bool + fields[1].special = ConstValSpecialStatic; + fields[1].type = ira->codegen->builtin_types.entry_bool; + fields[1].data.x_bool = type_entry->data.pointer.is_volatile; + // alignment: u32 + fields[2].special = ConstValSpecialStatic; + fields[2].type = ira->codegen->builtin_types.entry_u32; + bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.pointer.alignment); + // child: &TypeInfo + ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); + assert(type_info_type->type->id == TypeTableEntryIdMetaType); + fields[3].special = ConstValSpecialStatic; + fields[3].type = get_pointer_to_type(ira->codegen, type_info_type->data.x_type, false); + fields[3].data.x_ptr.special = ConstPtrSpecialRef; + fields[3].data.x_ptr.mut = ConstPtrMutComptimeVar; + fields[3].data.x_ptr.data.ref.pointee = ir_make_type_info_value(ira, &fields[3], type_entry->data.pointer.child_type); + return payload; } default: - zig_panic("@typeInfo unsupported for %s", buf_ptr(&type_entry->name)); + zig_unreachable(); } +} + +static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, + IrInstructionTypeInfo *instruction) +{ + IrInstruction *type_value = instruction->type_value->other; + TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); + if (type_is_invalid(type_entry)) + return ira->codegen->builtin_types.entry_invalid; + + ConstExprValue *var_value = get_builtin_value(ira->codegen, "TypeInfo"); + assert(var_value->type->id == TypeTableEntryIdMetaType); + TypeTableEntry *result_type = var_value->data.x_type; + + // TODO: We need to return a const pointer to the typeinfo, not the typeinfo by value. + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); + out_val->type = result_type; + bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry->id)); + out_val->data.x_union.payload = ir_make_type_info_value(ira, out_val, type_entry); return result_type; } From 189e8e97bdd8dea8efa9ea30401b164ea619f2e4 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 24 Apr 2018 16:50:36 +0300 Subject: [PATCH 06/35] PointerInfo child is a pointer to a TypeInfo union, still not working correctly --- src/ir.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 3ba9bc4772c6..86c718da813d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15867,7 +15867,11 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p fields[3].type = get_pointer_to_type(ira->codegen, type_info_type->data.x_type, false); fields[3].data.x_ptr.special = ConstPtrSpecialRef; fields[3].data.x_ptr.mut = ConstPtrMutComptimeVar; - fields[3].data.x_ptr.data.ref.pointee = ir_make_type_info_value(ira, &fields[3], type_entry->data.pointer.child_type); + ConstExprValue *union_val = create_const_vals(1); + union_val->type = type_info_type->data.x_type; + bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.pointer.child_type->id)); + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, type_entry->data.pointer.child_type); + fields[3].data.x_ptr.data.ref.pointee = union_val; return payload; } default: From 2d8553c85333734a1690dfae30d881103dde0727 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 24 Apr 2018 17:01:20 +0300 Subject: [PATCH 07/35] Fixed PointerInfo generation --- src/ir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 86c718da813d..e1208f03ad45 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15859,7 +15859,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p // alignment: u32 fields[2].special = ConstValSpecialStatic; fields[2].type = ira->codegen->builtin_types.entry_u32; - bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.pointer.alignment); + bigint_init_unsigned(&fields[2].data.x_bigint, type_entry->data.pointer.alignment); // child: &TypeInfo ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); assert(type_info_type->type->id == TypeTableEntryIdMetaType); From 09d7033d1db6ac0887aa21f87a2f96dad039f4e3 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 24 Apr 2018 17:08:45 +0300 Subject: [PATCH 08/35] PointerInfo child is known at comptime --- src/ir.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ir.cpp b/src/ir.cpp index e1208f03ad45..be61b0c2807c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15868,6 +15868,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p fields[3].data.x_ptr.special = ConstPtrSpecialRef; fields[3].data.x_ptr.mut = ConstPtrMutComptimeVar; ConstExprValue *union_val = create_const_vals(1); + union_val->special = ConstValSpecialStatic; union_val->type = type_info_type->data.x_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.pointer.child_type->id)); union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, type_entry->data.pointer.child_type); From 182a9fad2d55973ab50f4a2170edb88d6708681d Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 24 Apr 2018 17:38:30 +0300 Subject: [PATCH 09/35] Added ArrayInfo, NullableInfo, PromiseInfo generation --- src/codegen.cpp | 2 +- src/ir.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 60a459f822d3..2e7cc937b4a1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6366,7 +6366,7 @@ static void define_builtin_compile_vars(CodeGen *g) { "};\n" "\n" "pub const ArrayInfo = struct {\n" - " len: u64,\n" + " len: usize,\n" " child: &TypeInfo,\n" "};\n" "\n" diff --git a/src/ir.cpp b/src/ir.cpp index be61b0c2807c..a00d98efd1ba 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15875,6 +15875,151 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p fields[3].data.x_ptr.data.ref.pointee = union_val; return payload; } + case TypeTableEntryIdArray: + { + ConstExprValue *payload = create_const_vals(1); + payload->special = ConstValSpecialStatic; + + ConstExprValue *pointer_info_type = get_builtin_value(ira->codegen, "ArrayInfo"); + assert(pointer_info_type->type->id == TypeTableEntryIdMetaType); + payload->type = pointer_info_type->data.x_type; + + ConstExprValue *fields = create_const_vals(2); + payload->data.x_struct.fields = fields; + + if (parent->type->id == TypeTableEntryIdStruct) + { + payload->data.x_struct.parent.id = ConstParentIdStruct; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else if (parent->type->id == TypeTableEntryIdUnion) + { + payload->data.x_struct.parent.id = ConstParentIdUnion; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else + { + payload->data.x_struct.parent.id = ConstParentIdNone; + } + // len: usize + fields[0].special = ConstValSpecialStatic; + fields[0].type = ira->codegen->builtin_types.entry_usize; + bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.array.len); + // child: &TypeInfo + ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); + assert(type_info_type->type->id == TypeTableEntryIdMetaType); + fields[1].special = ConstValSpecialStatic; + fields[1].type = get_pointer_to_type(ira->codegen, type_info_type->data.x_type, false); + fields[1].data.x_ptr.special = ConstPtrSpecialRef; + fields[1].data.x_ptr.mut = ConstPtrMutComptimeVar; + ConstExprValue *union_val = create_const_vals(1); + union_val->special = ConstValSpecialStatic; + union_val->type = type_info_type->data.x_type; + bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.array.child_type->id)); + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, type_entry->data.array.child_type); + fields[1].data.x_ptr.data.ref.pointee = union_val; + return payload; + } + case TypeTableEntryIdMaybe: + { + ConstExprValue *payload = create_const_vals(1); + payload->special = ConstValSpecialStatic; + + ConstExprValue *pointer_info_type = get_builtin_value(ira->codegen, "NullableInfo"); + assert(pointer_info_type->type->id == TypeTableEntryIdMetaType); + payload->type = pointer_info_type->data.x_type; + + ConstExprValue *fields = create_const_vals(1); + payload->data.x_struct.fields = fields; + + if (parent->type->id == TypeTableEntryIdStruct) + { + payload->data.x_struct.parent.id = ConstParentIdStruct; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else if (parent->type->id == TypeTableEntryIdUnion) + { + payload->data.x_struct.parent.id = ConstParentIdUnion; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else + { + payload->data.x_struct.parent.id = ConstParentIdNone; + } + // child: &TypeInfo + ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); + assert(type_info_type->type->id == TypeTableEntryIdMetaType); + fields[0].special = ConstValSpecialStatic; + fields[0].type = get_pointer_to_type(ira->codegen, type_info_type->data.x_type, false); + fields[0].data.x_ptr.special = ConstPtrSpecialRef; + fields[0].data.x_ptr.mut = ConstPtrMutComptimeVar; + ConstExprValue *union_val = create_const_vals(1); + union_val->special = ConstValSpecialStatic; + union_val->type = type_info_type->data.x_type; + bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.maybe.child_type->id)); + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, type_entry->data.maybe.child_type); + fields[0].data.x_ptr.data.ref.pointee = union_val; + return payload; + } + case TypeTableEntryIdPromise: + { + ConstExprValue *payload = create_const_vals(1); + payload->special = ConstValSpecialStatic; + + ConstExprValue *pointer_info_type = get_builtin_value(ira->codegen, "PromiseInfo"); + assert(pointer_info_type->type->id == TypeTableEntryIdMetaType); + payload->type = pointer_info_type->data.x_type; + + ConstExprValue *fields = create_const_vals(1); + payload->data.x_struct.fields = fields; + + if (parent->type->id == TypeTableEntryIdStruct) + { + payload->data.x_struct.parent.id = ConstParentIdStruct; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else if (parent->type->id == TypeTableEntryIdUnion) + { + payload->data.x_struct.parent.id = ConstParentIdUnion; + payload->data.x_struct.parent.data.p_union.union_val = parent; + } + else + { + payload->data.x_struct.parent.id = ConstParentIdNone; + } + // child: ?&TypeInfo + ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); + assert(type_info_type->type->id == TypeTableEntryIdMetaType); + + TypeTableEntry *type_info_ptr_type = get_pointer_to_type(ira->codegen, type_info_type->data.x_type, false); + + fields[0].special = ConstValSpecialStatic; + fields[0].type = get_maybe_type(ira->codegen, type_info_ptr_type); + + if (type_entry->data.promise.result_type == nullptr) + { + fields[0].data.x_maybe = nullptr; + } + else + { + ConstExprValue *maybe_value = create_const_vals(1); + maybe_value->special = ConstValSpecialStatic; + maybe_value->type = type_info_ptr_type; + + maybe_value->data.x_ptr.special = ConstPtrSpecialRef; + maybe_value->data.x_ptr.mut = ConstPtrMutComptimeVar; + + ConstExprValue *union_val = create_const_vals(1); + union_val->special = ConstValSpecialStatic; + union_val->type = type_info_type->data.x_type; + bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.promise.result_type->id)); + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, type_entry->data.promise.result_type); + + maybe_value->data.x_ptr.data.ref.pointee = union_val; + fields[0].data.x_maybe = maybe_value; + } + return payload; + } default: zig_unreachable(); } From 778b931bf33c9b19502857af918fc159c0cd8e83 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Wed, 25 Apr 2018 02:50:18 +0300 Subject: [PATCH 10/35] Fixed comptime union void field access --- src/ir.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index a00d98efd1ba..aa456f503081 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13495,8 +13495,18 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ } ConstExprValue *payload_val = union_val->data.x_union.payload; - TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, payload_val->type, is_const, is_volatile, - get_abi_alignment(ira->codegen, payload_val->type), 0, 0); + + TypeTableEntry *field_type = field->type_entry; + if (field_type->id == TypeTableEntryIdVoid) + { + assert(payload_val == nullptr); + payload_val = create_const_vals(1); + payload_val->special = ConstValSpecialStatic; + payload_val->type = field_type; + } + + TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, is_const, is_volatile, + get_abi_alignment(ira->codegen, field_type), 0, 0); IrInstruction *result = ir_get_const(ira, source_instr); ConstExprValue *const_val = &result->value; @@ -15749,7 +15759,6 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p case TypeTableEntryIdBlock: case TypeTableEntryIdArgTuple: case TypeTableEntryIdOpaque: - // TODO: Construct a valid void payload. return nullptr; case TypeTableEntryIdInt: { From d68aea4f35fe935f3bf80c86dac4da7c4b88dc5b Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Wed, 25 Apr 2018 11:35:46 +0300 Subject: [PATCH 11/35] Added checks for field name/index mapping in TypeInfo generation. Abstracted the parent setting out. --- src/ir.cpp | 139 ++++++++++++++++++++--------------------------------- 1 file changed, 53 insertions(+), 86 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index aa456f503081..dee093c57ef0 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13411,7 +13411,6 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, return ira->codegen->invalid_instruction; } - static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type) { @@ -15738,6 +15737,37 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira, return ira->codegen->builtin_types.entry_num_lit_int; } +static void ensure_field_index(TypeTableEntry *type, const char *field_name, size_t index) { + Buf *field_name_buf; + + assert(type != nullptr && !type_is_invalid(type)); + // Check for our field by creating a buffer in place then using the comma operator to free it so that we don't + // leak memory in debug mode. + assert(find_struct_type_field(type, field_name_buf = buf_create_from_str(field_name))->src_index == index && + (buf_deinit(field_name_buf), true)); +} + +static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExprValue *parent) { + assert(struct_val->type->id == TypeTableEntryIdStruct); + assert(parent->type != nullptr && !type_is_invalid(parent->type)); + + switch (parent->type->id) + { + case TypeTableEntryIdArray: + zig_panic("TODO - Only expected struct or union parent."); + case TypeTableEntryIdStruct: + struct_val->data.x_struct.parent.id = ConstParentIdStruct; + struct_val->data.x_struct.parent.data.p_union.union_val = parent; + break; + case TypeTableEntryIdUnion: + struct_val->data.x_struct.parent.id = ConstParentIdUnion; + struct_val->data.x_struct.parent.data.p_union.union_val = parent; + break; + default: + struct_val->data.x_struct.parent.id = ConstParentIdNone; + } +} + static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *parent, TypeTableEntry *type_entry) { assert(type_entry != nullptr); @@ -15772,26 +15802,15 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(2); payload->data.x_struct.fields = fields; - if (parent->type->id == TypeTableEntryIdStruct) - { - payload->data.x_struct.parent.id = ConstParentIdStruct; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else if (parent->type->id == TypeTableEntryIdUnion) - { - payload->data.x_struct.parent.id = ConstParentIdUnion; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else - { - payload->data.x_struct.parent.id = ConstParentIdNone; - } + ir_type_info_struct_set_parent(payload, parent); // is_signed: bool + ensure_field_index(payload->type, "is_signed", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_bool; fields[0].data.x_bool = type_entry->data.integral.is_signed; // bits: u8 + ensure_field_index(payload->type, "bits", 1); fields[1].special = ConstValSpecialStatic; fields[1].type = ira->codegen->builtin_types.entry_u8; bigint_init_unsigned(&fields[1].data.x_bigint, type_entry->data.integral.bit_count); @@ -15810,21 +15829,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(1); payload->data.x_struct.fields = fields; - if (parent->type->id == TypeTableEntryIdStruct) - { - payload->data.x_struct.parent.id = ConstParentIdStruct; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else if (parent->type->id == TypeTableEntryIdUnion) - { - payload->data.x_struct.parent.id = ConstParentIdUnion; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else - { - payload->data.x_struct.parent.id = ConstParentIdNone; - } + ir_type_info_struct_set_parent(payload, parent); + // bits: u8 + ensure_field_index(payload->type, "bits", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_u8; bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.floating.bit_count); @@ -15843,33 +15851,25 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(4); payload->data.x_struct.fields = fields; - if (parent->type->id == TypeTableEntryIdStruct) - { - payload->data.x_struct.parent.id = ConstParentIdStruct; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else if (parent->type->id == TypeTableEntryIdUnion) - { - payload->data.x_struct.parent.id = ConstParentIdUnion; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else - { - payload->data.x_struct.parent.id = ConstParentIdNone; - } + ir_type_info_struct_set_parent(payload, parent); + // is_const: bool + ensure_field_index(payload->type, "is_const", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_bool; fields[0].data.x_bool = type_entry->data.pointer.is_const; // is_volatile: bool + ensure_field_index(payload->type, "is_volatile", 1); fields[1].special = ConstValSpecialStatic; fields[1].type = ira->codegen->builtin_types.entry_bool; fields[1].data.x_bool = type_entry->data.pointer.is_volatile; // alignment: u32 + ensure_field_index(payload->type, "alignment", 2); fields[2].special = ConstValSpecialStatic; fields[2].type = ira->codegen->builtin_types.entry_u32; bigint_init_unsigned(&fields[2].data.x_bigint, type_entry->data.pointer.alignment); // child: &TypeInfo + ensure_field_index(payload->type, "child", 3); ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); assert(type_info_type->type->id == TypeTableEntryIdMetaType); fields[3].special = ConstValSpecialStatic; @@ -15896,25 +15896,15 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(2); payload->data.x_struct.fields = fields; - if (parent->type->id == TypeTableEntryIdStruct) - { - payload->data.x_struct.parent.id = ConstParentIdStruct; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else if (parent->type->id == TypeTableEntryIdUnion) - { - payload->data.x_struct.parent.id = ConstParentIdUnion; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else - { - payload->data.x_struct.parent.id = ConstParentIdNone; - } + ir_type_info_struct_set_parent(payload, parent); + // len: usize + ensure_field_index(payload->type, "len", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_usize; bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.array.len); // child: &TypeInfo + ensure_field_index(payload->type, "child", 1); ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); assert(type_info_type->type->id == TypeTableEntryIdMetaType); fields[1].special = ConstValSpecialStatic; @@ -15941,21 +15931,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(1); payload->data.x_struct.fields = fields; - if (parent->type->id == TypeTableEntryIdStruct) - { - payload->data.x_struct.parent.id = ConstParentIdStruct; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else if (parent->type->id == TypeTableEntryIdUnion) - { - payload->data.x_struct.parent.id = ConstParentIdUnion; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else - { - payload->data.x_struct.parent.id = ConstParentIdNone; - } + ir_type_info_struct_set_parent(payload, parent); + // child: &TypeInfo + ensure_field_index(payload->type, "child", 0); ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); assert(type_info_type->type->id == TypeTableEntryIdMetaType); fields[0].special = ConstValSpecialStatic; @@ -15982,21 +15961,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(1); payload->data.x_struct.fields = fields; - if (parent->type->id == TypeTableEntryIdStruct) - { - payload->data.x_struct.parent.id = ConstParentIdStruct; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else if (parent->type->id == TypeTableEntryIdUnion) - { - payload->data.x_struct.parent.id = ConstParentIdUnion; - payload->data.x_struct.parent.data.p_union.union_val = parent; - } - else - { - payload->data.x_struct.parent.id = ConstParentIdNone; - } + ir_type_info_struct_set_parent(payload, parent); + // child: ?&TypeInfo + ensure_field_index(payload->type, "child", 0); ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); assert(type_info_type->type->id == TypeTableEntryIdMetaType); @@ -16046,7 +16014,6 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, assert(var_value->type->id == TypeTableEntryIdMetaType); TypeTableEntry *result_type = var_value->data.x_type; - // TODO: We need to return a const pointer to the typeinfo, not the typeinfo by value. ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); out_val->type = result_type; bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry->id)); From 2606993cb48e69015a9152b860e48fca29d330e1 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Wed, 25 Apr 2018 11:59:35 +0300 Subject: [PATCH 12/35] Fixed ir_type_info_struct_set_parent for struct parents. --- src/ir.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index dee093c57ef0..a68747fce4fb 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15747,7 +15747,7 @@ static void ensure_field_index(TypeTableEntry *type, const char *field_name, siz (buf_deinit(field_name_buf), true)); } -static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExprValue *parent) { +static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExprValue *parent, ssize_t parent_field_index) { assert(struct_val->type->id == TypeTableEntryIdStruct); assert(parent->type != nullptr && !type_is_invalid(parent->type)); @@ -15756,10 +15756,13 @@ static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExpr case TypeTableEntryIdArray: zig_panic("TODO - Only expected struct or union parent."); case TypeTableEntryIdStruct: + assert(parent_field_index >= 0); struct_val->data.x_struct.parent.id = ConstParentIdStruct; - struct_val->data.x_struct.parent.data.p_union.union_val = parent; + struct_val->data.x_struct.parent.data.p_struct.struct_val = parent; + struct_val->data.x_struct.parent.data.p_struct.field_index = parent_field_index; break; case TypeTableEntryIdUnion: + assert(parent_field_index == -1); struct_val->data.x_struct.parent.id = ConstParentIdUnion; struct_val->data.x_struct.parent.data.p_union.union_val = parent; break; @@ -15768,7 +15771,8 @@ static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExpr } } -static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *parent, TypeTableEntry *type_entry) +static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *parent, + ssize_t parent_field_index, TypeTableEntry *type_entry) { assert(type_entry != nullptr); assert(!type_is_invalid(type_entry)); @@ -15802,7 +15806,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(2); payload->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent); + ir_type_info_struct_set_parent(payload, parent, parent_field_index); // is_signed: bool ensure_field_index(payload->type, "is_signed", 0); @@ -15829,7 +15833,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(1); payload->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent); + ir_type_info_struct_set_parent(payload, parent, parent_field_index); // bits: u8 ensure_field_index(payload->type, "bits", 0); @@ -15851,7 +15855,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(4); payload->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent); + ir_type_info_struct_set_parent(payload, parent, parent_field_index); // is_const: bool ensure_field_index(payload->type, "is_const", 0); @@ -15880,7 +15884,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p union_val->special = ConstValSpecialStatic; union_val->type = type_info_type->data.x_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.pointer.child_type->id)); - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, type_entry->data.pointer.child_type); + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, type_entry->data.pointer.child_type); fields[3].data.x_ptr.data.ref.pointee = union_val; return payload; } @@ -15896,7 +15900,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(2); payload->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent); + ir_type_info_struct_set_parent(payload, parent, parent_field_index); // len: usize ensure_field_index(payload->type, "len", 0); @@ -15915,7 +15919,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p union_val->special = ConstValSpecialStatic; union_val->type = type_info_type->data.x_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.array.child_type->id)); - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, type_entry->data.array.child_type); + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, type_entry->data.array.child_type); fields[1].data.x_ptr.data.ref.pointee = union_val; return payload; } @@ -15931,7 +15935,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(1); payload->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent); + ir_type_info_struct_set_parent(payload, parent, parent_field_index); // child: &TypeInfo ensure_field_index(payload->type, "child", 0); @@ -15945,7 +15949,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p union_val->special = ConstValSpecialStatic; union_val->type = type_info_type->data.x_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.maybe.child_type->id)); - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, type_entry->data.maybe.child_type); + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, type_entry->data.maybe.child_type); fields[0].data.x_ptr.data.ref.pointee = union_val; return payload; } @@ -15961,7 +15965,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *fields = create_const_vals(1); payload->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent); + ir_type_info_struct_set_parent(payload, parent, parent_field_index); // child: ?&TypeInfo ensure_field_index(payload->type, "child", 0); @@ -15990,7 +15994,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p union_val->special = ConstValSpecialStatic; union_val->type = type_info_type->data.x_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.promise.result_type->id)); - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, type_entry->data.promise.result_type); + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, type_entry->data.promise.result_type); maybe_value->data.x_ptr.data.ref.pointee = union_val; fields[0].data.x_maybe = maybe_value; @@ -16017,7 +16021,7 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); out_val->type = result_type; bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry->id)); - out_val->data.x_union.payload = ir_make_type_info_value(ira, out_val, type_entry); + out_val->data.x_union.payload = ir_make_type_info_value(ira, out_val, -1, type_entry); return result_type; } From bc160821d33a9284cf8bb85cca6cbf161af71d3b Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Wed, 25 Apr 2018 17:50:11 +0300 Subject: [PATCH 13/35] Changed TypeInfo layout. --- src/codegen.cpp | 236 ++++++++++++++++++++++++------------------------ src/ir.cpp | 89 +++++++++++------- 2 files changed, 174 insertions(+), 151 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 2e7cc937b4a1..7d83a38bbf88 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6349,143 +6349,143 @@ static void define_builtin_compile_vars(CodeGen *g) { { // TODO: Add method info where methods are supported. buf_appendf(contents, - "pub const IntInfo = struct {\n" - " is_signed: bool,\n" - " bits: u8,\n" - "};\n" - "\n" - "pub const FloatInfo = struct {\n" - " bits: u8,\n" - "};\n" + "pub const TypeInfo = union(TypeId) {\n" + " Type: void,\n" + " Void: void,\n" + " Bool: void,\n" + " NoReturn: void,\n" + " Int: Int,\n" + " Float: Float,\n" + " Pointer: Pointer,\n" + " Array: Array,\n" + " Struct: Struct,\n" + " FloatLiteral: void,\n" + " IntLiteral: void,\n" + " UndefinedLiteral: void,\n" + " NullLiteral: void,\n" + " Nullable: Nullable,\n" + " ErrorUnion: ErrorUnion,\n" + " ErrorSet: ErrorSet,\n" + " Enum: Enum,\n" + " Union: Union,\n" + " Fn: Fn,\n" + " Namespace: void,\n" + " Block: void,\n" + " BoundFn: BoundFn,\n" + " ArgTuple: void,\n" + " Opaque: void,\n" + " Promise: Promise,\n" + "\n\n" + " pub const Int = struct {\n" + " is_signed: bool,\n" + " bits: u8,\n" + " };\n" "\n" - "pub const PointerInfo = struct {\n" - " is_const: bool,\n" - " is_volatile: bool,\n" - " alignment: u32,\n" - " child: &TypeInfo,\n" - "};\n" + " pub const Float = struct {\n" + " bits: u8,\n" + " };\n" "\n" - "pub const ArrayInfo = struct {\n" - " len: usize,\n" - " child: &TypeInfo,\n" - "};\n" + " pub const Pointer = struct {\n" + " is_const: bool,\n" + " is_volatile: bool,\n" + " alignment: u32,\n" + " child: &TypeInfo,\n" + " };\n" "\n" - "pub const ContainerLayout = enum {\n" - " Auto,\n" - " Extern,\n" - " Packed,\n" - "};\n" + " pub const Array = struct {\n" + " len: usize,\n" + " child: &TypeInfo,\n" + " };\n" "\n" - "pub const StructFieldInfo = struct {\n" - " name: []const u8,\n" - " offset: usize,\n" - " type_info: TypeInfo,\n" - "};\n" + " pub const ContainerLayout = enum {\n" + " Auto,\n" + " Extern,\n" + " Packed,\n" + " };\n" "\n" - "pub const StructInfo = struct {\n" - " layout: ContainerLayout,\n" - " fields: []StructFieldInfo,\n" - "};\n" + " pub const StructField = struct {\n" + " name: []const u8,\n" + " offset: usize,\n" + " type_info: TypeInfo,\n" + " };\n" "\n" - "pub const NullableInfo = struct {\n" - " child: &TypeInfo,\n" - "};\n" + " pub const Struct = struct {\n" + " layout: ContainerLayout,\n" + " fields: []StructField,\n" + " };\n" "\n" - "pub const ErrorUnionInfo = struct {\n" - " error_set: ErrorSetInfo,\n" - " payload: &TypeInfo,\n" - "};\n" + " pub const Nullable = struct {\n" + " child: &TypeInfo,\n" + " };\n" "\n" - "pub const ErrorInfo = struct {\n" - " name: []const u8,\n" - " value: usize,\n" - "};\n" + " pub const ErrorUnion = struct {\n" + " error_set: ErrorSet,\n" + " payload: &TypeInfo,\n" + " };\n" "\n" - "pub const ErrorSetInfo = struct {\n" - " errors: []ErrorInfo,\n" - "};\n" + " pub const Error = struct {\n" + " name: []const u8,\n" + " value: usize,\n" + " };\n" "\n" - "pub const EnumFieldInfo = struct {\n" - " name: []const u8,\n" - " value: usize,\n" - "};\n" + " pub const ErrorSet = struct {\n" + " errors: []Error,\n" + " };\n" "\n" - "pub const EnumInfo = struct {\n" - " layout: ContainerLayout,\n" - " tag_type: IntInfo,\n" - " fields: []EnumFieldInfo,\n" - "};\n" + " pub const EnumField = struct {\n" + " name: []const u8,\n" + " value: usize,\n" + " };\n" "\n" - "pub const UnionFieldInfo = struct {\n" - " name: []const u8,\n" - " enum_field: EnumFieldInfo,\n" - " type_info: TypeInfo,\n" - "};\n" + " pub const Enum = struct {\n" + " layout: ContainerLayout,\n" + " tag_type: Int,\n" + " fields: []EnumField,\n" + " };\n" "\n" - "pub const UnionInfo = struct {\n" - " layout: ContainerLayout,\n" - " tag_type: ?EnumInfo,\n" - " fields: []UnionFieldInfo,\n" - "};\n" + " pub const UnionField = struct {\n" + " name: []const u8,\n" + " enum_field: EnumField,\n" + " type_info: TypeInfo,\n" + " };\n" "\n" - "pub const CallingConvention = enum {\n" - " Unspecified,\n" - " C,\n" - " Cold,\n" - " Naked,\n" - " Stdcall,\n" - " Async,\n" - "};\n" + " pub const Union = struct {\n" + " layout: ContainerLayout,\n" + " tag_type: ?Enum,\n" + " fields: []UnionField,\n" + " };\n" "\n" - "pub const FnArgInfo = struct {\n" - " is_comptime: bool,\n" - " name: []const u8,\n" - " type_info: TypeInfo,\n" - "};\n" + " pub const CallingConvention = enum {\n" + " Unspecified,\n" + " C,\n" + " Cold,\n" + " Naked,\n" + " Stdcall,\n" + " Async,\n" + " };\n" "\n" - "pub const FnInfo = struct {\n" - " calling_convention: CallingConvention,\n" - " is_generic: bool,\n" - " is_varargs: bool,\n" - " return_type: &TypeInfo,\n" - " args: []FnArgInfo,\n" - "};\n" + " pub const FnArg = struct {\n" + " is_comptime: bool,\n" + " name: []const u8,\n" + " type_info: TypeInfo,\n" + " };\n" "\n" - "pub const BoundFnInfo = struct {\n" - " bound_type: &TypeInfo,\n" - " fn_info: FnInfo,\n" - "};\n" + " pub const Fn = struct {\n" + " calling_convention: CallingConvention,\n" + " is_generic: bool,\n" + " is_varargs: bool,\n" + " return_type: &TypeInfo,\n" + " args: []FnArg,\n" + " };\n" "\n" - "pub const PromiseInfo = struct {\n" - " child: ?&TypeInfo,\n" - "};\n" + " pub const BoundFn = struct {\n" + " bound_type: &TypeInfo,\n" + " fn_info: Fn,\n" + " };\n" "\n" - "pub const TypeInfo = union(TypeId) {\n" - " Type: void,\n" - " Void: void,\n" - " Bool: void,\n" - " NoReturn: void,\n" - " Int: IntInfo,\n" - " Float: FloatInfo,\n" - " Pointer: PointerInfo,\n" - " Array: ArrayInfo,\n" - " Struct: StructInfo,\n" - " FloatLiteral: void,\n" - " IntLiteral: void,\n" - " UndefinedLiteral: void,\n" - " NullLiteral: void,\n" - " Nullable: NullableInfo,\n" - " ErrorUnion: ErrorUnionInfo,\n" - " ErrorSet: ErrorSetInfo,\n" - " Enum: EnumInfo,\n" - " Union: UnionInfo,\n" - " Fn: FnInfo,\n" - " Namespace: void,\n" - " Block: void,\n" - " BoundFn: BoundFnInfo,\n" - " ArgTuple: void,\n" - " Opaque: void,\n" - " Promise: PromiseInfo,\n" + " pub const Promise = struct {\n" + " child: ?&TypeInfo,\n" + " };\n" "};\n\n"); assert(ContainerLayoutAuto == 0); assert(ContainerLayoutExtern == 1); diff --git a/src/ir.cpp b/src/ir.cpp index a68747fce4fb..1f2ef0e68f00 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15737,7 +15737,8 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira, return ira->codegen->builtin_types.entry_num_lit_int; } -static void ensure_field_index(TypeTableEntry *type, const char *field_name, size_t index) { +static void ensure_field_index(TypeTableEntry *type, const char *field_name, size_t index) +{ Buf *field_name_buf; assert(type != nullptr && !type_is_invalid(type)); @@ -15747,7 +15748,8 @@ static void ensure_field_index(TypeTableEntry *type, const char *field_name, siz (buf_deinit(field_name_buf), true)); } -static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExprValue *parent, ssize_t parent_field_index) { +static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExprValue *parent, ssize_t parent_field_index) +{ assert(struct_val->type->id == TypeTableEntryIdStruct); assert(parent->type != nullptr && !type_is_invalid(parent->type)); @@ -15771,6 +15773,37 @@ static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExpr } } +static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_name) +{ + ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); + assert(type_info_var->type->id == TypeTableEntryIdMetaType); + + TypeTableEntry *type_info_type = type_info_var->data.x_type; + assert(type_info_type->id == TypeTableEntryIdUnion); + + if (type_name == nullptr) + return type_info_type; + + // @TODO + + ScopeDecls *type_info_scope = get_container_scope(type_info_type); + assert(type_info_scope != nullptr); + + Buf field_name = BUF_INIT; + buf_init_from_str(&field_name, type_name); + auto entry = type_info_scope->decl_table.maybe_get(&field_name); + buf_deinit(&field_name); + assert(entry != nullptr); + + TldVar *tld = (TldVar *)entry->value; + assert(tld->base.id == TldIdVar); + + VariableTableEntry *var = tld->var; + + assert(var->value->type->id == TypeTableEntryIdMetaType); + return var->value->data.x_type; +} + static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *parent, ssize_t parent_field_index, TypeTableEntry *type_entry) { @@ -15798,10 +15831,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p { ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; - - ConstExprValue *int_info_type = get_builtin_value(ira->codegen, "IntInfo"); - assert(int_info_type->type->id == TypeTableEntryIdMetaType); - payload->type = int_info_type->data.x_type; + payload->type = ir_type_info_get_type(ira, "Int"); ConstExprValue *fields = create_const_vals(2); payload->data.x_struct.fields = fields; @@ -15825,10 +15855,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p { ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; - - ConstExprValue *float_info_type = get_builtin_value(ira->codegen, "FloatInfo"); - assert(float_info_type->type->id == TypeTableEntryIdMetaType); - payload->type = float_info_type->data.x_type; + payload->type = ir_type_info_get_type(ira, "Float"); ConstExprValue *fields = create_const_vals(1); payload->data.x_struct.fields = fields; @@ -15847,10 +15874,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p { ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; - - ConstExprValue *pointer_info_type = get_builtin_value(ira->codegen, "PointerInfo"); - assert(pointer_info_type->type->id == TypeTableEntryIdMetaType); - payload->type = pointer_info_type->data.x_type; + payload->type = ir_type_info_get_type(ira, "Pointer"); ConstExprValue *fields = create_const_vals(4); payload->data.x_struct.fields = fields; @@ -15884,7 +15908,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p union_val->special = ConstValSpecialStatic; union_val->type = type_info_type->data.x_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.pointer.child_type->id)); - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, type_entry->data.pointer.child_type); + + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, + type_entry->data.pointer.child_type); + fields[3].data.x_ptr.data.ref.pointee = union_val; return payload; } @@ -15892,10 +15919,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p { ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; - - ConstExprValue *pointer_info_type = get_builtin_value(ira->codegen, "ArrayInfo"); - assert(pointer_info_type->type->id == TypeTableEntryIdMetaType); - payload->type = pointer_info_type->data.x_type; + payload->type = ir_type_info_get_type(ira, "Array"); ConstExprValue *fields = create_const_vals(2); payload->data.x_struct.fields = fields; @@ -15919,7 +15943,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p union_val->special = ConstValSpecialStatic; union_val->type = type_info_type->data.x_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.array.child_type->id)); - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, type_entry->data.array.child_type); + + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, + type_entry->data.array.child_type); + fields[1].data.x_ptr.data.ref.pointee = union_val; return payload; } @@ -15927,10 +15954,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p { ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; - - ConstExprValue *pointer_info_type = get_builtin_value(ira->codegen, "NullableInfo"); - assert(pointer_info_type->type->id == TypeTableEntryIdMetaType); - payload->type = pointer_info_type->data.x_type; + payload->type = ir_type_info_get_type(ira, "Nullable"); ConstExprValue *fields = create_const_vals(1); payload->data.x_struct.fields = fields; @@ -15949,7 +15973,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p union_val->special = ConstValSpecialStatic; union_val->type = type_info_type->data.x_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.maybe.child_type->id)); - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, type_entry->data.maybe.child_type); + + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, + type_entry->data.maybe.child_type); + fields[0].data.x_ptr.data.ref.pointee = union_val; return payload; } @@ -15957,10 +15984,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p { ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; - - ConstExprValue *pointer_info_type = get_builtin_value(ira->codegen, "PromiseInfo"); - assert(pointer_info_type->type->id == TypeTableEntryIdMetaType); - payload->type = pointer_info_type->data.x_type; + payload->type = ir_type_info_get_type(ira, "Promise"); ConstExprValue *fields = create_const_vals(1); payload->data.x_struct.fields = fields; @@ -15994,7 +16018,8 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p union_val->special = ConstValSpecialStatic; union_val->type = type_info_type->data.x_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.promise.result_type->id)); - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, type_entry->data.promise.result_type); + union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, + type_entry->data.promise.result_type); maybe_value->data.x_ptr.data.ref.pointee = union_val; fields[0].data.x_maybe = maybe_value; @@ -16014,9 +16039,7 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, if (type_is_invalid(type_entry)) return ira->codegen->builtin_types.entry_invalid; - ConstExprValue *var_value = get_builtin_value(ira->codegen, "TypeInfo"); - assert(var_value->type->id == TypeTableEntryIdMetaType); - TypeTableEntry *result_type = var_value->data.x_type; + TypeTableEntry *result_type = ir_type_info_get_type(ira, nullptr); ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); out_val->type = result_type; From dd88d7deda66a4e4e1527831e7b24a3cf358d1b7 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Thu, 26 Apr 2018 13:27:16 +0300 Subject: [PATCH 14/35] Cleanup --- src/ir.cpp | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 1f2ef0e68f00..cbd8d51b3276 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15775,17 +15775,20 @@ static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExpr static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_name) { - ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); - assert(type_info_var->type->id == TypeTableEntryIdMetaType); + static ConstExprValue *type_info_var = nullptr; + static TypeTableEntry *type_info_type = nullptr; + if (type_info_var == nullptr) + { + type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); + assert(type_info_var->type->id == TypeTableEntryIdMetaType); - TypeTableEntry *type_info_type = type_info_var->data.x_type; - assert(type_info_type->id == TypeTableEntryIdUnion); + type_info_type = type_info_var->data.x_type; + assert(type_info_type->id == TypeTableEntryIdUnion); + } if (type_name == nullptr) return type_info_type; - // @TODO - ScopeDecls *type_info_scope = get_container_scope(type_info_type); assert(type_info_scope != nullptr); @@ -15898,15 +15901,16 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p bigint_init_unsigned(&fields[2].data.x_bigint, type_entry->data.pointer.alignment); // child: &TypeInfo ensure_field_index(payload->type, "child", 3); - ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); - assert(type_info_type->type->id == TypeTableEntryIdMetaType); + + TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); + fields[3].special = ConstValSpecialStatic; - fields[3].type = get_pointer_to_type(ira->codegen, type_info_type->data.x_type, false); + fields[3].type = get_pointer_to_type(ira->codegen, type_info_type, false); fields[3].data.x_ptr.special = ConstPtrSpecialRef; fields[3].data.x_ptr.mut = ConstPtrMutComptimeVar; ConstExprValue *union_val = create_const_vals(1); union_val->special = ConstValSpecialStatic; - union_val->type = type_info_type->data.x_type; + union_val->type = type_info_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.pointer.child_type->id)); union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, @@ -15933,15 +15937,16 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.array.len); // child: &TypeInfo ensure_field_index(payload->type, "child", 1); - ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); - assert(type_info_type->type->id == TypeTableEntryIdMetaType); + + TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); + fields[1].special = ConstValSpecialStatic; - fields[1].type = get_pointer_to_type(ira->codegen, type_info_type->data.x_type, false); + fields[1].type = get_pointer_to_type(ira->codegen, type_info_type, false); fields[1].data.x_ptr.special = ConstPtrSpecialRef; fields[1].data.x_ptr.mut = ConstPtrMutComptimeVar; ConstExprValue *union_val = create_const_vals(1); union_val->special = ConstValSpecialStatic; - union_val->type = type_info_type->data.x_type; + union_val->type = type_info_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.array.child_type->id)); union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, @@ -15963,15 +15968,16 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p // child: &TypeInfo ensure_field_index(payload->type, "child", 0); - ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); - assert(type_info_type->type->id == TypeTableEntryIdMetaType); + + TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); + fields[0].special = ConstValSpecialStatic; - fields[0].type = get_pointer_to_type(ira->codegen, type_info_type->data.x_type, false); + fields[0].type = get_pointer_to_type(ira->codegen, type_info_type, false); fields[0].data.x_ptr.special = ConstPtrSpecialRef; fields[0].data.x_ptr.mut = ConstPtrMutComptimeVar; ConstExprValue *union_val = create_const_vals(1); union_val->special = ConstValSpecialStatic; - union_val->type = type_info_type->data.x_type; + union_val->type = type_info_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.maybe.child_type->id)); union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, @@ -15993,10 +15999,9 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p // child: ?&TypeInfo ensure_field_index(payload->type, "child", 0); - ConstExprValue *type_info_type = get_builtin_value(ira->codegen, "TypeInfo"); - assert(type_info_type->type->id == TypeTableEntryIdMetaType); - TypeTableEntry *type_info_ptr_type = get_pointer_to_type(ira->codegen, type_info_type->data.x_type, false); + TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); + TypeTableEntry *type_info_ptr_type = get_pointer_to_type(ira->codegen, type_info_type, false); fields[0].special = ConstValSpecialStatic; fields[0].type = get_maybe_type(ira->codegen, type_info_ptr_type); @@ -16016,7 +16021,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p ConstExprValue *union_val = create_const_vals(1); union_val->special = ConstValSpecialStatic; - union_val->type = type_info_type->data.x_type; + union_val->type = type_info_type; bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.promise.result_type->id)); union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, type_entry->data.promise.result_type); From bb56360bfaa317809bd3c742a655b357bd5b6226 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Thu, 26 Apr 2018 14:03:19 +0300 Subject: [PATCH 15/35] Added TypeInfo cache --- src/all_types.hpp | 1 + src/codegen.cpp | 10 ++++- src/ir.cpp | 109 +++++++++++++++++++++++++--------------------- 3 files changed, 70 insertions(+), 50 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 332fc5204eec..c1c6c9a1a598 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1507,6 +1507,7 @@ struct CodeGen { HashMap exported_symbol_names; HashMap external_prototypes; HashMap string_literals_table; + HashMap type_info_cache; ZigList import_queue; diff --git a/src/codegen.cpp b/src/codegen.cpp index 7d83a38bbf88..71df7fcd65a5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -88,6 +88,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out g->exported_symbol_names.init(8); g->external_prototypes.init(8); g->string_literals_table.init(16); + g->type_info_cache.init(32); g->is_test_build = false; g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); buf_resize(&g->global_asm, 0); @@ -6347,7 +6348,8 @@ static void define_builtin_compile_vars(CodeGen *g) { buf_appendf(contents, "};\n\n"); } { - // TODO: Add method info where methods are supported. + // @TODO Add method info where methods are supported. + // @TODO Add Namespace info. buf_appendf(contents, "pub const TypeInfo = union(TypeId) {\n" " Type: void,\n" @@ -6403,6 +6405,11 @@ static void define_builtin_compile_vars(CodeGen *g) { " Packed,\n" " };\n" "\n" + " pub const Method = struct {\n" + " name: []const u8,\n" + " fn_info: Fn,\n" + " };\n" + "\n" " pub const StructField = struct {\n" " name: []const u8,\n" " offset: usize,\n" @@ -6412,6 +6419,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " pub const Struct = struct {\n" " layout: ContainerLayout,\n" " fields: []StructField,\n" + " methods: []Method,\n" " };\n" "\n" " pub const Nullable = struct {\n" diff --git a/src/ir.cpp b/src/ir.cpp index cbd8d51b3276..9229e4e89dba 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15810,6 +15810,15 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *parent, ssize_t parent_field_index, TypeTableEntry *type_entry) { + // Lookup an available value in our cache. + auto entry = ira->codegen->type_info_cache.maybe_get(type_entry); + if (entry != nullptr) + return entry->value; + + ConstExprValue *result = nullptr; + + // @TODO + // We should probably cache the values generated with a type_entry key. assert(type_entry != nullptr); assert(!type_is_invalid(type_entry)); @@ -15832,75 +15841,73 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p return nullptr; case TypeTableEntryIdInt: { - ConstExprValue *payload = create_const_vals(1); - payload->special = ConstValSpecialStatic; - payload->type = ir_type_info_get_type(ira, "Int"); + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Int"); ConstExprValue *fields = create_const_vals(2); - payload->data.x_struct.fields = fields; + result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent, parent_field_index); + ir_type_info_struct_set_parent(result, parent, parent_field_index); // is_signed: bool - ensure_field_index(payload->type, "is_signed", 0); + ensure_field_index(result->type, "is_signed", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_bool; fields[0].data.x_bool = type_entry->data.integral.is_signed; // bits: u8 - ensure_field_index(payload->type, "bits", 1); + ensure_field_index(result->type, "bits", 1); fields[1].special = ConstValSpecialStatic; fields[1].type = ira->codegen->builtin_types.entry_u8; bigint_init_unsigned(&fields[1].data.x_bigint, type_entry->data.integral.bit_count); - - return payload; + break; } case TypeTableEntryIdFloat: { - ConstExprValue *payload = create_const_vals(1); - payload->special = ConstValSpecialStatic; - payload->type = ir_type_info_get_type(ira, "Float"); + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Float"); ConstExprValue *fields = create_const_vals(1); - payload->data.x_struct.fields = fields; + result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent, parent_field_index); + ir_type_info_struct_set_parent(result, parent, parent_field_index); // bits: u8 - ensure_field_index(payload->type, "bits", 0); + ensure_field_index(result->type, "bits", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_u8; bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.floating.bit_count); - - return payload; + break; } case TypeTableEntryIdPointer: { - ConstExprValue *payload = create_const_vals(1); - payload->special = ConstValSpecialStatic; - payload->type = ir_type_info_get_type(ira, "Pointer"); + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Pointer"); ConstExprValue *fields = create_const_vals(4); - payload->data.x_struct.fields = fields; + result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent, parent_field_index); + ir_type_info_struct_set_parent(result, parent, parent_field_index); // is_const: bool - ensure_field_index(payload->type, "is_const", 0); + ensure_field_index(result->type, "is_const", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_bool; fields[0].data.x_bool = type_entry->data.pointer.is_const; // is_volatile: bool - ensure_field_index(payload->type, "is_volatile", 1); + ensure_field_index(result->type, "is_volatile", 1); fields[1].special = ConstValSpecialStatic; fields[1].type = ira->codegen->builtin_types.entry_bool; fields[1].data.x_bool = type_entry->data.pointer.is_volatile; // alignment: u32 - ensure_field_index(payload->type, "alignment", 2); + ensure_field_index(result->type, "alignment", 2); fields[2].special = ConstValSpecialStatic; fields[2].type = ira->codegen->builtin_types.entry_u32; bigint_init_unsigned(&fields[2].data.x_bigint, type_entry->data.pointer.alignment); // child: &TypeInfo - ensure_field_index(payload->type, "child", 3); + ensure_field_index(result->type, "child", 3); TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); @@ -15917,26 +15924,26 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p type_entry->data.pointer.child_type); fields[3].data.x_ptr.data.ref.pointee = union_val; - return payload; + break; } case TypeTableEntryIdArray: { - ConstExprValue *payload = create_const_vals(1); - payload->special = ConstValSpecialStatic; - payload->type = ir_type_info_get_type(ira, "Array"); + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Array"); ConstExprValue *fields = create_const_vals(2); - payload->data.x_struct.fields = fields; + result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent, parent_field_index); + ir_type_info_struct_set_parent(result, parent, parent_field_index); // len: usize - ensure_field_index(payload->type, "len", 0); + ensure_field_index(result->type, "len", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_usize; bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.array.len); // child: &TypeInfo - ensure_field_index(payload->type, "child", 1); + ensure_field_index(result->type, "child", 1); TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); @@ -15953,21 +15960,21 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p type_entry->data.array.child_type); fields[1].data.x_ptr.data.ref.pointee = union_val; - return payload; + break; } case TypeTableEntryIdMaybe: { - ConstExprValue *payload = create_const_vals(1); - payload->special = ConstValSpecialStatic; - payload->type = ir_type_info_get_type(ira, "Nullable"); + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Nullable"); ConstExprValue *fields = create_const_vals(1); - payload->data.x_struct.fields = fields; + result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent, parent_field_index); + ir_type_info_struct_set_parent(result, parent, parent_field_index); // child: &TypeInfo - ensure_field_index(payload->type, "child", 0); + ensure_field_index(result->type, "child", 0); TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); @@ -15984,21 +15991,21 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p type_entry->data.maybe.child_type); fields[0].data.x_ptr.data.ref.pointee = union_val; - return payload; + break; } case TypeTableEntryIdPromise: { - ConstExprValue *payload = create_const_vals(1); - payload->special = ConstValSpecialStatic; - payload->type = ir_type_info_get_type(ira, "Promise"); + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Promise"); ConstExprValue *fields = create_const_vals(1); - payload->data.x_struct.fields = fields; + result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(payload, parent, parent_field_index); + ir_type_info_struct_set_parent(result, parent, parent_field_index); // child: ?&TypeInfo - ensure_field_index(payload->type, "child", 0); + ensure_field_index(result->type, "child", 0); TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); TypeTableEntry *type_info_ptr_type = get_pointer_to_type(ira->codegen, type_info_type, false); @@ -16029,11 +16036,15 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p maybe_value->data.x_ptr.data.ref.pointee = union_val; fields[0].data.x_maybe = maybe_value; } - return payload; + break; } default: zig_unreachable(); } + + assert(result != nullptr); + ira->codegen->type_info_cache.put(type_entry, result); + return result; } static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, From 7a91e4736a4151bd41b65b6e3b395cc51c443162 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Thu, 26 Apr 2018 14:29:27 +0300 Subject: [PATCH 16/35] Reset parent on cached TypeInfo values if we need to. --- src/codegen.cpp | 3 ++- src/ir.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 71df7fcd65a5..a8c32044fcea 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6348,7 +6348,6 @@ static void define_builtin_compile_vars(CodeGen *g) { buf_appendf(contents, "};\n\n"); } { - // @TODO Add method info where methods are supported. // @TODO Add Namespace info. buf_appendf(contents, "pub const TypeInfo = union(TypeId) {\n" @@ -6449,6 +6448,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " layout: ContainerLayout,\n" " tag_type: Int,\n" " fields: []EnumField,\n" + " methods: []Method,\n" " };\n" "\n" " pub const UnionField = struct {\n" @@ -6461,6 +6461,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " layout: ContainerLayout,\n" " tag_type: ?Enum,\n" " fields: []UnionField,\n" + " methods: []Method,\n" " };\n" "\n" " pub const CallingConvention = enum {\n" diff --git a/src/ir.cpp b/src/ir.cpp index 9229e4e89dba..5cffb882f2b6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15810,17 +15810,61 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *parent, ssize_t parent_field_index, TypeTableEntry *type_entry) { + assert(type_entry != nullptr); + assert(!type_is_invalid(type_entry)); + // Lookup an available value in our cache. auto entry = ira->codegen->type_info_cache.maybe_get(type_entry); if (entry != nullptr) - return entry->value; + { + // Override the parent if we need to. + ConstExprValue *result = entry->value; - ConstExprValue *result = nullptr; + assert(result->type->id == TypeTableEntryIdStruct); - // @TODO - // We should probably cache the values generated with a type_entry key. - assert(type_entry != nullptr); - assert(!type_is_invalid(type_entry)); + ConstParent *curr_parent = &result->data.x_struct.parent; + if (curr_parent->id == ConstParentIdStruct) + { + if (curr_parent->data.p_struct.struct_val == parent && + parent_field_index != -1 && + curr_parent->data.p_struct.field_index == (size_t)parent_field_index) + { + return result; + } + ConstExprValue *new_result = create_const_vals(1); + copy_const_val(new_result, result, true); + ir_type_info_struct_set_parent(new_result, parent, parent_field_index); + return new_result; + } + else if (curr_parent->id == ConstParentIdUnion) + { + if (curr_parent->data.p_union.union_val == parent) + { + return result; + } + ConstExprValue *new_result = create_const_vals(1); + copy_const_val(new_result, result, true); + ir_type_info_struct_set_parent(new_result, parent, parent_field_index); + return new_result; + } + else if (curr_parent->id == ConstParentIdNone) + { + if (parent->type->id != TypeTableEntryIdStruct && + parent->type->id != TypeTableEntryIdArray && + parent->type->id != TypeTableEntryIdUnion) + { + return result; + } + ConstExprValue *new_result = create_const_vals(1); + copy_const_val(new_result, result, true); + ir_type_info_struct_set_parent(new_result, parent, parent_field_index); + return new_result; + } + + return result; + } + + ConstExprValue *result = nullptr; switch (type_entry->id) { @@ -16042,6 +16086,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p zig_unreachable(); } + // Cache the returned value. assert(result != nullptr); ira->codegen->type_info_cache.put(type_entry, result); return result; From f5977f68ebe344ec9c96507322218b87c24804a1 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Thu, 26 Apr 2018 16:41:59 +0300 Subject: [PATCH 17/35] Added Enum TypeInfo except for methods --- src/codegen.cpp | 8 ++-- src/ir.cpp | 125 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 111 insertions(+), 22 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index a8c32044fcea..9c4e5b15553b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6412,7 +6412,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " pub const StructField = struct {\n" " name: []const u8,\n" " offset: usize,\n" - " type_info: TypeInfo,\n" + " type_info: &TypeInfo,\n" " };\n" "\n" " pub const Struct = struct {\n" @@ -6446,7 +6446,7 @@ static void define_builtin_compile_vars(CodeGen *g) { "\n" " pub const Enum = struct {\n" " layout: ContainerLayout,\n" - " tag_type: Int,\n" + " tag_type: &Int,\n" " fields: []EnumField,\n" " methods: []Method,\n" " };\n" @@ -6454,7 +6454,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " pub const UnionField = struct {\n" " name: []const u8,\n" " enum_field: EnumField,\n" - " type_info: TypeInfo,\n" + " type_info: &TypeInfo,\n" " };\n" "\n" " pub const Union = struct {\n" @@ -6476,7 +6476,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " pub const FnArg = struct {\n" " is_comptime: bool,\n" " name: []const u8,\n" - " type_info: TypeInfo,\n" + " type_info: &TypeInfo,\n" " };\n" "\n" " pub const Fn = struct {\n" diff --git a/src/ir.cpp b/src/ir.cpp index 5cffb882f2b6..9ca95d62222d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15864,7 +15864,11 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p return result; } - ConstExprValue *result = nullptr; + // If the value is not present in the cache, we will build it, add it and return it. + // We add values to the cache eagerly, as soon as we have filled out the root object's fields. + // That way, if we need to fetch the value in a recursive call down the line, even if we need to + // copy the value and reajust the parent, the value we get back still points to child values that + // will be filled later. switch (type_entry->id) { @@ -15885,7 +15889,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p return nullptr; case TypeTableEntryIdInt: { - result = create_const_vals(1); + ConstExprValue *result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Int"); @@ -15893,6 +15897,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p result->data.x_struct.fields = fields; ir_type_info_struct_set_parent(result, parent, parent_field_index); + ira->codegen->type_info_cache.put(type_entry, result); // is_signed: bool ensure_field_index(result->type, "is_signed", 0); @@ -15904,11 +15909,12 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p fields[1].special = ConstValSpecialStatic; fields[1].type = ira->codegen->builtin_types.entry_u8; bigint_init_unsigned(&fields[1].data.x_bigint, type_entry->data.integral.bit_count); - break; + + return result; } case TypeTableEntryIdFloat: { - result = create_const_vals(1); + ConstExprValue *result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Float"); @@ -15916,17 +15922,19 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p result->data.x_struct.fields = fields; ir_type_info_struct_set_parent(result, parent, parent_field_index); + ira->codegen->type_info_cache.put(type_entry, result); // bits: u8 ensure_field_index(result->type, "bits", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_u8; bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.floating.bit_count); - break; + + return result; } case TypeTableEntryIdPointer: { - result = create_const_vals(1); + ConstExprValue *result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Pointer"); @@ -15934,6 +15942,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p result->data.x_struct.fields = fields; ir_type_info_struct_set_parent(result, parent, parent_field_index); + ira->codegen->type_info_cache.put(type_entry, result); // is_const: bool ensure_field_index(result->type, "is_const", 0); @@ -15968,11 +15977,12 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p type_entry->data.pointer.child_type); fields[3].data.x_ptr.data.ref.pointee = union_val; - break; + + return result; } case TypeTableEntryIdArray: { - result = create_const_vals(1); + ConstExprValue *result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Array"); @@ -15980,6 +15990,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p result->data.x_struct.fields = fields; ir_type_info_struct_set_parent(result, parent, parent_field_index); + ira->codegen->type_info_cache.put(type_entry, result); // len: usize ensure_field_index(result->type, "len", 0); @@ -15988,7 +15999,6 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.array.len); // child: &TypeInfo ensure_field_index(result->type, "child", 1); - TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); fields[1].special = ConstValSpecialStatic; @@ -16004,11 +16014,12 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p type_entry->data.array.child_type); fields[1].data.x_ptr.data.ref.pointee = union_val; - break; + + return result; } case TypeTableEntryIdMaybe: { - result = create_const_vals(1); + ConstExprValue *result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Nullable"); @@ -16016,6 +16027,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p result->data.x_struct.fields = fields; ir_type_info_struct_set_parent(result, parent, parent_field_index); + ira->codegen->type_info_cache.put(type_entry, result); // child: &TypeInfo ensure_field_index(result->type, "child", 0); @@ -16035,11 +16047,12 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p type_entry->data.maybe.child_type); fields[0].data.x_ptr.data.ref.pointee = union_val; - break; + + return result; } case TypeTableEntryIdPromise: { - result = create_const_vals(1); + ConstExprValue *result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Promise"); @@ -16047,6 +16060,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p result->data.x_struct.fields = fields; ir_type_info_struct_set_parent(result, parent, parent_field_index); + ira->codegen->type_info_cache.put(type_entry, result); // child: ?&TypeInfo ensure_field_index(result->type, "child", 0); @@ -16080,16 +16094,91 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p maybe_value->data.x_ptr.data.ref.pointee = union_val; fields[0].data.x_maybe = maybe_value; } - break; + + return result; + } + case TypeTableEntryIdEnum: + { + ConstExprValue *result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Enum"); + + ConstExprValue *fields = create_const_vals(4); + result->data.x_struct.fields = fields; + + ir_type_info_struct_set_parent(result, parent, parent_field_index); + ira->codegen->type_info_cache.put(type_entry, result); + + // layout: ContainerLayout + ensure_field_index(result->type, "layout", 0); + fields[0].special = ConstValSpecialStatic; + fields[0].type = ir_type_info_get_type(ira, "ContainerLayout"); + bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.enumeration.layout); + // tag_type: &TypeInfo.Int + ensure_field_index(result->type, "tag_type", 1); + + TypeTableEntry *type_info_int_type = ir_type_info_get_type(ira, "Int"); + + fields[1].special = ConstValSpecialStatic; + fields[1].type = get_pointer_to_type(ira->codegen, type_info_int_type, false); + fields[1].data.x_ptr.special = ConstPtrSpecialRef; + fields[1].data.x_ptr.mut = ConstPtrMutComptimeVar; + + ConstExprValue *tag_type_info_struct = ir_make_type_info_value(ira, &fields[1], -1, + type_entry->data.enumeration.tag_int_type); + assert(tag_type_info_struct->type == type_info_int_type); + fields[1].data.x_ptr.data.ref.pointee = tag_type_info_struct; + // fields: []TypeInfo.EnumField + ensure_field_index(result->type, "fields", 2); + + TypeTableEntry *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField"); + // @TODO Those cause a find_struct_type_field assertion to fail (type_entry->data.structure.complete) + // ensure_field_index(type_info_enum_field_type, "name", 0); + // ensure_field_index(type_info_enum_field_type, "value", 1); + + uint32_t enum_field_count = type_entry->data.enumeration.src_field_count; + + ConstExprValue *enum_field_array = create_const_vals(1); + enum_field_array->special = ConstValSpecialStatic; + enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count); + enum_field_array->data.x_array.special = ConstArraySpecialNone; + enum_field_array->data.x_array.s_none.parent.id = ConstParentIdNone; + enum_field_array->data.x_array.s_none.elements = create_const_vals(enum_field_count); + + init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false); + + for (uint32_t enum_field_index = 0; enum_field_index < enum_field_count; enum_field_index++) + { + TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index]; + ConstExprValue *enum_field_val = &enum_field_array->data.x_array.s_none.elements[enum_field_index]; + + enum_field_val->special = ConstValSpecialStatic; + enum_field_val->type = type_info_enum_field_type; + + ConstExprValue *inner_fields = create_const_vals(2); + inner_fields[1].special = ConstValSpecialStatic; + inner_fields[1].type = ira->codegen->builtin_types.entry_usize; + + ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name); + init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(enum_field->name), true); + + bigint_init_bigint(&inner_fields[1].data.x_bigint, &enum_field->value); + + enum_field_val->data.x_struct.fields = inner_fields; + enum_field_val->data.x_struct.parent.id = ConstParentIdArray; + enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array; + enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index; + } + + // @TODO + // methods: []TypeInfo.Method + return result; } default: zig_unreachable(); } - // Cache the returned value. - assert(result != nullptr); - ira->codegen->type_info_cache.put(type_entry, result); - return result; + zig_unreachable(); } static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, From 4aa5d87ada56f9887d49c7a2a80246e0bb9d5fb9 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Thu, 26 Apr 2018 17:14:38 +0300 Subject: [PATCH 18/35] Added ErrorSet TypeInfo generation. --- src/codegen.cpp | 2 +- src/ir.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 9c4e5b15553b..8c56af674c40 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6426,7 +6426,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " };\n" "\n" " pub const ErrorUnion = struct {\n" - " error_set: ErrorSet,\n" + " error_set: &ErrorSet,\n" " payload: &TypeInfo,\n" " };\n" "\n" diff --git a/src/ir.cpp b/src/ir.cpp index 9ca95d62222d..92fd7a70180b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16172,6 +16172,63 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p // @TODO // methods: []TypeInfo.Method + return result; + } + case TypeTableEntryIdErrorSet: + { + ConstExprValue *result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "ErrorSet"); + + ConstExprValue *fields = create_const_vals(1); + result->data.x_struct.fields = fields; + + ir_type_info_struct_set_parent(result, parent, parent_field_index); + ira->codegen->type_info_cache.put(type_entry, result); + + // errors: []TypeInfo.Error + ensure_field_index(result->type, "errors", 0); + + TypeTableEntry *type_info_error_type = ir_type_info_get_type(ira, "Error"); + // @TODO Same as above in Enum TypeInfo generation. + // ensure_field_index(type_info_error_type, "name", 0); + // ensure_field_index(type_info_error_type, "value", 1); + + uint32_t error_count = type_entry->data.error_set.err_count; + ConstExprValue *error_array = create_const_vals(1); + error_array->special = ConstValSpecialStatic; + error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count); + error_array->data.x_array.special = ConstArraySpecialNone; + error_array->data.x_array.s_none.parent.id = ConstParentIdNone; + error_array->data.x_array.s_none.elements = create_const_vals(error_count); + + init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false); + for (uint32_t error_index = 0; error_index < error_count; error_index++) + { + ErrorTableEntry *error = type_entry->data.error_set.errors[error_index]; + ConstExprValue *error_val = &error_array->data.x_array.s_none.elements[error_index]; + + error_val->special = ConstValSpecialStatic; + error_val->type = type_info_error_type; + + ConstExprValue *inner_fields = create_const_vals(2); + inner_fields[1].special = ConstValSpecialStatic; + inner_fields[1].type = ira->codegen->builtin_types.entry_usize; + + ConstExprValue *name = nullptr; + if (error->cached_error_name_val != nullptr) + name = error->cached_error_name_val; + if (name == nullptr) + name = create_const_str_lit(ira->codegen, &error->name); + init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(&error->name), true); + bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value); + + error_val->data.x_struct.fields = inner_fields; + error_val->data.x_struct.parent.id = ConstParentIdArray; + error_val->data.x_struct.parent.data.p_array.array_val = error_array; + error_val->data.x_struct.parent.data.p_array.elem_index = error_index; + } + return result; } default: From fbbbee6b72991b65c31a8eac8f1edfc3d1a88b59 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Thu, 26 Apr 2018 18:18:47 +0300 Subject: [PATCH 19/35] Switched to shallow TypeInfo. --- src/codegen.cpp | 24 ++--- src/ir.cpp | 271 ++++++++++-------------------------------------- 2 files changed, 69 insertions(+), 226 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 8c56af674c40..c8bb5027188a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6390,12 +6390,12 @@ static void define_builtin_compile_vars(CodeGen *g) { " is_const: bool,\n" " is_volatile: bool,\n" " alignment: u32,\n" - " child: &TypeInfo,\n" + " child: type,\n" " };\n" "\n" " pub const Array = struct {\n" " len: usize,\n" - " child: &TypeInfo,\n" + " child: type,\n" " };\n" "\n" " pub const ContainerLayout = enum {\n" @@ -6412,7 +6412,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " pub const StructField = struct {\n" " name: []const u8,\n" " offset: usize,\n" - " type_info: &TypeInfo,\n" + " field_type: type,\n" " };\n" "\n" " pub const Struct = struct {\n" @@ -6422,12 +6422,12 @@ static void define_builtin_compile_vars(CodeGen *g) { " };\n" "\n" " pub const Nullable = struct {\n" - " child: &TypeInfo,\n" + " child: type,\n" " };\n" "\n" " pub const ErrorUnion = struct {\n" " error_set: &ErrorSet,\n" - " payload: &TypeInfo,\n" + " payload: type,\n" " };\n" "\n" " pub const Error = struct {\n" @@ -6446,7 +6446,7 @@ static void define_builtin_compile_vars(CodeGen *g) { "\n" " pub const Enum = struct {\n" " layout: ContainerLayout,\n" - " tag_type: &Int,\n" + " tag_type: type,\n" " fields: []EnumField,\n" " methods: []Method,\n" " };\n" @@ -6454,12 +6454,12 @@ static void define_builtin_compile_vars(CodeGen *g) { " pub const UnionField = struct {\n" " name: []const u8,\n" " enum_field: EnumField,\n" - " type_info: &TypeInfo,\n" + " field_type: type,\n" " };\n" "\n" " pub const Union = struct {\n" " layout: ContainerLayout,\n" - " tag_type: ?Enum,\n" + " tag_type: type,\n" " fields: []UnionField,\n" " methods: []Method,\n" " };\n" @@ -6476,24 +6476,24 @@ static void define_builtin_compile_vars(CodeGen *g) { " pub const FnArg = struct {\n" " is_comptime: bool,\n" " name: []const u8,\n" - " type_info: &TypeInfo,\n" + " arg_type: type,\n" " };\n" "\n" " pub const Fn = struct {\n" " calling_convention: CallingConvention,\n" " is_generic: bool,\n" " is_varargs: bool,\n" - " return_type: &TypeInfo,\n" + " return_type: type,\n" " args: []FnArg,\n" " };\n" "\n" " pub const BoundFn = struct {\n" - " bound_type: &TypeInfo,\n" + " bound_type: type,\n" " fn_info: Fn,\n" " };\n" "\n" " pub const Promise = struct {\n" - " child: ?&TypeInfo,\n" + " child: type,\n" " };\n" "};\n\n"); assert(ContainerLayoutAuto == 0); diff --git a/src/ir.cpp b/src/ir.cpp index 92fd7a70180b..fdf1a0c8ab38 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15748,31 +15748,6 @@ static void ensure_field_index(TypeTableEntry *type, const char *field_name, siz (buf_deinit(field_name_buf), true)); } -static void ir_type_info_struct_set_parent(ConstExprValue *struct_val, ConstExprValue *parent, ssize_t parent_field_index) -{ - assert(struct_val->type->id == TypeTableEntryIdStruct); - assert(parent->type != nullptr && !type_is_invalid(parent->type)); - - switch (parent->type->id) - { - case TypeTableEntryIdArray: - zig_panic("TODO - Only expected struct or union parent."); - case TypeTableEntryIdStruct: - assert(parent_field_index >= 0); - struct_val->data.x_struct.parent.id = ConstParentIdStruct; - struct_val->data.x_struct.parent.data.p_struct.struct_val = parent; - struct_val->data.x_struct.parent.data.p_struct.field_index = parent_field_index; - break; - case TypeTableEntryIdUnion: - assert(parent_field_index == -1); - struct_val->data.x_struct.parent.id = ConstParentIdUnion; - struct_val->data.x_struct.parent.data.p_union.union_val = parent; - break; - default: - struct_val->data.x_struct.parent.id = ConstParentIdNone; - } -} - static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_name) { static ConstExprValue *type_info_var = nullptr; @@ -15807,69 +15782,12 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na return var->value->data.x_type; } -static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *parent, - ssize_t parent_field_index, 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)); - // Lookup an available value in our cache. - auto entry = ira->codegen->type_info_cache.maybe_get(type_entry); - if (entry != nullptr) - { - // Override the parent if we need to. - ConstExprValue *result = entry->value; - - assert(result->type->id == TypeTableEntryIdStruct); - - ConstParent *curr_parent = &result->data.x_struct.parent; - if (curr_parent->id == ConstParentIdStruct) - { - if (curr_parent->data.p_struct.struct_val == parent && - parent_field_index != -1 && - curr_parent->data.p_struct.field_index == (size_t)parent_field_index) - { - return result; - } - ConstExprValue *new_result = create_const_vals(1); - copy_const_val(new_result, result, true); - ir_type_info_struct_set_parent(new_result, parent, parent_field_index); - return new_result; - } - else if (curr_parent->id == ConstParentIdUnion) - { - if (curr_parent->data.p_union.union_val == parent) - { - return result; - } - ConstExprValue *new_result = create_const_vals(1); - copy_const_val(new_result, result, true); - ir_type_info_struct_set_parent(new_result, parent, parent_field_index); - return new_result; - } - else if (curr_parent->id == ConstParentIdNone) - { - if (parent->type->id != TypeTableEntryIdStruct && - parent->type->id != TypeTableEntryIdArray && - parent->type->id != TypeTableEntryIdUnion) - { - return result; - } - ConstExprValue *new_result = create_const_vals(1); - copy_const_val(new_result, result, true); - ir_type_info_struct_set_parent(new_result, parent, parent_field_index); - return new_result; - } - - return result; - } - - // If the value is not present in the cache, we will build it, add it and return it. - // We add values to the cache eagerly, as soon as we have filled out the root object's fields. - // That way, if we need to fetch the value in a recursive call down the line, even if we need to - // copy the value and reajust the parent, the value we get back still points to child values that - // will be filled later. - + ConstExprValue *result = nullptr; switch (type_entry->id) { case TypeTableEntryIdInvalid: @@ -15887,18 +15805,24 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p case TypeTableEntryIdArgTuple: case TypeTableEntryIdOpaque: return nullptr; + default: + { + // Lookup an available value in our cache. + auto entry = ira->codegen->type_info_cache.maybe_get(type_entry); + if (entry != nullptr) + return entry->value; + + // Fallthrough if we don't find one. + } case TypeTableEntryIdInt: { - ConstExprValue *result = create_const_vals(1); + result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Int"); ConstExprValue *fields = create_const_vals(2); result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(result, parent, parent_field_index); - ira->codegen->type_info_cache.put(type_entry, result); - // is_signed: bool ensure_field_index(result->type, "is_signed", 0); fields[0].special = ConstValSpecialStatic; @@ -15910,40 +15834,34 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p fields[1].type = ira->codegen->builtin_types.entry_u8; bigint_init_unsigned(&fields[1].data.x_bigint, type_entry->data.integral.bit_count); - return result; + break; } case TypeTableEntryIdFloat: { - ConstExprValue *result = create_const_vals(1); + result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Float"); ConstExprValue *fields = create_const_vals(1); result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(result, parent, parent_field_index); - ira->codegen->type_info_cache.put(type_entry, result); - // bits: u8 ensure_field_index(result->type, "bits", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_u8; bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.floating.bit_count); - return result; + break; } case TypeTableEntryIdPointer: { - ConstExprValue *result = create_const_vals(1); + result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Pointer"); ConstExprValue *fields = create_const_vals(4); result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(result, parent, parent_field_index); - ira->codegen->type_info_cache.put(type_entry, result); - // is_const: bool ensure_field_index(result->type, "is_const", 0); fields[0].special = ConstValSpecialStatic; @@ -15959,175 +15877,94 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p fields[2].special = ConstValSpecialStatic; fields[2].type = ira->codegen->builtin_types.entry_u32; bigint_init_unsigned(&fields[2].data.x_bigint, type_entry->data.pointer.alignment); - // child: &TypeInfo + // child: type ensure_field_index(result->type, "child", 3); - - TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); - fields[3].special = ConstValSpecialStatic; - fields[3].type = get_pointer_to_type(ira->codegen, type_info_type, false); - fields[3].data.x_ptr.special = ConstPtrSpecialRef; - fields[3].data.x_ptr.mut = ConstPtrMutComptimeVar; - ConstExprValue *union_val = create_const_vals(1); - union_val->special = ConstValSpecialStatic; - union_val->type = type_info_type; - bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.pointer.child_type->id)); + fields[3].type = ira->codegen->builtin_types.entry_type; + fields[3].data.x_type = type_entry->data.pointer.child_type; - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, - type_entry->data.pointer.child_type); - - fields[3].data.x_ptr.data.ref.pointee = union_val; - - return result; + break; } case TypeTableEntryIdArray: { - ConstExprValue *result = create_const_vals(1); + result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Array"); ConstExprValue *fields = create_const_vals(2); result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(result, parent, parent_field_index); - ira->codegen->type_info_cache.put(type_entry, result); - // len: usize ensure_field_index(result->type, "len", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ira->codegen->builtin_types.entry_usize; bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.array.len); - // child: &TypeInfo + // child: type ensure_field_index(result->type, "child", 1); - TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); - fields[1].special = ConstValSpecialStatic; - fields[1].type = get_pointer_to_type(ira->codegen, type_info_type, false); - fields[1].data.x_ptr.special = ConstPtrSpecialRef; - fields[1].data.x_ptr.mut = ConstPtrMutComptimeVar; - ConstExprValue *union_val = create_const_vals(1); - union_val->special = ConstValSpecialStatic; - union_val->type = type_info_type; - bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.array.child_type->id)); + fields[1].type = ira->codegen->builtin_types.entry_type; + fields[1].data.x_type = type_entry->data.array.child_type; - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, - type_entry->data.array.child_type); - - fields[1].data.x_ptr.data.ref.pointee = union_val; - - return result; + break; } case TypeTableEntryIdMaybe: { - ConstExprValue *result = create_const_vals(1); + result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Nullable"); ConstExprValue *fields = create_const_vals(1); result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(result, parent, parent_field_index); - ira->codegen->type_info_cache.put(type_entry, result); - - // child: &TypeInfo + // child: type ensure_field_index(result->type, "child", 0); - - TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); - fields[0].special = ConstValSpecialStatic; - fields[0].type = get_pointer_to_type(ira->codegen, type_info_type, false); - fields[0].data.x_ptr.special = ConstPtrSpecialRef; - fields[0].data.x_ptr.mut = ConstPtrMutComptimeVar; - ConstExprValue *union_val = create_const_vals(1); - union_val->special = ConstValSpecialStatic; - union_val->type = type_info_type; - bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.maybe.child_type->id)); - - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, - type_entry->data.maybe.child_type); - - fields[0].data.x_ptr.data.ref.pointee = union_val; + fields[0].type = ira->codegen->builtin_types.entry_type; + fields[0].data.x_type = type_entry->data.maybe.child_type; - return result; + break; } case TypeTableEntryIdPromise: { - ConstExprValue *result = create_const_vals(1); + result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Promise"); ConstExprValue *fields = create_const_vals(1); result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(result, parent, parent_field_index); - ira->codegen->type_info_cache.put(type_entry, result); - - // child: ?&TypeInfo + // @TODO ?type instead of using @typeOf(undefined) when we have no type. + // child: type ensure_field_index(result->type, "child", 0); - - TypeTableEntry *type_info_type = ir_type_info_get_type(ira, nullptr); - TypeTableEntry *type_info_ptr_type = get_pointer_to_type(ira->codegen, type_info_type, false); - fields[0].special = ConstValSpecialStatic; - fields[0].type = get_maybe_type(ira->codegen, type_info_ptr_type); + fields[0].type = ira->codegen->builtin_types.entry_type; if (type_entry->data.promise.result_type == nullptr) - { - fields[0].data.x_maybe = nullptr; - } + fields[0].data.x_type = ira->codegen->builtin_types.entry_undef; else - { - ConstExprValue *maybe_value = create_const_vals(1); - maybe_value->special = ConstValSpecialStatic; - maybe_value->type = type_info_ptr_type; - - maybe_value->data.x_ptr.special = ConstPtrSpecialRef; - maybe_value->data.x_ptr.mut = ConstPtrMutComptimeVar; - - ConstExprValue *union_val = create_const_vals(1); - union_val->special = ConstValSpecialStatic; - union_val->type = type_info_type; - bigint_init_unsigned(&union_val->data.x_union.tag, type_id_index(type_entry->data.promise.result_type->id)); - union_val->data.x_union.payload = ir_make_type_info_value(ira, union_val, -1, - type_entry->data.promise.result_type); - - maybe_value->data.x_ptr.data.ref.pointee = union_val; - fields[0].data.x_maybe = maybe_value; - } + fields[0].data.x_type = type_entry->data.promise.result_type; - return result; + break; } case TypeTableEntryIdEnum: { - ConstExprValue *result = create_const_vals(1); + result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Enum"); ConstExprValue *fields = create_const_vals(4); result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(result, parent, parent_field_index); - ira->codegen->type_info_cache.put(type_entry, result); - // layout: ContainerLayout ensure_field_index(result->type, "layout", 0); fields[0].special = ConstValSpecialStatic; fields[0].type = ir_type_info_get_type(ira, "ContainerLayout"); bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.enumeration.layout); - // tag_type: &TypeInfo.Int + // tag_type: type ensure_field_index(result->type, "tag_type", 1); - - TypeTableEntry *type_info_int_type = ir_type_info_get_type(ira, "Int"); - fields[1].special = ConstValSpecialStatic; - fields[1].type = get_pointer_to_type(ira->codegen, type_info_int_type, false); - fields[1].data.x_ptr.special = ConstPtrSpecialRef; - fields[1].data.x_ptr.mut = ConstPtrMutComptimeVar; - - ConstExprValue *tag_type_info_struct = ir_make_type_info_value(ira, &fields[1], -1, - type_entry->data.enumeration.tag_int_type); - assert(tag_type_info_struct->type == type_info_int_type); - fields[1].data.x_ptr.data.ref.pointee = tag_type_info_struct; + fields[1].type = ira->codegen->builtin_types.entry_type; + fields[1].data.x_type = type_entry->data.enumeration.tag_int_type; // fields: []TypeInfo.EnumField ensure_field_index(result->type, "fields", 2); @@ -16172,20 +16009,17 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p // @TODO // methods: []TypeInfo.Method - return result; + break; } case TypeTableEntryIdErrorSet: { - ConstExprValue *result = create_const_vals(1); + result = create_const_vals(1); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "ErrorSet"); ConstExprValue *fields = create_const_vals(1); result->data.x_struct.fields = fields; - ir_type_info_struct_set_parent(result, parent, parent_field_index); - ira->codegen->type_info_cache.put(type_entry, result); - // errors: []TypeInfo.Error ensure_field_index(result->type, "errors", 0); @@ -16229,13 +16063,13 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, ConstExprValue *p error_val->data.x_struct.parent.data.p_array.elem_index = error_index; } - return result; + break; } - default: - zig_unreachable(); } - zig_unreachable(); + assert(result != nullptr); + ira->codegen->type_info_cache.put(type_entry, result); + return result; } static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, @@ -16251,7 +16085,16 @@ static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira, ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); out_val->type = result_type; bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry->id)); - out_val->data.x_union.payload = ir_make_type_info_value(ira, out_val, -1, type_entry); + + ConstExprValue *payload = ir_make_type_info_value(ira, type_entry); + out_val->data.x_union.payload = payload; + + if (payload != nullptr) + { + assert(payload->type->id == TypeTableEntryIdStruct); + payload->data.x_struct.parent.id = ConstParentIdUnion; + payload->data.x_struct.parent.data.p_union.union_val = out_val; + } return result_type; } From 884e32d5c3aac470cdcd9b20e15554d6193f5501 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Thu, 26 Apr 2018 19:56:34 +0300 Subject: [PATCH 20/35] Added ErrorUnion, Union TypeInfo generation --- src/codegen.cpp | 2 +- src/ir.cpp | 140 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 127 insertions(+), 15 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index c8bb5027188a..77794c2ab9f3 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6426,7 +6426,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " };\n" "\n" " pub const ErrorUnion = struct {\n" - " error_set: &ErrorSet,\n" + " error_set: type,\n" " payload: type,\n" " };\n" "\n" diff --git a/src/ir.cpp b/src/ir.cpp index fdf1a0c8ab38..f91d1c3edfb4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15787,6 +15787,27 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t assert(type_entry != nullptr); assert(!type_is_invalid(type_entry)); + const auto make_enum_field_val = [ira](ConstExprValue *enum_field_val, TypeEnumField *enum_field) { + TypeTableEntry *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField"); + // @TODO Those cause a find_struct_type_field assertion to fail (type_entry->data.structure.complete) + // ensure_field_index(type_info_enum_field_type, "name", 0); + // ensure_field_index(type_info_enum_field_type, "value", 1); + + enum_field_val->special = ConstValSpecialStatic; + enum_field_val->type = type_info_enum_field_type; + + ConstExprValue *inner_fields = create_const_vals(2); + inner_fields[1].special = ConstValSpecialStatic; + inner_fields[1].type = ira->codegen->builtin_types.entry_usize; + + ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name); + init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(enum_field->name), true); + + bigint_init_bigint(&inner_fields[1].data.x_bigint, &enum_field->value); + + enum_field_val->data.x_struct.fields = inner_fields; + }; + ConstExprValue *result = nullptr; switch (type_entry->id) { @@ -15988,20 +16009,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t { TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index]; ConstExprValue *enum_field_val = &enum_field_array->data.x_array.s_none.elements[enum_field_index]; - - enum_field_val->special = ConstValSpecialStatic; - enum_field_val->type = type_info_enum_field_type; - - ConstExprValue *inner_fields = create_const_vals(2); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = ira->codegen->builtin_types.entry_usize; - - ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(enum_field->name), true); - - bigint_init_bigint(&inner_fields[1].data.x_bigint, &enum_field->value); - - enum_field_val->data.x_struct.fields = inner_fields; + make_enum_field_val(enum_field_val, enum_field); enum_field_val->data.x_struct.parent.id = ConstParentIdArray; enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array; enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index; @@ -16063,6 +16071,110 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t error_val->data.x_struct.parent.data.p_array.elem_index = error_index; } + break; + } + case TypeTableEntryIdErrorUnion: + { + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "ErrorUnion"); + + ConstExprValue *fields = create_const_vals(2); + result->data.x_struct.fields = fields; + + // error_set: type + ensure_field_index(result->type, "error_set", 0); + fields[0].special = ConstValSpecialStatic; + fields[0].type = ira->codegen->builtin_types.entry_type; + fields[0].data.x_type = type_entry->data.error_union.err_set_type; + + // payload: type + ensure_field_index(result->type, "payload", 1); + fields[1].special = ConstValSpecialStatic; + fields[1].type = ira->codegen->builtin_types.entry_type; + fields[1].data.x_type = type_entry->data.error_union.payload_type; + + break; + } + case TypeTableEntryIdUnion: + { + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Union"); + + ConstExprValue *fields = create_const_vals(4); + result->data.x_struct.fields = fields; + + // layout: ContainerLayout + ensure_field_index(result->type, "layout", 0); + fields[0].special = ConstValSpecialStatic; + fields[0].type = ir_type_info_get_type(ira, "ContainerLayout"); + bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.unionation.layout); + // tag_type: type + ensure_field_index(result->type, "tag_type", 1); + fields[1].special = ConstValSpecialStatic; + fields[1].type = ira->codegen->builtin_types.entry_type; + // @TODO ?type instead of using @typeOf(undefined) when we have no type. + if (type_entry->data.unionation.tag_type == nullptr) + fields[1].data.x_type = ira->codegen->builtin_types.entry_undef; + else + fields[1].data.x_type = type_entry->data.unionation.tag_type; + + fields[1].data.x_type = type_entry->data.unionation.tag_type; + // fields: []TypeInfo.UnionField + ensure_field_index(result->type, "fields", 2); + + TypeTableEntry *type_info_union_field_type = ir_type_info_get_type(ira, "UnionField"); + // @TODO Those cause a find_struct_type_field assertion to fail (type_entry->data.structure.complete) + // ensure_field_index(type_info_union_field_type, "name", 0); + // ensure_field_index(type_info_union_field_type, "enum_field", 1); + // ensure_field_index(type_info_union_field_type, "field_type", 2); + + uint32_t union_field_count = type_entry->data.unionation.src_field_count; + + ConstExprValue *union_field_array = create_const_vals(1); + union_field_array->special = ConstValSpecialStatic; + union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count); + union_field_array->data.x_array.special = ConstArraySpecialNone; + union_field_array->data.x_array.s_none.parent.id = ConstParentIdNone; + union_field_array->data.x_array.s_none.elements = create_const_vals(union_field_count); + + init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false); + + for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++) + { + TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index]; + ConstExprValue *union_field_val = &union_field_array->data.x_array.s_none.elements[union_field_index]; + + union_field_val->special = ConstValSpecialStatic; + union_field_val->type = type_info_union_field_type; + + ConstExprValue *inner_fields = create_const_vals(3); + inner_fields[1].special = ConstValSpecialStatic; + make_enum_field_val(&inner_fields[1], union_field->enum_field); + inner_fields[1].data.x_struct.parent.id = ConstParentIdStruct; + inner_fields[1].data.x_struct.parent.data.p_struct.struct_val = union_field_val; + inner_fields[1].data.x_struct.parent.data.p_struct.field_index = 1; + + inner_fields[2].special = ConstValSpecialStatic; + inner_fields[2].type = ira->codegen->builtin_types.entry_type; + inner_fields[2].data.x_type = union_field->type_entry; + + ConstExprValue *name = create_const_str_lit(ira->codegen, union_field->name); + init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true); + + + union_field_val->data.x_struct.fields = inner_fields; + union_field_val->data.x_struct.parent.id = ConstParentIdArray; + union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array; + union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index; + + // @TODO Check if TypeUnionField::enum_field == nullptr when tag_type == nullptr + // If it is, make enum_field: ?EnumField, set it when available, done. + } + + // @TODO + // methods: []TypeInfo.Method break; } } From 9041d0d37e59e3f07d568f93bd680cc0065d1cd2 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Fri, 27 Apr 2018 02:05:24 +0300 Subject: [PATCH 21/35] Fixed enum tag type detection in TypeInfo generation. --- src/codegen.cpp | 8 ++++++- src/ir.cpp | 56 ++++++++++++++++++++----------------------------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 77794c2ab9f3..b6236197cc89 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6349,6 +6349,12 @@ static void define_builtin_compile_vars(CodeGen *g) { } { // @TODO Add Namespace info. + // @TODO Methods -> definitions + // @TODO Includes type definitions (name + type bound) + functions + const variable definitions (+ type of variable) + // @TODO Type definitions are defined as variable definitions of type 'type' + // @TODO This should give us everything available. + // @TODO An alternative is exposing the value of every variable definition, check out if it's possible and wether we want that. + // @TODO I don't think so, @field gives it to us for free. buf_appendf(contents, "pub const TypeInfo = union(TypeId) {\n" " Type: void,\n" @@ -6453,7 +6459,7 @@ static void define_builtin_compile_vars(CodeGen *g) { "\n" " pub const UnionField = struct {\n" " name: []const u8,\n" - " enum_field: EnumField,\n" + " enum_field: ?EnumField,\n" " field_type: type,\n" " };\n" "\n" diff --git a/src/ir.cpp b/src/ir.cpp index f91d1c3edfb4..a6012b0a91ff 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15787,8 +15787,8 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t assert(type_entry != nullptr); assert(!type_is_invalid(type_entry)); - const auto make_enum_field_val = [ira](ConstExprValue *enum_field_val, TypeEnumField *enum_field) { - TypeTableEntry *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField"); + const auto make_enum_field_val = [ira](ConstExprValue *enum_field_val, TypeEnumField *enum_field, + TypeTableEntry *type_info_enum_field_type) { // @TODO Those cause a find_struct_type_field assertion to fail (type_entry->data.structure.complete) // ensure_field_index(type_info_enum_field_type, "name", 0); // ensure_field_index(type_info_enum_field_type, "value", 1); @@ -15990,10 +15990,6 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t ensure_field_index(result->type, "fields", 2); TypeTableEntry *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField"); - // @TODO Those cause a find_struct_type_field assertion to fail (type_entry->data.structure.complete) - // ensure_field_index(type_info_enum_field_type, "name", 0); - // ensure_field_index(type_info_enum_field_type, "value", 1); - uint32_t enum_field_count = type_entry->data.enumeration.src_field_count; ConstExprValue *enum_field_array = create_const_vals(1); @@ -16009,14 +16005,13 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t { TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index]; ConstExprValue *enum_field_val = &enum_field_array->data.x_array.s_none.elements[enum_field_index]; - make_enum_field_val(enum_field_val, enum_field); + make_enum_field_val(enum_field_val, enum_field, type_info_enum_field_type); enum_field_val->data.x_struct.parent.id = ConstParentIdArray; enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array; enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index; } - // @TODO - // methods: []TypeInfo.Method + // @TODO Definitions break; } case TypeTableEntryIdErrorSet: @@ -16032,10 +16027,6 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t ensure_field_index(result->type, "errors", 0); TypeTableEntry *type_info_error_type = ir_type_info_get_type(ira, "Error"); - // @TODO Same as above in Enum TypeInfo generation. - // ensure_field_index(type_info_error_type, "name", 0); - // ensure_field_index(type_info_error_type, "value", 1); - uint32_t error_count = type_entry->data.error_set.err_count; ConstExprValue *error_array = create_const_vals(1); error_array->special = ConstValSpecialStatic; @@ -16115,21 +16106,18 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t fields[1].special = ConstValSpecialStatic; fields[1].type = ira->codegen->builtin_types.entry_type; // @TODO ?type instead of using @typeOf(undefined) when we have no type. - if (type_entry->data.unionation.tag_type == nullptr) - fields[1].data.x_type = ira->codegen->builtin_types.entry_undef; - else + AstNode *union_decl_node = type_entry->data.unionation.decl_node; + if (union_decl_node->data.container_decl.auto_enum || + union_decl_node->data.container_decl.init_arg_expr != nullptr) + { fields[1].data.x_type = type_entry->data.unionation.tag_type; - - fields[1].data.x_type = type_entry->data.unionation.tag_type; + } + else + fields[1].data.x_type = ira->codegen->builtin_types.entry_undef; // fields: []TypeInfo.UnionField ensure_field_index(result->type, "fields", 2); TypeTableEntry *type_info_union_field_type = ir_type_info_get_type(ira, "UnionField"); - // @TODO Those cause a find_struct_type_field assertion to fail (type_entry->data.structure.complete) - // ensure_field_index(type_info_union_field_type, "name", 0); - // ensure_field_index(type_info_union_field_type, "enum_field", 1); - // ensure_field_index(type_info_union_field_type, "field_type", 2); - uint32_t union_field_count = type_entry->data.unionation.src_field_count; ConstExprValue *union_field_array = create_const_vals(1); @@ -16141,6 +16129,8 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false); + TypeTableEntry *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField"); + for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++) { TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index]; @@ -16151,10 +16141,15 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t ConstExprValue *inner_fields = create_const_vals(3); inner_fields[1].special = ConstValSpecialStatic; - make_enum_field_val(&inner_fields[1], union_field->enum_field); - inner_fields[1].data.x_struct.parent.id = ConstParentIdStruct; - inner_fields[1].data.x_struct.parent.data.p_struct.struct_val = union_field_val; - inner_fields[1].data.x_struct.parent.data.p_struct.field_index = 1; + inner_fields[1].type = get_maybe_type(ira->codegen, type_info_enum_field_type); + + if (fields[1].data.x_type == ira->codegen->builtin_types.entry_undef) + inner_fields[1].data.x_maybe = nullptr; + else + { + inner_fields[1].data.x_maybe = create_const_vals(1); + make_enum_field_val(inner_fields[1].data.x_maybe, union_field->enum_field, type_info_enum_field_type); + } inner_fields[2].special = ConstValSpecialStatic; inner_fields[2].type = ira->codegen->builtin_types.entry_type; @@ -16163,18 +16158,13 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t ConstExprValue *name = create_const_str_lit(ira->codegen, union_field->name); init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true); - union_field_val->data.x_struct.fields = inner_fields; union_field_val->data.x_struct.parent.id = ConstParentIdArray; union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array; union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index; - - // @TODO Check if TypeUnionField::enum_field == nullptr when tag_type == nullptr - // If it is, make enum_field: ?EnumField, set it when available, done. } - // @TODO - // methods: []TypeInfo.Method + // @TODO Definitions break; } } From a2dadbc206f80dcf39b42f3be97a8d74795d0381 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Fri, 27 Apr 2018 02:52:09 +0300 Subject: [PATCH 22/35] Added struct TypeInfo generation. --- src/codegen.cpp | 2 +- src/ir.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index b6236197cc89..873cf18072d7 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6417,7 +6417,7 @@ static void define_builtin_compile_vars(CodeGen *g) { "\n" " pub const StructField = struct {\n" " name: []const u8,\n" - " offset: usize,\n" + " offset: ?usize,\n" " field_type: type,\n" " };\n" "\n" diff --git a/src/ir.cpp b/src/ir.cpp index a6012b0a91ff..f167d76ca14c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15787,6 +15787,8 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t assert(type_entry != nullptr); assert(!type_is_invalid(type_entry)); + ensure_complete_type(ira->codegen, type_entry); + const auto make_enum_field_val = [ira](ConstExprValue *enum_field_val, TypeEnumField *enum_field, TypeTableEntry *type_info_enum_field_type) { // @TODO Those cause a find_struct_type_field assertion to fail (type_entry->data.structure.complete) @@ -16164,6 +16166,72 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index; } + // @TODO Definitions + break; + } + case TypeTableEntryIdStruct: + { + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Struct"); + + ConstExprValue *fields = create_const_vals(3); + result->data.x_struct.fields = fields; + + // layout: ContainerLayout + ensure_field_index(result->type, "layout", 0); + fields[0].special = ConstValSpecialStatic; + fields[0].type = ir_type_info_get_type(ira, "ContainerLayout"); + bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.structure.layout); + // fields: []TypeInfo.StructField + ensure_field_index(result->type, "fields", 1); + + TypeTableEntry *type_info_struct_field_type = ir_type_info_get_type(ira, "StructField"); + uint32_t struct_field_count = type_entry->data.structure.src_field_count; + + ConstExprValue *struct_field_array = create_const_vals(1); + struct_field_array->special = ConstValSpecialStatic; + struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count); + struct_field_array->data.x_array.special = ConstArraySpecialNone; + struct_field_array->data.x_array.s_none.parent.id = ConstParentIdNone; + struct_field_array->data.x_array.s_none.elements = create_const_vals(struct_field_count); + + init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false); + + for (uint32_t struct_field_index = 0; struct_field_index < struct_field_count; struct_field_index++) + { + TypeStructField *struct_field = &type_entry->data.structure.fields[struct_field_index]; + ConstExprValue *struct_field_val = &struct_field_array->data.x_array.s_none.elements[struct_field_index]; + + struct_field_val->special = ConstValSpecialStatic; + struct_field_val->type = type_info_struct_field_type; + + ConstExprValue *inner_fields = create_const_vals(3); + inner_fields[1].special = ConstValSpecialStatic; + inner_fields[1].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_usize); + + if (!type_has_bits(struct_field->type_entry)) + inner_fields[1].data.x_maybe = nullptr; + else + { + size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, type_entry->type_ref, struct_field->gen_index); + inner_fields[1].data.x_maybe = create_const_vals(1); + inner_fields[1].data.x_maybe->type = ira->codegen->builtin_types.entry_usize; + bigint_init_unsigned(&inner_fields[1].data.x_maybe->data.x_bigint, byte_offset); + } + + inner_fields[2].special = ConstValSpecialStatic; + inner_fields[2].type = ira->codegen->builtin_types.entry_type; + inner_fields[2].data.x_type = struct_field->type_entry; + + ConstExprValue *name = create_const_str_lit(ira->codegen, struct_field->name); + init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true); + + struct_field_val->data.x_struct.fields = inner_fields; + struct_field_val->data.x_struct.parent.id = ConstParentIdArray; + struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array; + struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index; + } // @TODO Definitions break; } From 8f703f919f13e23b2c09f577a446aabb7799e27c Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Fri, 27 Apr 2018 04:29:50 +0300 Subject: [PATCH 23/35] Added Fn TypeInfo generation. --- src/codegen.cpp | 7 ++-- src/ir.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 873cf18072d7..ee85d7d3c428 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6480,16 +6480,17 @@ static void define_builtin_compile_vars(CodeGen *g) { " };\n" "\n" " pub const FnArg = struct {\n" - " is_comptime: bool,\n" - " name: []const u8,\n" + " is_generic: bool,\n" + " is_noalias: bool,\n" " arg_type: type,\n" " };\n" "\n" " pub const Fn = struct {\n" " calling_convention: CallingConvention,\n" " is_generic: bool,\n" - " is_varargs: bool,\n" + " is_var_args: bool,\n" " return_type: type,\n" + " async_allocator_type: type,\n" " args: []FnArg,\n" " };\n" "\n" diff --git a/src/ir.cpp b/src/ir.cpp index f167d76ca14c..a7076a3243d4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16233,6 +16233,98 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index; } // @TODO Definitions + break; + } + case TypeTableEntryIdFn: + { + result = create_const_vals(1); + result->special = ConstValSpecialStatic; + result->type = ir_type_info_get_type(ira, "Fn"); + + ConstExprValue *fields = create_const_vals(5); + result->data.x_struct.fields = fields; + + // @TODO Fix type = undefined with ?type + + // calling_convention: TypeInfo.CallingConvention + ensure_field_index(result->type, "calling_convention", 0); + fields[0].special = ConstValSpecialStatic; + fields[0].type = ir_type_info_get_type(ira, "CallingConvention"); + bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.fn.fn_type_id.cc); + // is_generic: bool + ensure_field_index(result->type, "is_generic", 1); + bool is_generic = type_entry->data.fn.is_generic; + fields[1].special = ConstValSpecialStatic; + fields[1].type = ira->codegen->builtin_types.entry_bool; + fields[1].data.x_bool = is_generic; + // is_varargs: bool + ensure_field_index(result->type, "is_var_args", 2); + bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args; + fields[2].special = ConstValSpecialStatic; + fields[2].type = ira->codegen->builtin_types.entry_bool; + fields[2].data.x_bool = type_entry->data.fn.fn_type_id.is_var_args; + // return_type: type + ensure_field_index(result->type, "return_type", 3); + fields[3].special = ConstValSpecialStatic; + fields[3].type = ira->codegen->builtin_types.entry_type; + if (type_entry->data.fn.fn_type_id.return_type == nullptr) + fields[3].data.x_type = ira->codegen->builtin_types.entry_undef; + else + fields[3].data.x_type = type_entry->data.fn.fn_type_id.return_type; + // async_allocator_type: type + ensure_field_index(result->type, "async_allocator_type", 4); + fields[4].special = ConstValSpecialStatic; + fields[4].type = ira->codegen->builtin_types.entry_type; + if (type_entry->data.fn.fn_type_id.async_allocator_type == nullptr) + fields[4].data.x_type = ira->codegen->builtin_types.entry_undef; + else + fields[4].data.x_type = type_entry->data.fn.fn_type_id.async_allocator_type; + // args: []TypeInfo.FnArg + TypeTableEntry *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg"); + size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count - + (is_varargs && type_entry->data.fn.fn_type_id.cc != CallingConventionC); + + ConstExprValue *fn_arg_array = create_const_vals(1); + fn_arg_array->special = ConstValSpecialStatic; + fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count); + fn_arg_array->data.x_array.special = ConstArraySpecialNone; + fn_arg_array->data.x_array.s_none.parent.id = ConstParentIdNone; + fn_arg_array->data.x_array.s_none.elements = create_const_vals(fn_arg_count); + + init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false); + + for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) + { + FnTypeParamInfo *fn_param_info = &type_entry->data.fn.fn_type_id.param_info[fn_arg_index]; + ConstExprValue *fn_arg_val = &fn_arg_array->data.x_array.s_none.elements[fn_arg_index]; + + fn_arg_val->special = ConstValSpecialStatic; + fn_arg_val->type = type_info_fn_arg_type; + + bool arg_is_generic = fn_param_info->type == nullptr; + if (arg_is_generic) assert(is_generic); + + ConstExprValue *inner_fields = create_const_vals(3); + inner_fields[0].special = ConstValSpecialStatic; + inner_fields[0].type = ira->codegen->builtin_types.entry_bool; + inner_fields[0].data.x_bool = arg_is_generic; + inner_fields[1].special = ConstValSpecialStatic; + inner_fields[1].type = ira->codegen->builtin_types.entry_bool; + inner_fields[1].data.x_bool = fn_param_info->is_noalias; + inner_fields[2].special = ConstValSpecialStatic; + inner_fields[2].type = ira->codegen->builtin_types.entry_type; + + if (arg_is_generic) + inner_fields[2].data.x_type = ira->codegen->builtin_types.entry_undef; + else + inner_fields[2].data.x_type = fn_param_info->type; + + fn_arg_val->data.x_struct.fields = inner_fields; + fn_arg_val->data.x_struct.parent.id = ConstParentIdArray; + fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array; + fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index; + } + break; } } From ea2596280fc2c78f71b08921db3a4c9826eb93e0 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Fri, 27 Apr 2018 05:10:20 +0300 Subject: [PATCH 24/35] Added BoundFn TypeInfo generation. --- src/codegen.cpp | 7 +------ src/ir.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index ee85d7d3c428..fc872e1908ba 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6378,7 +6378,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " Fn: Fn,\n" " Namespace: void,\n" " Block: void,\n" - " BoundFn: BoundFn,\n" + " BoundFn: Fn,\n" " ArgTuple: void,\n" " Opaque: void,\n" " Promise: Promise,\n" @@ -6494,11 +6494,6 @@ static void define_builtin_compile_vars(CodeGen *g) { " args: []FnArg,\n" " };\n" "\n" - " pub const BoundFn = struct {\n" - " bound_type: type,\n" - " fn_info: Fn,\n" - " };\n" - "\n" " pub const Promise = struct {\n" " child: type,\n" " };\n" diff --git a/src/ir.cpp b/src/ir.cpp index a7076a3243d4..c2da83886a53 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16241,7 +16241,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Fn"); - ConstExprValue *fields = create_const_vals(5); + ConstExprValue *fields = create_const_vals(6); result->data.x_struct.fields = fields; // @TODO Fix type = undefined with ?type @@ -16325,6 +16325,15 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index; } + break; + } + case TypeTableEntryIdBoundFn: + { + // @TODO figure out memory corruption error. + TypeTableEntry *fn_type = type_entry->data.bound_fn.fn_type; + assert(fn_type->id == TypeTableEntryIdFn); + result = ir_make_type_info_value(ira, fn_type); + break; } } From 61b01805968939669a29f7189f4ce7fab46ab2da Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Sat, 28 Apr 2018 17:01:19 +0300 Subject: [PATCH 25/35] Added definition TypeInfo generation, except for function definitions. --- src/codegen.cpp | 30 +++++----- src/ir.cpp | 150 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 154 insertions(+), 26 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index fc872e1908ba..be1d59c26ae7 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6348,13 +6348,6 @@ static void define_builtin_compile_vars(CodeGen *g) { buf_appendf(contents, "};\n\n"); } { - // @TODO Add Namespace info. - // @TODO Methods -> definitions - // @TODO Includes type definitions (name + type bound) + functions + const variable definitions (+ type of variable) - // @TODO Type definitions are defined as variable definitions of type 'type' - // @TODO This should give us everything available. - // @TODO An alternative is exposing the value of every variable definition, check out if it's possible and wether we want that. - // @TODO I don't think so, @field gives it to us for free. buf_appendf(contents, "pub const TypeInfo = union(TypeId) {\n" " Type: void,\n" @@ -6410,11 +6403,6 @@ static void define_builtin_compile_vars(CodeGen *g) { " Packed,\n" " };\n" "\n" - " pub const Method = struct {\n" - " name: []const u8,\n" - " fn_info: Fn,\n" - " };\n" - "\n" " pub const StructField = struct {\n" " name: []const u8,\n" " offset: ?usize,\n" @@ -6424,7 +6412,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " pub const Struct = struct {\n" " layout: ContainerLayout,\n" " fields: []StructField,\n" - " methods: []Method,\n" + " defs: []Definition,\n" " };\n" "\n" " pub const Nullable = struct {\n" @@ -6454,7 +6442,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " layout: ContainerLayout,\n" " tag_type: type,\n" " fields: []EnumField,\n" - " methods: []Method,\n" + " defs: []Definition,\n" " };\n" "\n" " pub const UnionField = struct {\n" @@ -6467,7 +6455,7 @@ static void define_builtin_compile_vars(CodeGen *g) { " layout: ContainerLayout,\n" " tag_type: type,\n" " fields: []UnionField,\n" - " methods: []Method,\n" + " defs: []Definition,\n" " };\n" "\n" " pub const CallingConvention = enum {\n" @@ -6497,6 +6485,18 @@ static void define_builtin_compile_vars(CodeGen *g) { " pub const Promise = struct {\n" " child: type,\n" " };\n" + "\n" + " pub const Definition = struct {\n" + " name: []const u8,\n" + " is_pub: bool,\n" + " data: Data,\n" + "\n" + " const Data = union(enum) {\n" + " Type: type,\n" + " Var: type,\n" + " Fn: void,\n" + " };\n" + " };\n" "};\n\n"); assert(ContainerLayoutAuto == 0); assert(ContainerLayoutExtern == 1); diff --git a/src/ir.cpp b/src/ir.cpp index c2da83886a53..d8da5b317213 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15748,7 +15748,7 @@ static void ensure_field_index(TypeTableEntry *type, const char *field_name, siz (buf_deinit(field_name_buf), true)); } -static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_name) +static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, TypeTableEntry *root = nullptr) { static ConstExprValue *type_info_var = nullptr; static TypeTableEntry *type_info_type = nullptr; @@ -15761,10 +15761,14 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na assert(type_info_type->id == TypeTableEntryIdUnion); } - if (type_name == nullptr) + if (type_name == nullptr && root == nullptr) return type_info_type; + else if (type_name == nullptr) + return root; - ScopeDecls *type_info_scope = get_container_scope(type_info_type); + TypeTableEntry *root_type = (root == nullptr) ? type_info_type : root; + + ScopeDecls *type_info_scope = get_container_scope(root_type); assert(type_info_scope != nullptr); Buf field_name = BUF_INIT; @@ -15782,6 +15786,128 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na return var->value->data.x_type; } +static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) +{ + TypeTableEntry *type_info_definition_type = ir_type_info_get_type(ira, "Definition"); + ensure_complete_type(ira->codegen, type_info_definition_type); + ensure_field_index(type_info_definition_type, "name", 0); + ensure_field_index(type_info_definition_type, "is_pub", 1); + ensure_field_index(type_info_definition_type, "data", 2); + + TypeTableEntry *type_info_definition_data_type = ir_type_info_get_type(ira, "Data", type_info_definition_type); + ensure_complete_type(ira->codegen, type_info_definition_data_type); + + // Loop through our definitions once to figure out how many definitions we will generate info for. + auto decl_it = decls_scope->decl_table.entry_iterator(); + decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr; + int definition_count = 0; + + while ((curr_entry = decl_it.next()) != nullptr) + { + // Skip comptime blocks. + if (curr_entry->value->id != TldIdCompTime) + { + definition_count += 1; + } + } + + ConstExprValue *definition_array = create_const_vals(1); + definition_array->special = ConstValSpecialStatic; + definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count); + definition_array->data.x_array.special = ConstArraySpecialNone; + definition_array->data.x_array.s_none.parent.id = ConstParentIdNone; + definition_array->data.x_array.s_none.elements = create_const_vals(definition_count); + init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false); + + // Loop through the definitions and generate info. + decl_it = decls_scope->decl_table.entry_iterator(); + curr_entry = nullptr; + int definition_index = 0; + while ((curr_entry = decl_it.next()) != nullptr) + { + // Skip comptime blocks + if (curr_entry->value->id == TldIdCompTime) + continue; + + ConstExprValue *definition_val = &definition_array->data.x_array.s_none.elements[definition_index]; + + definition_val->special = ConstValSpecialStatic; + definition_val->type = type_info_definition_type; + + ConstExprValue *inner_fields = create_const_vals(3); + ConstExprValue *name = create_const_str_lit(ira->codegen, curr_entry->key); + init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(curr_entry->key), true); + inner_fields[1].special = ConstValSpecialStatic; + inner_fields[1].type = ira->codegen->builtin_types.entry_bool; + inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub; + inner_fields[2].special = ConstValSpecialStatic; + inner_fields[2].type = type_info_definition_data_type; + inner_fields[2].data.x_union.parent.id = ConstParentIdStruct; + inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val; + inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1; + + switch (curr_entry->value->id) + { + case TldIdVar: + { + VariableTableEntry *var = ((TldVar *)curr_entry->value)->var; + ensure_complete_type(ira->codegen, var->value->type); + if (var->value->type->id == TypeTableEntryIdMetaType) + { + // We have a variable of type 'type', so it's actually a type definition. + // 0: Data.Type: type + bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); + inner_fields[2].data.x_union.payload = var->value; + } + else + { + // We have a variable of another type, so we store the type of the variable. + // 1: Data.Var: type + bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1); + + ConstExprValue *payload = create_const_vals(1); + payload->type = ira->codegen->builtin_types.entry_type; + payload->data.x_type = var->value->type; + + inner_fields[2].data.x_union.payload = payload; + } + + break; + } + case TldIdFn: + { + // 2: Data.Fn: Data.FnDef + bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 2); + // @TODO Data.FnDef + inner_fields[2].data.x_union.payload = nullptr; + break; + } + case TldIdContainer: + { + TypeTableEntry *type_entry = ((TldContainer *)curr_entry->value)->type_entry; + ensure_complete_type(ira->codegen, type_entry); + // This is a type. + bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); + + ConstExprValue *payload = create_const_vals(1); + payload->type = ira->codegen->builtin_types.entry_type; + payload->data.x_type = type_entry; + + inner_fields[2].data.x_union.payload = payload; + + break; + } + default: + zig_unreachable(); + } + + definition_val->data.x_struct.fields = inner_fields; + definition_index++; + } + + assert(definition_index == definition_count); +} + static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) { assert(type_entry != nullptr); @@ -15791,10 +15917,6 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t const auto make_enum_field_val = [ira](ConstExprValue *enum_field_val, TypeEnumField *enum_field, TypeTableEntry *type_info_enum_field_type) { - // @TODO Those cause a find_struct_type_field assertion to fail (type_entry->data.structure.complete) - // ensure_field_index(type_info_enum_field_type, "name", 0); - // ensure_field_index(type_info_enum_field_type, "value", 1); - enum_field_val->special = ConstValSpecialStatic; enum_field_val->type = type_info_enum_field_type; @@ -16012,8 +16134,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array; enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index; } + // defs: []TypeInfo.Definition + ensure_field_index(result->type, "defs", 3); + ir_make_type_info_defs(ira, &fields[3], type_entry->data.enumeration.decls_scope); - // @TODO Definitions break; } case TypeTableEntryIdErrorSet: @@ -16165,8 +16289,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array; union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index; } + // defs: []TypeInfo.Definition + ensure_field_index(result->type, "defs", 3); + ir_make_type_info_defs(ira, &fields[3], type_entry->data.unionation.decls_scope); - // @TODO Definitions break; } case TypeTableEntryIdStruct: @@ -16232,7 +16358,10 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array; struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index; } - // @TODO Definitions + // defs: []TypeInfo.Definition + ensure_field_index(result->type, "defs", 2); + ir_make_type_info_defs(ira, &fields[2], type_entry->data.structure.decls_scope); + break; } case TypeTableEntryIdFn: @@ -16329,7 +16458,6 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t } case TypeTableEntryIdBoundFn: { - // @TODO figure out memory corruption error. TypeTableEntry *fn_type = type_entry->data.bound_fn.fn_type; assert(fn_type->id == TypeTableEntryIdFn); result = ir_make_type_info_value(ira, fn_type); From 9ba400673d798ea6f0842e4c207039c9faffb27e Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Sat, 28 Apr 2018 18:38:38 +0300 Subject: [PATCH 26/35] Generating TypeInfo's now forces definitions to be resolved. --- src/ir.cpp | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index d8da5b317213..6a3b4953c4cb 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15804,9 +15804,26 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop while ((curr_entry = decl_it.next()) != nullptr) { - // Skip comptime blocks. + // If the definition is unresolved, force it to be resolved again. + if (curr_entry->value->resolution == TldResolutionUnresolved) + { + resolve_top_level_decl(ira->codegen, curr_entry->value, false, curr_entry->value->source_node); + if (curr_entry->value->resolution != TldResolutionOk) + { + return; + } + } + + // Skip comptime blocks and test functions. if (curr_entry->value->id != TldIdCompTime) { + if (curr_entry->value->id == TldIdFn) + { + FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; + if (fn_entry->is_test) + continue; + } + definition_count += 1; } } @@ -15825,9 +15842,15 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop int definition_index = 0; while ((curr_entry = decl_it.next()) != nullptr) { - // Skip comptime blocks + // Skip comptime blocks and test functions. if (curr_entry->value->id == TldIdCompTime) continue; + else if (curr_entry->value->id == TldIdFn) + { + FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; + if (fn_entry->is_test) + continue; + } ConstExprValue *definition_val = &definition_array->data.x_array.s_none.elements[definition_index]; @@ -15878,7 +15901,10 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop { // 2: Data.Fn: Data.FnDef bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 2); - // @TODO Data.FnDef + + FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; + assert(!fn_entry->is_test); + inner_fields[2].data.x_union.payload = nullptr; break; } From af73462da46611ea9293f283ce8a6920ad73b10f Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Sat, 28 Apr 2018 19:57:59 +0300 Subject: [PATCH 27/35] Started work on function definition TypeInfo generation. --- src/codegen.cpp | 18 +++++++++++++++++- src/ir.cpp | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index be1d59c26ae7..414a34d5cb7d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6494,7 +6494,19 @@ static void define_builtin_compile_vars(CodeGen *g) { " const Data = union(enum) {\n" " Type: type,\n" " Var: type,\n" - " Fn: void,\n" + " Fn: FnDef,\n" + "\n" + " const FnDef = struct {\n" + " fn_type: type,\n" + " inline_type: Inline,\n" + " calling_convention: CallingConvention,\n" + "\n" + " const Inline = enum {\n" + " Auto,\n" + " Always,\n" + " Never,\n" + " };\n" + " };\n" " };\n" " };\n" "};\n\n"); @@ -6508,6 +6520,10 @@ static void define_builtin_compile_vars(CodeGen *g) { assert(CallingConventionNaked == 3); assert(CallingConventionStdcall == 4); assert(CallingConventionAsync == 5); + + assert(FnInlineAuto == 0); + assert(FnInlineAlways == 1); + assert(FnInlineNever == 2); } { buf_appendf(contents, diff --git a/src/ir.cpp b/src/ir.cpp index 6a3b4953c4cb..8fadc7f7a376 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15797,6 +15797,12 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop TypeTableEntry *type_info_definition_data_type = ir_type_info_get_type(ira, "Data", type_info_definition_type); ensure_complete_type(ira->codegen, type_info_definition_data_type); + TypeTableEntry *type_info_fn_def_type = ir_type_info_get_type(ira, "FnDef", type_info_definition_data_type); + ensure_complete_type(ira->codegen, type_info_fn_def_type); + + TypeTableEntry *type_info_fn_def_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_def_type); + ensure_complete_type(ira->codegen, type_info_fn_def_inline_type); + // Loop through our definitions once to figure out how many definitions we will generate info for. auto decl_it = decls_scope->decl_table.entry_iterator(); decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr; @@ -15905,7 +15911,35 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; assert(!fn_entry->is_test); - inner_fields[2].data.x_union.payload = nullptr; + AstNodeFnProto *fn_node = (AstNodeFnProto *)(fn_entry->proto_node); + + ConstExprValue *fn_def_val = create_const_vals(1); + fn_def_val->special = ConstValSpecialStatic; + fn_def_val->type = type_info_fn_def_type; + fn_def_val->data.x_struct.parent.id = ConstParentIdUnion; + fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2]; + + // @TODO Add fields + ConstExprValue *fn_def_fields = create_const_vals(3); + fn_def_val->data.x_struct.fields = fn_def_fields; + + // fn_type: type + ensure_field_index(fn_def_val->type, "fn_type", 0); + fn_def_fields[0].special = ConstValSpecialStatic; + fn_def_fields[0].type = ira->codegen->builtin_types.entry_type; + fn_def_fields[0].data.x_type = fn_entry->type_entry; + // inline_type: Data.FnDef.Inline + ensure_field_index(fn_def_val->type, "inline_type", 1); + fn_def_fields[1].special = ConstValSpecialStatic; + fn_def_fields[1].type = type_info_fn_def_inline_type; + bigint_init_unsigned(&fn_def_fields[1].data.x_enum_tag, fn_entry->fn_inline); + // calling_convention: TypeInfo.CallingConvention + ensure_field_index(fn_def_val->type, "calling_convention", 2); + fn_def_fields[2].special = ConstValSpecialStatic; + fn_def_fields[2].type = ir_type_info_get_type(ira, "CallingConvention"); + bigint_init_unsigned(&fn_def_fields[2].data.x_enum_tag, fn_node->cc); + + inner_fields[2].data.x_union.payload = fn_def_val; break; } case TldIdContainer: From 66aa760f83529cf932d35090adfa6fb84264ff7a Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Sun, 29 Apr 2018 14:03:55 +0300 Subject: [PATCH 28/35] More FnDef TypeInfo generation. --- src/codegen.cpp | 4 ++++ src/ir.cpp | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 414a34d5cb7d..507b9afe8b6e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6500,6 +6500,10 @@ static void define_builtin_compile_vars(CodeGen *g) { " fn_type: type,\n" " inline_type: Inline,\n" " calling_convention: CallingConvention,\n" + " is_var_args: bool,\n" + " is_extern: bool,\n" + " is_export: bool,\n" + " lib_name: ?[]const u8,\n" "\n" " const Inline = enum {\n" " Auto,\n" diff --git a/src/ir.cpp b/src/ir.cpp index 8fadc7f7a376..e3add4d61261 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15920,7 +15920,7 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2]; // @TODO Add fields - ConstExprValue *fn_def_fields = create_const_vals(3); + ConstExprValue *fn_def_fields = create_const_vals(7); fn_def_val->data.x_struct.fields = fn_def_fields; // fn_type: type @@ -15938,6 +15938,40 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop fn_def_fields[2].special = ConstValSpecialStatic; fn_def_fields[2].type = ir_type_info_get_type(ira, "CallingConvention"); bigint_init_unsigned(&fn_def_fields[2].data.x_enum_tag, fn_node->cc); + // is_var_args: bool + ensure_field_index(fn_def_val->type, "is_var_args", 3); + fn_def_fields[3].special = ConstValSpecialStatic; + fn_def_fields[3].type = ira->codegen->builtin_types.entry_bool; + fn_def_fields[3].data.x_bool = fn_node->is_var_args; + // is_extern: bool + ensure_field_index(fn_def_val->type, "is_extern", 4); + fn_def_fields[4].special = ConstValSpecialStatic; + fn_def_fields[4].type = ira->codegen->builtin_types.entry_bool; + fn_def_fields[4].data.x_bool = fn_node->is_extern; + // is_export: bool + ensure_field_index(fn_def_val->type, "is_export", 5); + fn_def_fields[5].special = ConstValSpecialStatic; + fn_def_fields[5].type = ira->codegen->builtin_types.entry_bool; + fn_def_fields[5].data.x_bool = fn_node->is_export; + // lib_name: ?[]const u8 + ensure_field_index(fn_def_val->type, "lib_name", 6); + fn_def_fields[6].special = ConstValSpecialStatic; + fn_def_fields[6].type = get_maybe_type(ira->codegen, + get_slice_type(ira->codegen, get_pointer_to_type(ira->codegen, + ira->codegen->builtin_types.entry_u8, true))); + + + if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) + { + fn_def_fields[6].data.x_maybe = create_const_vals(1); + // @TODO Figure out if lib_name is always non-null for extern fns. + ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name); + init_const_slice(ira->codegen, fn_def_fields[6].data.x_maybe, lib_name, 0, buf_len(fn_node->lib_name), true); + } + else + { + fn_def_fields[6].data.x_maybe = nullptr; + } inner_fields[2].data.x_union.payload = fn_def_val; break; From 013f548202ae1ffb584c211a0ea2cea53b745583 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Sun, 29 Apr 2018 15:40:26 +0300 Subject: [PATCH 29/35] Finished FnDef TypeInfo generation (warning: may be buggy). --- src/codegen.cpp | 8 +++++--- src/ir.cpp | 47 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 507b9afe8b6e..db69708e9a21 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6491,12 +6491,12 @@ static void define_builtin_compile_vars(CodeGen *g) { " is_pub: bool,\n" " data: Data,\n" "\n" - " const Data = union(enum) {\n" + " pub const Data = union(enum) {\n" " Type: type,\n" " Var: type,\n" " Fn: FnDef,\n" "\n" - " const FnDef = struct {\n" + " pub const FnDef = struct {\n" " fn_type: type,\n" " inline_type: Inline,\n" " calling_convention: CallingConvention,\n" @@ -6504,8 +6504,10 @@ static void define_builtin_compile_vars(CodeGen *g) { " is_extern: bool,\n" " is_export: bool,\n" " lib_name: ?[]const u8,\n" + " return_type: type,\n" + " arg_names: [][] const u8,\n" "\n" - " const Inline = enum {\n" + " pub const Inline = enum {\n" " Auto,\n" " Always,\n" " Never,\n" diff --git a/src/ir.cpp b/src/ir.cpp index e3add4d61261..3bce9c51cd74 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15911,6 +15911,10 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; assert(!fn_entry->is_test); + analyze_fn_body(ira->codegen, fn_entry); + if (fn_entry->anal_state == FnAnalStateInvalid) + return; + AstNodeFnProto *fn_node = (AstNodeFnProto *)(fn_entry->proto_node); ConstExprValue *fn_def_val = create_const_vals(1); @@ -15919,8 +15923,7 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop fn_def_val->data.x_struct.parent.id = ConstParentIdUnion; fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2]; - // @TODO Add fields - ConstExprValue *fn_def_fields = create_const_vals(7); + ConstExprValue *fn_def_fields = create_const_vals(9); fn_def_val->data.x_struct.fields = fn_def_fields; // fn_type: type @@ -15940,9 +15943,10 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop bigint_init_unsigned(&fn_def_fields[2].data.x_enum_tag, fn_node->cc); // is_var_args: bool ensure_field_index(fn_def_val->type, "is_var_args", 3); + bool is_varargs = fn_node->is_var_args; fn_def_fields[3].special = ConstValSpecialStatic; fn_def_fields[3].type = ira->codegen->builtin_types.entry_bool; - fn_def_fields[3].data.x_bool = fn_node->is_var_args; + fn_def_fields[3].data.x_bool = is_varargs; // is_extern: bool ensure_field_index(fn_def_val->type, "is_extern", 4); fn_def_fields[4].special = ConstValSpecialStatic; @@ -15959,18 +15963,47 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop fn_def_fields[6].type = get_maybe_type(ira->codegen, get_slice_type(ira->codegen, get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true))); - - if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) { fn_def_fields[6].data.x_maybe = create_const_vals(1); - // @TODO Figure out if lib_name is always non-null for extern fns. ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name); init_const_slice(ira->codegen, fn_def_fields[6].data.x_maybe, lib_name, 0, buf_len(fn_node->lib_name), true); } else - { fn_def_fields[6].data.x_maybe = nullptr; + // return_type: type + ensure_field_index(fn_def_val->type, "return_type", 7); + fn_def_fields[7].special = ConstValSpecialStatic; + fn_def_fields[7].type = ira->codegen->builtin_types.entry_type; + // @TODO Check whether this is correct. + if (fn_entry->src_implicit_return_type != nullptr) + fn_def_fields[7].data.x_type = fn_entry->src_implicit_return_type; + else if (fn_entry->type_entry->data.fn.gen_return_type != nullptr) + fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.gen_return_type; + else + fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type; + // arg_names: [][] const u8 + ensure_field_index(fn_def_val->type, "arg_names", 8); + size_t fn_arg_count = fn_entry->variable_list.length; + ConstExprValue *fn_arg_name_array = create_const_vals(1); + fn_arg_name_array->special = ConstValSpecialStatic; + fn_arg_name_array->type = get_array_type(ira->codegen, get_slice_type(ira->codegen, + get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true)), fn_arg_count); + fn_arg_name_array->data.x_array.special = ConstArraySpecialNone; + fn_arg_name_array->data.x_array.s_none.parent.id = ConstParentIdNone; + fn_arg_name_array->data.x_array.s_none.elements = create_const_vals(fn_arg_count); + + init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false); + + for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) + { + VariableTableEntry *arg_var = fn_entry->variable_list.at(fn_arg_index); + ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.s_none.elements[fn_arg_index]; + ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name); + init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true); + fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray; + fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array; + fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index; } inner_fields[2].data.x_union.payload = fn_def_val; From ff1c4e1f13943b63dcb6d257a2ee58ae88d4b12a Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 1 May 2018 13:00:39 +0300 Subject: [PATCH 30/35] Added tests. --- src/ir.cpp | 1 - test/cases/union.zig | 10 ++++++++++ test/compile_errors.zig | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 3bce9c51cd74..dfffb41873cc 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15975,7 +15975,6 @@ static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop ensure_field_index(fn_def_val->type, "return_type", 7); fn_def_fields[7].special = ConstValSpecialStatic; fn_def_fields[7].type = ira->codegen->builtin_types.entry_type; - // @TODO Check whether this is correct. if (fn_entry->src_implicit_return_type != nullptr) fn_def_fields[7].data.x_type = fn_entry->src_implicit_return_type; else if (fn_entry->type_entry->data.fn.gen_return_type != nullptr) diff --git a/test/cases/union.zig b/test/cases/union.zig index dc2a7c3414e4..e7d9c23d77c4 100644 --- a/test/cases/union.zig +++ b/test/cases/union.zig @@ -45,6 +45,16 @@ test "basic unions" { assert(foo.float == 12.34); } +test "comptime union field access" { + comptime { + var foo = Foo { .int = 0 }; + assert(foo.int == 0); + + foo = Foo { .float = 42.42 }; + assert(foo.float == 42.42); + } +} + test "init union with runtime value" { var foo: Foo = undefined; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index f8febc27b809..d9454adf2cd9 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3209,4 +3209,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { \\} , ".tmp_source.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset"); + + cases.add("invalid union field access in comptime", + \\const Foo = union { + \\ Bar: u8, + \\ Baz: void, + \\}; + \\comptime { + \\ var foo = Foo {.Baz = {}}; + \\ const bar_val = foo.Bar; + \\} + , + ".tmp_source.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set"); } From e1535ee0a9f9d01d16a79c380b493f676ae57121 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 1 May 2018 13:01:54 +0300 Subject: [PATCH 31/35] Added typeInfo tests --- test/cases/type_info.zig | 181 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 test/cases/type_info.zig diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig new file mode 100644 index 000000000000..8e6721beae69 --- /dev/null +++ b/test/cases/type_info.zig @@ -0,0 +1,181 @@ +const assert = @import("std").debug.assert; +const mem = @import("std").mem; +const TypeInfo = @import("builtin").TypeInfo; +const TypeId = @import("builtin").TypeId; + +test "type info: tag type, void info" { + comptime { + assert(@TagType(TypeInfo) == TypeId); + const void_info = @typeInfo(void); + assert(TypeId(void_info) == TypeId.Void); + assert(void_info.Void == {}); + } +} + +test "type info: integer, floating point type info" { + comptime { + const u8_info = @typeInfo(u8); + assert(TypeId(u8_info) == TypeId.Int); + assert(!u8_info.Int.is_signed); + assert(u8_info.Int.bits == 8); + + const f64_info = @typeInfo(f64); + assert(TypeId(f64_info) == TypeId.Float); + assert(f64_info.Float.bits == 64); + } +} + +test "type info: pointer, array and nullable type info" { + comptime { + const u32_ptr_info = @typeInfo(&u32); + assert(TypeId(u32_ptr_info) == TypeId.Pointer); + 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.child == u32); + + const arr_info = @typeInfo([42]bool); + assert(TypeId(arr_info) == TypeId.Array); + assert(arr_info.Array.len == 42); + assert(arr_info.Array.child == bool); + + const null_info = @typeInfo(?void); + assert(TypeId(null_info) == TypeId.Nullable); + assert(null_info.Nullable.child == void); + } +} + +test "type info: promise info" { + comptime { + const null_promise_info = @typeInfo(promise); + assert(TypeId(null_promise_info) == TypeId.Promise); + assert(null_promise_info.Promise.child == @typeOf(undefined)); + + const promise_info = @typeInfo(promise->usize); + assert(TypeId(promise_info) == TypeId.Promise); + assert(promise_info.Promise.child == usize); + } + +} + +test "type info: error set, error union info" { + comptime { + const TestErrorSet = error { + First, + Second, + Third, + }; + + const error_set_info = @typeInfo(TestErrorSet); + assert(TypeId(error_set_info) == TypeId.ErrorSet); + assert(error_set_info.ErrorSet.errors.len == 3); + assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); + assert(error_set_info.ErrorSet.errors[2].value == 3); + + const error_union_info = @typeInfo(TestErrorSet!usize); + assert(TypeId(error_union_info) == TypeId.ErrorUnion); + assert(error_union_info.ErrorUnion.error_set == TestErrorSet); + assert(error_union_info.ErrorUnion.payload == usize); + } +} + +test "type info: enum info" { + comptime { + const Os = @import("builtin").Os; + + const os_info = @typeInfo(Os); + assert(TypeId(os_info) == TypeId.Enum); + assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); + assert(os_info.Enum.fields.len == 32); + assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas")); + assert(os_info.Enum.fields[10].value == 10); + assert(os_info.Enum.tag_type == u5); + assert(os_info.Enum.defs.len == 0); + } +} + +test "type info: union info" { + comptime { + const typeinfo_info = @typeInfo(TypeInfo); + 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 == 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(u8_info.Int)); + assert(typeinfo_info.Union.defs.len == 20); + + const TestNoTagUnion = union { + Foo: void, + Bar: u32, + }; + + const notag_union_info = @typeInfo(TestNoTagUnion); + assert(TypeId(notag_union_info) == TypeId.Union); + assert(notag_union_info.Union.tag_type == @typeOf(undefined)); + assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); + assert(notag_union_info.Union.fields.len == 2); + assert(notag_union_info.Union.fields[0].enum_field == null); + assert(notag_union_info.Union.fields[1].field_type == u32); + + const TestExternUnion = extern union { + foo: &c_void, + }; + + const extern_union_info = @typeInfo(TestExternUnion); + assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); + assert(extern_union_info.Union.tag_type == @typeOf(undefined)); + assert(extern_union_info.Union.fields[0].enum_field == null); + assert(extern_union_info.Union.fields[0].field_type == &c_void); + } +} + +test "type info: struct info" { + comptime { + const struct_info = @typeInfo(TestStruct); + assert(TypeId(struct_info) == TypeId.Struct); + assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); + assert(struct_info.Struct.fields.len == 3); + assert(struct_info.Struct.fields[1].offset == null); + assert(struct_info.Struct.fields[2].field_type == &TestStruct); + assert(struct_info.Struct.defs.len == 2); + assert(struct_info.Struct.defs[0].is_pub); + assert(!struct_info.Struct.defs[0].data.Fn.is_extern); + assert(struct_info.Struct.defs[0].data.Fn.lib_name == null); + assert(struct_info.Struct.defs[0].data.Fn.return_type == void); + assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void); + } +} + +const TestStruct = packed struct { + const Self = this; + + fieldA: usize, + fieldB: void, + fieldC: &Self, + + pub fn foo(self: &const Self) void {} +}; + +test "type info: function type info" { + comptime { + const fn_info = @typeInfo(@typeOf(foo)); + assert(TypeId(fn_info) == TypeId.Fn); + assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); + assert(fn_info.Fn.is_generic); + assert(fn_info.Fn.args.len == 2); + assert(fn_info.Fn.is_var_args); + assert(fn_info.Fn.return_type == @typeOf(undefined)); + assert(fn_info.Fn.async_allocator_type == @typeOf(undefined)); + + const test_instance: TestStruct = undefined; + const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); + assert(TypeId(bound_fn_info) == TypeId.BoundFn); + assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct); + } +} + +fn foo(comptime a: usize, b: bool, args: ...) usize { + return 0; +} From 1b6e97355d58fbd8aa961d02c3e75c9ca34ed1b9 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 1 May 2018 13:31:14 +0300 Subject: [PATCH 32/35] Added type info tests to behavior test listing --- test/behavior.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/test/behavior.zig b/test/behavior.zig index 2c10c6d71bfd..3efd65e5dd0d 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -36,6 +36,7 @@ comptime { _ = @import("cases/pub_enum/index.zig"); _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); _ = @import("cases/reflection.zig"); + _ = @import("cases/type_info.zig"); _ = @import("cases/sizeof_and_typeof.zig"); _ = @import("cases/slice.zig"); _ = @import("cases/struct.zig"); From 7d239414f7ed5abad8cdd8b1262590d8f50dd56a Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 1 May 2018 13:42:20 +0300 Subject: [PATCH 33/35] Fixed type info test, added documentation. --- doc/langref.html.in | 391 ++++++++++++++++++++++++++++++++++++++- test/cases/type_info.zig | 4 +- 2 files changed, 389 insertions(+), 6 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 16fafdaad9ab..db41ca6a1f78 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -4809,6 +4809,182 @@ pub const TypeId = enum { BoundFn, ArgTuple, Opaque, +}; + {#code_end#} + {#header_close#} + {#header_open|@typeInfo#} +
@typeInfo(comptime T: type) -> @import("builtin").TypeInfo
+

+ Returns information on the type. Returns a value of the following union: +

+ {#code_begin|syntax#} +pub const TypeInfo = union(TypeId) { + Type: void, + Void: void, + Bool: void, + NoReturn: void, + Int: Int, + Float: Float, + Pointer: Pointer, + Array: Array, + Struct: Struct, + FloatLiteral: void, + IntLiteral: void, + UndefinedLiteral: void, + NullLiteral: void, + Nullable: Nullable, + ErrorUnion: ErrorUnion, + ErrorSet: ErrorSet, + Enum: Enum, + Union: Union, + Fn: Fn, + Namespace: void, + Block: void, + BoundFn: Fn, + ArgTuple: void, + Opaque: void, + Promise: Promise, + + + pub const Int = struct { + is_signed: bool, + bits: u8, + }; + + pub const Float = struct { + bits: u8, + }; + + pub const Pointer = struct { + is_const: bool, + is_volatile: bool, + alignment: u32, + child: type, + }; + + pub const Array = struct { + len: usize, + child: type, + }; + + pub const ContainerLayout = enum { + Auto, + Extern, + Packed, + }; + + pub const StructField = struct { + name: []const u8, + offset: ?usize, + field_type: type, + }; + + pub const Struct = struct { + layout: ContainerLayout, + fields: []StructField, + defs: []Definition, + }; + + pub const Nullable = struct { + child: type, + }; + + pub const ErrorUnion = struct { + error_set: type, + payload: type, + }; + + pub const Error = struct { + name: []const u8, + value: usize, + }; + + pub const ErrorSet = struct { + errors: []Error, + }; + + pub const EnumField = struct { + name: []const u8, + value: usize, + }; + + pub const Enum = struct { + layout: ContainerLayout, + tag_type: type, + fields: []EnumField, + defs: []Definition, + }; + + pub const UnionField = struct { + name: []const u8, + enum_field: ?EnumField, + field_type: type, + }; + + pub const Union = struct { + layout: ContainerLayout, + tag_type: type, + fields: []UnionField, + defs: []Definition, + }; + + pub const CallingConvention = enum { + Unspecified, + C, + Cold, + Naked, + Stdcall, + Async, + }; + + pub const FnArg = struct { + is_generic: bool, + is_noalias: bool, + arg_type: type, + }; + + pub const Fn = struct { + calling_convention: CallingConvention, + is_generic: bool, + is_var_args: bool, + return_type: type, + async_allocator_type: type, + args: []FnArg, + }; + + pub const Promise = struct { + child: type, + }; + + pub const Definition = struct { + name: []const u8, + is_pub: bool, + data: Data, + + pub const Data = union(enum) { + Type: type, + Var: type, + Fn: FnDef, + + pub const FnDef = struct { + fn_type: type, + inline_type: Inline, + calling_convention: CallingConvention, + is_var_args: bool, + is_extern: bool, + is_export: bool, + lib_name: ?[]const u8, + return_type: type, + arg_names: [][] const u8, + + pub const Inline = enum { + Auto, + Always, + Never, + }; + }; + }; + }; }; {#code_end#} {#header_close#} @@ -5226,7 +5402,6 @@ pub const Os = enum { rtems, nacl, cnk, - bitrig, aix, cuda, nvcl, @@ -5237,10 +5412,12 @@ pub const Os = enum { watchos, mesa3d, contiki, + amdpal, zen, }; pub const Arch = enum { + armv8_3a, armv8_2a, armv8_1a, armv8, @@ -5260,9 +5437,29 @@ pub const Arch = enum { armv5, armv5te, armv4t, - armeb, + armebv8_3a, + armebv8_2a, + armebv8_1a, + armebv8, + armebv8r, + armebv8m_baseline, + armebv8m_mainline, + armebv7, + armebv7em, + armebv7m, + armebv7s, + armebv7k, + armebv7ve, + armebv6, + armebv6m, + armebv6k, + armebv6t2, + armebv5, + armebv5te, + armebv4t, aarch64, aarch64_be, + arc, avr, bpfel, bpfeb, @@ -5315,6 +5512,7 @@ pub const Arch = enum { pub const Environ = enum { unknown, gnu, + gnuabin32, gnuabi64, gnueabi, gnueabihf, @@ -5332,6 +5530,7 @@ pub const Environ = enum { amdopencl, coreclr, opencl, + simulator, }; pub const ObjectFormat = enum { @@ -5358,10 +5557,23 @@ pub const AtomicOrder = enum { SeqCst, }; +pub const AtomicRmwOp = enum { + Xchg, + Add, + Sub, + And, + Nand, + Or, + Xor, + Max, + Min, +}; + pub const Mode = enum { Debug, ReleaseSafe, ReleaseFast, + ReleaseSmall, }; pub const TypeId = enum { @@ -5380,7 +5592,7 @@ pub const TypeId = enum { NullLiteral, Nullable, ErrorUnion, - Error, + ErrorSet, Enum, Union, Fn, @@ -5389,6 +5601,176 @@ pub const TypeId = enum { BoundFn, ArgTuple, Opaque, + Promise, +}; + +pub const TypeInfo = union(TypeId) { + Type: void, + Void: void, + Bool: void, + NoReturn: void, + Int: Int, + Float: Float, + Pointer: Pointer, + Array: Array, + Struct: Struct, + FloatLiteral: void, + IntLiteral: void, + UndefinedLiteral: void, + NullLiteral: void, + Nullable: Nullable, + ErrorUnion: ErrorUnion, + ErrorSet: ErrorSet, + Enum: Enum, + Union: Union, + Fn: Fn, + Namespace: void, + Block: void, + BoundFn: Fn, + ArgTuple: void, + Opaque: void, + Promise: Promise, + + + pub const Int = struct { + is_signed: bool, + bits: u8, + }; + + pub const Float = struct { + bits: u8, + }; + + pub const Pointer = struct { + is_const: bool, + is_volatile: bool, + alignment: u32, + child: type, + }; + + pub const Array = struct { + len: usize, + child: type, + }; + + pub const ContainerLayout = enum { + Auto, + Extern, + Packed, + }; + + pub const StructField = struct { + name: []const u8, + offset: ?usize, + field_type: type, + }; + + pub const Struct = struct { + layout: ContainerLayout, + fields: []StructField, + defs: []Definition, + }; + + pub const Nullable = struct { + child: type, + }; + + pub const ErrorUnion = struct { + error_set: type, + payload: type, + }; + + pub const Error = struct { + name: []const u8, + value: usize, + }; + + pub const ErrorSet = struct { + errors: []Error, + }; + + pub const EnumField = struct { + name: []const u8, + value: usize, + }; + + pub const Enum = struct { + layout: ContainerLayout, + tag_type: type, + fields: []EnumField, + defs: []Definition, + }; + + pub const UnionField = struct { + name: []const u8, + enum_field: ?EnumField, + field_type: type, + }; + + pub const Union = struct { + layout: ContainerLayout, + tag_type: type, + fields: []UnionField, + defs: []Definition, + }; + + pub const CallingConvention = enum { + Unspecified, + C, + Cold, + Naked, + Stdcall, + Async, + }; + + pub const FnArg = struct { + is_generic: bool, + is_noalias: bool, + arg_type: type, + }; + + pub const Fn = struct { + calling_convention: CallingConvention, + is_generic: bool, + is_var_args: bool, + return_type: type, + async_allocator_type: type, + args: []FnArg, + }; + + pub const Promise = struct { + child: type, + }; + + pub const Definition = struct { + name: []const u8, + is_pub: bool, + data: Data, + + pub const Data = union(enum) { + Type: type, + Var: type, + Fn: FnDef, + + pub const FnDef = struct { + fn_type: type, + inline_type: Inline, + calling_convention: CallingConvention, + is_var_args: bool, + is_extern: bool, + is_export: bool, + lib_name: ?[]const u8, + return_type: type, + arg_names: [][] const u8, + + pub const Inline = enum { + Auto, + Always, + Never, + }; + }; + }; + }; }; pub const FloatMode = enum { @@ -5402,7 +5784,7 @@ pub const Endian = enum { }; pub const endian = Endian.Little; -pub const is_test = false; +pub const is_test = true; pub const os = Os.linux; pub const arch = Arch.x86_64; pub const environ = Environ.gnu; @@ -5410,6 +5792,7 @@ pub const object_format = ObjectFormat.elf; pub const mode = Mode.Debug; pub const link_libc = false; pub const have_error_return_tracing = true; +pub const __zig_test_fn_slice = {}; // overwritten later {#code_end#} {#see_also|Build Mode#} {#header_close#} diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig index 8e6721beae69..c9b15157e81f 100644 --- a/test/cases/type_info.zig +++ b/test/cases/type_info.zig @@ -70,7 +70,7 @@ test "type info: error set, error union info" { assert(TypeId(error_set_info) == TypeId.ErrorSet); assert(error_set_info.ErrorSet.errors.len == 3); assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); - assert(error_set_info.ErrorSet.errors[2].value == 3); + assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third)); const error_union_info = @typeInfo(TestErrorSet!usize); assert(TypeId(error_union_info) == TypeId.ErrorUnion); @@ -103,7 +103,7 @@ test "type info: union info" { 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(u8_info.Int)); + assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); assert(typeinfo_info.Union.defs.len == 20); const TestNoTagUnion = union { From 57940837e7a178577c22b89c5173082e4fb8e618 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 1 May 2018 13:44:19 +0300 Subject: [PATCH 34/35] Added typeInfo to langref built_ins --- doc/langref.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index db41ca6a1f78..b867ff0b3523 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6451,7 +6451,7 @@ hljs.registerLanguage("zig", function(t) { a = t.IR + "\\s*\\(", c = { keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong", - built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field", + built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo", literal: "true false null undefined" }, n = [e, t.CLCM, t.CBCM, s, r]; From 849ea61fa11460b1a6df2529063a6b0cabc6e5e4 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Tue, 1 May 2018 17:10:50 +0300 Subject: [PATCH 35/35] Small fix. --- src/ir.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ir.cpp b/src/ir.cpp index ff81ebfd8600..cffee9bebc78 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15765,6 +15765,7 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); assert(type_info_var->type->id == TypeTableEntryIdMetaType); + ensure_complete_type(ira->codegen, type_info_var->data.x_type); type_info_type = type_info_var->data.x_type; assert(type_info_type->id == TypeTableEntryIdUnion); } @@ -15790,6 +15791,7 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na VariableTableEntry *var = tld->var; + ensure_complete_type(ira->codegen, var->value->type); assert(var->value->type->id == TypeTableEntryIdMetaType); return var->value->data.x_type; }