authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-03 23:02:33-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-05-03 23:02:33-04:00
logb9e320dd521751663db7b040e65c8ff5420c824a
tree2c4161ebf8d1997ea45926af86301d64a960484c
parentaa2586de182e5587c924740e80468c4c4d509500
parent849ea61fa11460b1a6df2529063a6b0cabc6e5e4
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #951 from alexnask/reflect_reify

Metaprogramming - @typeInfo [DONE]

9 files changed, 1758 insertions(+), 7 deletions(-)

doc/langref.html.in+388-5
......@@ -4809,6 +4809,182 @@ pub const TypeId = enum {
48094809 BoundFn,
48104810 ArgTuple,
48114811 Opaque,
4812};
4813 {#code_end#}
4814 {#header_close#}
4815 {#header_open|@typeInfo#}
4816 <pre><code class="zig">@typeInfo(comptime T: type) -&gt; @import("builtin").TypeInfo</code></pre>
4817 <p>
4818 Returns information on the type. Returns a value of the following union:
4819 </p>
4820 {#code_begin|syntax#}
4821pub const TypeInfo = union(TypeId) {
4822 Type: void,
4823 Void: void,
4824 Bool: void,
4825 NoReturn: void,
4826 Int: Int,
4827 Float: Float,
4828 Pointer: Pointer,
4829 Array: Array,
4830 Struct: Struct,
4831 FloatLiteral: void,
4832 IntLiteral: void,
4833 UndefinedLiteral: void,
4834 NullLiteral: void,
4835 Nullable: Nullable,
4836 ErrorUnion: ErrorUnion,
4837 ErrorSet: ErrorSet,
4838 Enum: Enum,
4839 Union: Union,
4840 Fn: Fn,
4841 Namespace: void,
4842 Block: void,
4843 BoundFn: Fn,
4844 ArgTuple: void,
4845 Opaque: void,
4846 Promise: Promise,
4847
4848
4849 pub const Int = struct {
4850 is_signed: bool,
4851 bits: u8,
4852 };
4853
4854 pub const Float = struct {
4855 bits: u8,
4856 };
4857
4858 pub const Pointer = struct {
4859 is_const: bool,
4860 is_volatile: bool,
4861 alignment: u32,
4862 child: type,
4863 };
4864
4865 pub const Array = struct {
4866 len: usize,
4867 child: type,
4868 };
4869
4870 pub const ContainerLayout = enum {
4871 Auto,
4872 Extern,
4873 Packed,
4874 };
4875
4876 pub const StructField = struct {
4877 name: []const u8,
4878 offset: ?usize,
4879 field_type: type,
4880 };
4881
4882 pub const Struct = struct {
4883 layout: ContainerLayout,
4884 fields: []StructField,
4885 defs: []Definition,
4886 };
4887
4888 pub const Nullable = struct {
4889 child: type,
4890 };
4891
4892 pub const ErrorUnion = struct {
4893 error_set: type,
4894 payload: type,
4895 };
4896
4897 pub const Error = struct {
4898 name: []const u8,
4899 value: usize,
4900 };
4901
4902 pub const ErrorSet = struct {
4903 errors: []Error,
4904 };
4905
4906 pub const EnumField = struct {
4907 name: []const u8,
4908 value: usize,
4909 };
4910
4911 pub const Enum = struct {
4912 layout: ContainerLayout,
4913 tag_type: type,
4914 fields: []EnumField,
4915 defs: []Definition,
4916 };
4917
4918 pub const UnionField = struct {
4919 name: []const u8,
4920 enum_field: ?EnumField,
4921 field_type: type,
4922 };
4923
4924 pub const Union = struct {
4925 layout: ContainerLayout,
4926 tag_type: type,
4927 fields: []UnionField,
4928 defs: []Definition,
4929 };
4930
4931 pub const CallingConvention = enum {
4932 Unspecified,
4933 C,
4934 Cold,
4935 Naked,
4936 Stdcall,
4937 Async,
4938 };
4939
4940 pub const FnArg = struct {
4941 is_generic: bool,
4942 is_noalias: bool,
4943 arg_type: type,
4944 };
4945
4946 pub const Fn = struct {
4947 calling_convention: CallingConvention,
4948 is_generic: bool,
4949 is_var_args: bool,
4950 return_type: type,
4951 async_allocator_type: type,
4952 args: []FnArg,
4953 };
4954
4955 pub const Promise = struct {
4956 child: type,
4957 };
4958
4959 pub const Definition = struct {
4960 name: []const u8,
4961 is_pub: bool,
4962 data: Data,
4963
4964 pub const Data = union(enum) {
4965 Type: type,
4966 Var: type,
4967 Fn: FnDef,
4968
4969 pub const FnDef = struct {
4970 fn_type: type,
4971 inline_type: Inline,
4972 calling_convention: CallingConvention,
4973 is_var_args: bool,
4974 is_extern: bool,
4975 is_export: bool,
4976 lib_name: ?[]const u8,
4977 return_type: type,
4978 arg_names: [][] const u8,
4979
4980 pub const Inline = enum {
4981 Auto,
4982 Always,
4983 Never,
4984 };
4985 };
4986 };
4987 };
48124988};
48134989 {#code_end#}
48144990 {#header_close#}
......@@ -5226,7 +5402,6 @@ pub const Os = enum {
52265402 rtems,
52275403 nacl,
52285404 cnk,
5229 bitrig,
52305405 aix,
52315406 cuda,
52325407 nvcl,
......@@ -5237,10 +5412,12 @@ pub const Os = enum {
52375412 watchos,
52385413 mesa3d,
52395414 contiki,
5415 amdpal,
52405416 zen,
52415417};
52425418
52435419pub const Arch = enum {
5420 armv8_3a,
52445421 armv8_2a,
52455422 armv8_1a,
52465423 armv8,
......@@ -5260,9 +5437,29 @@ pub const Arch = enum {
52605437 armv5,
52615438 armv5te,
52625439 armv4t,
5263 armeb,
5440 armebv8_3a,
5441 armebv8_2a,
5442 armebv8_1a,
5443 armebv8,
5444 armebv8r,
5445 armebv8m_baseline,
5446 armebv8m_mainline,
5447 armebv7,
5448 armebv7em,
5449 armebv7m,
5450 armebv7s,
5451 armebv7k,
5452 armebv7ve,
5453 armebv6,
5454 armebv6m,
5455 armebv6k,
5456 armebv6t2,
5457 armebv5,
5458 armebv5te,
5459 armebv4t,
52645460 aarch64,
52655461 aarch64_be,
5462 arc,
52665463 avr,
52675464 bpfel,
52685465 bpfeb,
......@@ -5315,6 +5512,7 @@ pub const Arch = enum {
53155512pub const Environ = enum {
53165513 unknown,
53175514 gnu,
5515 gnuabin32,
53185516 gnuabi64,
53195517 gnueabi,
53205518 gnueabihf,
......@@ -5332,6 +5530,7 @@ pub const Environ = enum {
53325530 amdopencl,
53335531 coreclr,
53345532 opencl,
5533 simulator,
53355534};
53365535
53375536pub const ObjectFormat = enum {
......@@ -5358,10 +5557,23 @@ pub const AtomicOrder = enum {
53585557 SeqCst,
53595558};
53605559
5560pub const AtomicRmwOp = enum {
5561 Xchg,
5562 Add,
5563 Sub,
5564 And,
5565 Nand,
5566 Or,
5567 Xor,
5568 Max,
5569 Min,
5570};
5571
53615572pub const Mode = enum {
53625573 Debug,
53635574 ReleaseSafe,
53645575 ReleaseFast,
5576 ReleaseSmall,
53655577};
53665578
53675579pub const TypeId = enum {
......@@ -5380,7 +5592,7 @@ pub const TypeId = enum {
53805592 NullLiteral,
53815593 Nullable,
53825594 ErrorUnion,
5383 Error,
5595 ErrorSet,
53845596 Enum,
53855597 Union,
53865598 Fn,
......@@ -5389,6 +5601,176 @@ pub const TypeId = enum {
53895601 BoundFn,
53905602 ArgTuple,
53915603 Opaque,
5604 Promise,
5605};
5606
5607pub const TypeInfo = union(TypeId) {
5608 Type: void,
5609 Void: void,
5610 Bool: void,
5611 NoReturn: void,
5612 Int: Int,
5613 Float: Float,
5614 Pointer: Pointer,
5615 Array: Array,
5616 Struct: Struct,
5617 FloatLiteral: void,
5618 IntLiteral: void,
5619 UndefinedLiteral: void,
5620 NullLiteral: void,
5621 Nullable: Nullable,
5622 ErrorUnion: ErrorUnion,
5623 ErrorSet: ErrorSet,
5624 Enum: Enum,
5625 Union: Union,
5626 Fn: Fn,
5627 Namespace: void,
5628 Block: void,
5629 BoundFn: Fn,
5630 ArgTuple: void,
5631 Opaque: void,
5632 Promise: Promise,
5633
5634
5635 pub const Int = struct {
5636 is_signed: bool,
5637 bits: u8,
5638 };
5639
5640 pub const Float = struct {
5641 bits: u8,
5642 };
5643
5644 pub const Pointer = struct {
5645 is_const: bool,
5646 is_volatile: bool,
5647 alignment: u32,
5648 child: type,
5649 };
5650
5651 pub const Array = struct {
5652 len: usize,
5653 child: type,
5654 };
5655
5656 pub const ContainerLayout = enum {
5657 Auto,
5658 Extern,
5659 Packed,
5660 };
5661
5662 pub const StructField = struct {
5663 name: []const u8,
5664 offset: ?usize,
5665 field_type: type,
5666 };
5667
5668 pub const Struct = struct {
5669 layout: ContainerLayout,
5670 fields: []StructField,
5671 defs: []Definition,
5672 };
5673
5674 pub const Nullable = struct {
5675 child: type,
5676 };
5677
5678 pub const ErrorUnion = struct {
5679 error_set: type,
5680 payload: type,
5681 };
5682
5683 pub const Error = struct {
5684 name: []const u8,
5685 value: usize,
5686 };
5687
5688 pub const ErrorSet = struct {
5689 errors: []Error,
5690 };
5691
5692 pub const EnumField = struct {
5693 name: []const u8,
5694 value: usize,
5695 };
5696
5697 pub const Enum = struct {
5698 layout: ContainerLayout,
5699 tag_type: type,
5700 fields: []EnumField,
5701 defs: []Definition,
5702 };
5703
5704 pub const UnionField = struct {
5705 name: []const u8,
5706 enum_field: ?EnumField,
5707 field_type: type,
5708 };
5709
5710 pub const Union = struct {
5711 layout: ContainerLayout,
5712 tag_type: type,
5713 fields: []UnionField,
5714 defs: []Definition,
5715 };
5716
5717 pub const CallingConvention = enum {
5718 Unspecified,
5719 C,
5720 Cold,
5721 Naked,
5722 Stdcall,
5723 Async,
5724 };
5725
5726 pub const FnArg = struct {
5727 is_generic: bool,
5728 is_noalias: bool,
5729 arg_type: type,
5730 };
5731
5732 pub const Fn = struct {
5733 calling_convention: CallingConvention,
5734 is_generic: bool,
5735 is_var_args: bool,
5736 return_type: type,
5737 async_allocator_type: type,
5738 args: []FnArg,
5739 };
5740
5741 pub const Promise = struct {
5742 child: type,
5743 };
5744
5745 pub const Definition = struct {
5746 name: []const u8,
5747 is_pub: bool,
5748 data: Data,
5749
5750 pub const Data = union(enum) {
5751 Type: type,
5752 Var: type,
5753 Fn: FnDef,
5754
5755 pub const FnDef = struct {
5756 fn_type: type,
5757 inline_type: Inline,
5758 calling_convention: CallingConvention,
5759 is_var_args: bool,
5760 is_extern: bool,
5761 is_export: bool,
5762 lib_name: ?[]const u8,
5763 return_type: type,
5764 arg_names: [][] const u8,
5765
5766 pub const Inline = enum {
5767 Auto,
5768 Always,
5769 Never,
5770 };
5771 };
5772 };
5773 };
53925774};
53935775
53945776pub const FloatMode = enum {
......@@ -5402,7 +5784,7 @@ pub const Endian = enum {
54025784};
54035785
54045786pub const endian = Endian.Little;
5405pub const is_test = false;
5787pub const is_test = true;
54065788pub const os = Os.linux;
54075789pub const arch = Arch.x86_64;
54085790pub const environ = Environ.gnu;
......@@ -5410,6 +5792,7 @@ pub const object_format = ObjectFormat.elf;
54105792pub const mode = Mode.Debug;
54115793pub const link_libc = false;
54125794pub const have_error_return_tracing = true;
5795pub const __zig_test_fn_slice = {}; // overwritten later
54135796 {#code_end#}
54145797 {#see_also|Build Mode#}
54155798 {#header_close#}
......@@ -6068,7 +6451,7 @@ hljs.registerLanguage("zig", function(t) {
60686451 a = t.IR + "\\s*\\(",
60696452 c = {
60706453 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",
6071 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",
6454 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",
60726455 literal: "true false null undefined"
60736456 },
60746457 n = [e, t.CLCM, t.CBCM, s, r];
src/all_types.hpp+9
......@@ -1293,6 +1293,7 @@ enum BuiltinFnId {
12931293 BuiltinFnIdMemberType,
12941294 BuiltinFnIdMemberName,
12951295 BuiltinFnIdField,
1296 BuiltinFnIdTypeInfo,
12961297 BuiltinFnIdTypeof,
12971298 BuiltinFnIdAddWithOverflow,
12981299 BuiltinFnIdSubWithOverflow,
......@@ -1506,6 +1507,7 @@ struct CodeGen {
15061507 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
15071508 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
15081509 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
1510 HashMap<const TypeTableEntry *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
15091511
15101512
15111513 ZigList<ImportTableEntry *> import_queue;
......@@ -2037,6 +2039,7 @@ enum IrInstructionId {
20372039 IrInstructionIdTagType,
20382040 IrInstructionIdFieldParentPtr,
20392041 IrInstructionIdOffsetOf,
2042 IrInstructionIdTypeInfo,
20402043 IrInstructionIdTypeId,
20412044 IrInstructionIdSetEvalBranchQuota,
20422045 IrInstructionIdPtrTypeOf,
......@@ -2858,6 +2861,12 @@ struct IrInstructionOffsetOf {
28582861 IrInstruction *field_name;
28592862};
28602863
2864struct IrInstructionTypeInfo {
2865 IrInstruction base;
2866
2867 IrInstruction *type_value;
2868};
2869
28612870struct IrInstructionTypeId {
28622871 IrInstruction base;
28632872
src/codegen.cpp+187
......@@ -88,6 +88,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
8888 g->exported_symbol_names.init(8);
8989 g->external_prototypes.init(8);
9090 g->string_literals_table.init(16);
91 g->type_info_cache.init(32);
9192 g->is_test_build = false;
9293 g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);
9394 buf_resize(&g->global_asm, 0);
......@@ -4502,6 +4503,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
45024503 case IrInstructionIdDeclRef:
45034504 case IrInstructionIdSwitchVar:
45044505 case IrInstructionIdOffsetOf:
4506 case IrInstructionIdTypeInfo:
45054507 case IrInstructionIdTypeId:
45064508 case IrInstructionIdSetEvalBranchQuota:
45074509 case IrInstructionIdPtrTypeOf:
......@@ -6125,6 +6127,7 @@ static void define_builtin_fns(CodeGen *g) {
61256127 create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2);
61266128 create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2);
61276129 create_builtin_fn(g, BuiltinFnIdField, "field", 2);
6130 create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1);
61286131 create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf
61296132 create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4);
61306133 create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4);
......@@ -6344,6 +6347,190 @@ static void define_builtin_compile_vars(CodeGen *g) {
63446347 }
63456348 buf_appendf(contents, "};\n\n");
63466349 }
6350 {
6351 buf_appendf(contents,
6352 "pub const TypeInfo = union(TypeId) {\n"
6353 " Type: void,\n"
6354 " Void: void,\n"
6355 " Bool: void,\n"
6356 " NoReturn: void,\n"
6357 " Int: Int,\n"
6358 " Float: Float,\n"
6359 " Pointer: Pointer,\n"
6360 " Array: Array,\n"
6361 " Struct: Struct,\n"
6362 " FloatLiteral: void,\n"
6363 " IntLiteral: void,\n"
6364 " UndefinedLiteral: void,\n"
6365 " NullLiteral: void,\n"
6366 " Nullable: Nullable,\n"
6367 " ErrorUnion: ErrorUnion,\n"
6368 " ErrorSet: ErrorSet,\n"
6369 " Enum: Enum,\n"
6370 " Union: Union,\n"
6371 " Fn: Fn,\n"
6372 " Namespace: void,\n"
6373 " Block: void,\n"
6374 " BoundFn: Fn,\n"
6375 " ArgTuple: void,\n"
6376 " Opaque: void,\n"
6377 " Promise: Promise,\n"
6378 "\n\n"
6379 " pub const Int = struct {\n"
6380 " is_signed: bool,\n"
6381 " bits: u8,\n"
6382 " };\n"
6383 "\n"
6384 " pub const Float = struct {\n"
6385 " bits: u8,\n"
6386 " };\n"
6387 "\n"
6388 " pub const Pointer = struct {\n"
6389 " is_const: bool,\n"
6390 " is_volatile: bool,\n"
6391 " alignment: u32,\n"
6392 " child: type,\n"
6393 " };\n"
6394 "\n"
6395 " pub const Array = struct {\n"
6396 " len: usize,\n"
6397 " child: type,\n"
6398 " };\n"
6399 "\n"
6400 " pub const ContainerLayout = enum {\n"
6401 " Auto,\n"
6402 " Extern,\n"
6403 " Packed,\n"
6404 " };\n"
6405 "\n"
6406 " pub const StructField = struct {\n"
6407 " name: []const u8,\n"
6408 " offset: ?usize,\n"
6409 " field_type: type,\n"
6410 " };\n"
6411 "\n"
6412 " pub const Struct = struct {\n"
6413 " layout: ContainerLayout,\n"
6414 " fields: []StructField,\n"
6415 " defs: []Definition,\n"
6416 " };\n"
6417 "\n"
6418 " pub const Nullable = struct {\n"
6419 " child: type,\n"
6420 " };\n"
6421 "\n"
6422 " pub const ErrorUnion = struct {\n"
6423 " error_set: type,\n"
6424 " payload: type,\n"
6425 " };\n"
6426 "\n"
6427 " pub const Error = struct {\n"
6428 " name: []const u8,\n"
6429 " value: usize,\n"
6430 " };\n"
6431 "\n"
6432 " pub const ErrorSet = struct {\n"
6433 " errors: []Error,\n"
6434 " };\n"
6435 "\n"
6436 " pub const EnumField = struct {\n"
6437 " name: []const u8,\n"
6438 " value: usize,\n"
6439 " };\n"
6440 "\n"
6441 " pub const Enum = struct {\n"
6442 " layout: ContainerLayout,\n"
6443 " tag_type: type,\n"
6444 " fields: []EnumField,\n"
6445 " defs: []Definition,\n"
6446 " };\n"
6447 "\n"
6448 " pub const UnionField = struct {\n"
6449 " name: []const u8,\n"
6450 " enum_field: ?EnumField,\n"
6451 " field_type: type,\n"
6452 " };\n"
6453 "\n"
6454 " pub const Union = struct {\n"
6455 " layout: ContainerLayout,\n"
6456 " tag_type: type,\n"
6457 " fields: []UnionField,\n"
6458 " defs: []Definition,\n"
6459 " };\n"
6460 "\n"
6461 " pub const CallingConvention = enum {\n"
6462 " Unspecified,\n"
6463 " C,\n"
6464 " Cold,\n"
6465 " Naked,\n"
6466 " Stdcall,\n"
6467 " Async,\n"
6468 " };\n"
6469 "\n"
6470 " pub const FnArg = struct {\n"
6471 " is_generic: bool,\n"
6472 " is_noalias: bool,\n"
6473 " arg_type: type,\n"
6474 " };\n"
6475 "\n"
6476 " pub const Fn = struct {\n"
6477 " calling_convention: CallingConvention,\n"
6478 " is_generic: bool,\n"
6479 " is_var_args: bool,\n"
6480 " return_type: type,\n"
6481 " async_allocator_type: type,\n"
6482 " args: []FnArg,\n"
6483 " };\n"
6484 "\n"
6485 " pub const Promise = struct {\n"
6486 " child: type,\n"
6487 " };\n"
6488 "\n"
6489 " pub const Definition = struct {\n"
6490 " name: []const u8,\n"
6491 " is_pub: bool,\n"
6492 " data: Data,\n"
6493 "\n"
6494 " pub const Data = union(enum) {\n"
6495 " Type: type,\n"
6496 " Var: type,\n"
6497 " Fn: FnDef,\n"
6498 "\n"
6499 " pub const FnDef = struct {\n"
6500 " fn_type: type,\n"
6501 " inline_type: Inline,\n"
6502 " calling_convention: CallingConvention,\n"
6503 " is_var_args: bool,\n"
6504 " is_extern: bool,\n"
6505 " is_export: bool,\n"
6506 " lib_name: ?[]const u8,\n"
6507 " return_type: type,\n"
6508 " arg_names: [][] const u8,\n"
6509 "\n"
6510 " pub const Inline = enum {\n"
6511 " Auto,\n"
6512 " Always,\n"
6513 " Never,\n"
6514 " };\n"
6515 " };\n"
6516 " };\n"
6517 " };\n"
6518 "};\n\n");
6519 assert(ContainerLayoutAuto == 0);
6520 assert(ContainerLayoutExtern == 1);
6521 assert(ContainerLayoutPacked == 2);
6522
6523 assert(CallingConventionUnspecified == 0);
6524 assert(CallingConventionC == 1);
6525 assert(CallingConventionCold == 2);
6526 assert(CallingConventionNaked == 3);
6527 assert(CallingConventionStdcall == 4);
6528 assert(CallingConventionAsync == 5);
6529
6530 assert(FnInlineAuto == 0);
6531 assert(FnInlineAlways == 1);
6532 assert(FnInlineNever == 2);
6533 }
63476534 {
63486535 buf_appendf(contents,
63496536 "pub const FloatMode = enum {\n"
src/ir.cpp+961-1
......@@ -617,6 +617,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOffsetOf *) {
617617 return IrInstructionIdOffsetOf;
618618}
619619
620static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) {
621 return IrInstructionIdTypeInfo;
622}
623
620624static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeId *) {
621625 return IrInstructionIdTypeId;
622626}
......@@ -2442,6 +2446,16 @@ static IrInstruction *ir_build_offset_of(IrBuilder *irb, Scope *scope, AstNode *
24422446 return &instruction->base;
24432447}
24442448
2449static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *source_node,
2450 IrInstruction *type_value) {
2451 IrInstructionTypeInfo *instruction = ir_build_instruction<IrInstructionTypeInfo>(irb, scope, source_node);
2452 instruction->type_value = type_value;
2453
2454 ir_ref_instruction(type_value, irb->current_basic_block);
2455
2456 return &instruction->base;
2457}
2458
24452459static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
24462460 IrInstruction *type_value)
24472461{
......@@ -4085,6 +4099,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
40854099
40864100 return ir_build_load_ptr(irb, scope, node, ptr_instruction);
40874101 }
4102 case BuiltinFnIdTypeInfo:
4103 {
4104 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4105 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4106 if (arg0_value == irb->codegen->invalid_instruction)
4107 return arg0_value;
4108
4109 IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);
4110 return ir_lval_wrap(irb, scope, type_info, lval);
4111 }
40884112 case BuiltinFnIdBreakpoint:
40894113 return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval);
40904114 case BuiltinFnIdReturnAddress:
......@@ -13388,7 +13412,6 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
1338813412 return ira->codegen->invalid_instruction;
1338913413}
1339013414
13391
1339213415static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
1339313416 IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type)
1339413417{
......@@ -13450,6 +13473,51 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1345013473 } else if (bare_type->id == TypeTableEntryIdUnion) {
1345113474 TypeUnionField *field = find_union_type_field(bare_type, field_name);
1345213475 if (field) {
13476 if (instr_is_comptime(container_ptr)) {
13477 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
13478 if (!ptr_val)
13479 return ira->codegen->invalid_instruction;
13480
13481 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
13482 ConstExprValue *union_val = const_ptr_pointee(ira->codegen, ptr_val);
13483 if (type_is_invalid(union_val->type))
13484 return ira->codegen->invalid_instruction;
13485
13486 TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag);
13487 if (actual_field == nullptr)
13488 zig_unreachable();
13489
13490 if (field != actual_field) {
13491 ir_add_error_node(ira, source_instr->source_node,
13492 buf_sprintf("accessing union field '%s' while field '%s' is set", buf_ptr(field_name),
13493 buf_ptr(actual_field->name)));
13494 return ira->codegen->invalid_instruction;
13495 }
13496
13497 ConstExprValue *payload_val = union_val->data.x_union.payload;
13498
13499 TypeTableEntry *field_type = field->type_entry;
13500 if (field_type->id == TypeTableEntryIdVoid)
13501 {
13502 assert(payload_val == nullptr);
13503 payload_val = create_const_vals(1);
13504 payload_val->special = ConstValSpecialStatic;
13505 payload_val->type = field_type;
13506 }
13507
13508 TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, is_const, is_volatile,
13509 get_abi_alignment(ira->codegen, field_type), 0, 0);
13510
13511 IrInstruction *result = ir_get_const(ira, source_instr);
13512 ConstExprValue *const_val = &result->value;
13513 const_val->data.x_ptr.special = ConstPtrSpecialRef;
13514 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
13515 const_val->data.x_ptr.data.ref.pointee = payload_val;
13516 const_val->type = ptr_type;
13517 return result;
13518 }
13519 }
13520
1345313521 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
1345413522 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
1345513523 get_abi_alignment(ira->codegen, field->type_entry), 0, 0);
......@@ -15679,6 +15747,895 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira,
1567915747 return ira->codegen->builtin_types.entry_num_lit_int;
1568015748}
1568115749
15750static void ensure_field_index(TypeTableEntry *type, const char *field_name, size_t index)
15751{
15752 Buf *field_name_buf;
15753
15754 assert(type != nullptr && !type_is_invalid(type));
15755 // Check for our field by creating a buffer in place then using the comma operator to free it so that we don't
15756 // leak memory in debug mode.
15757 assert(find_struct_type_field(type, field_name_buf = buf_create_from_str(field_name))->src_index == index &&
15758 (buf_deinit(field_name_buf), true));
15759}
15760
15761static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, TypeTableEntry *root = nullptr)
15762{
15763 static ConstExprValue *type_info_var = nullptr;
15764 static TypeTableEntry *type_info_type = nullptr;
15765 if (type_info_var == nullptr)
15766 {
15767 type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
15768 assert(type_info_var->type->id == TypeTableEntryIdMetaType);
15769
15770 ensure_complete_type(ira->codegen, type_info_var->data.x_type);
15771 type_info_type = type_info_var->data.x_type;
15772 assert(type_info_type->id == TypeTableEntryIdUnion);
15773 }
15774
15775 if (type_name == nullptr && root == nullptr)
15776 return type_info_type;
15777 else if (type_name == nullptr)
15778 return root;
15779
15780 TypeTableEntry *root_type = (root == nullptr) ? type_info_type : root;
15781
15782 ScopeDecls *type_info_scope = get_container_scope(root_type);
15783 assert(type_info_scope != nullptr);
15784
15785 Buf field_name = BUF_INIT;
15786 buf_init_from_str(&field_name, type_name);
15787 auto entry = type_info_scope->decl_table.maybe_get(&field_name);
15788 buf_deinit(&field_name);
15789 assert(entry != nullptr);
15790
15791 TldVar *tld = (TldVar *)entry->value;
15792 assert(tld->base.id == TldIdVar);
15793
15794 VariableTableEntry *var = tld->var;
15795
15796 ensure_complete_type(ira->codegen, var->value->type);
15797 assert(var->value->type->id == TypeTableEntryIdMetaType);
15798 return var->value->data.x_type;
15799}
15800
15801static void ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope)
15802{
15803 TypeTableEntry *type_info_definition_type = ir_type_info_get_type(ira, "Definition");
15804 ensure_complete_type(ira->codegen, type_info_definition_type);
15805 ensure_field_index(type_info_definition_type, "name", 0);
15806 ensure_field_index(type_info_definition_type, "is_pub", 1);
15807 ensure_field_index(type_info_definition_type, "data", 2);
15808
15809 TypeTableEntry *type_info_definition_data_type = ir_type_info_get_type(ira, "Data", type_info_definition_type);
15810 ensure_complete_type(ira->codegen, type_info_definition_data_type);
15811
15812 TypeTableEntry *type_info_fn_def_type = ir_type_info_get_type(ira, "FnDef", type_info_definition_data_type);
15813 ensure_complete_type(ira->codegen, type_info_fn_def_type);
15814
15815 TypeTableEntry *type_info_fn_def_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_def_type);
15816 ensure_complete_type(ira->codegen, type_info_fn_def_inline_type);
15817
15818 // Loop through our definitions once to figure out how many definitions we will generate info for.
15819 auto decl_it = decls_scope->decl_table.entry_iterator();
15820 decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr;
15821 int definition_count = 0;
15822
15823 while ((curr_entry = decl_it.next()) != nullptr)
15824 {
15825 // If the definition is unresolved, force it to be resolved again.
15826 if (curr_entry->value->resolution == TldResolutionUnresolved)
15827 {
15828 resolve_top_level_decl(ira->codegen, curr_entry->value, false, curr_entry->value->source_node);
15829 if (curr_entry->value->resolution != TldResolutionOk)
15830 {
15831 return;
15832 }
15833 }
15834
15835 // Skip comptime blocks and test functions.
15836 if (curr_entry->value->id != TldIdCompTime)
15837 {
15838 if (curr_entry->value->id == TldIdFn)
15839 {
15840 FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
15841 if (fn_entry->is_test)
15842 continue;
15843 }
15844
15845 definition_count += 1;
15846 }
15847 }
15848
15849 ConstExprValue *definition_array = create_const_vals(1);
15850 definition_array->special = ConstValSpecialStatic;
15851 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);
15852 definition_array->data.x_array.special = ConstArraySpecialNone;
15853 definition_array->data.x_array.s_none.parent.id = ConstParentIdNone;
15854 definition_array->data.x_array.s_none.elements = create_const_vals(definition_count);
15855 init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);
15856
15857 // Loop through the definitions and generate info.
15858 decl_it = decls_scope->decl_table.entry_iterator();
15859 curr_entry = nullptr;
15860 int definition_index = 0;
15861 while ((curr_entry = decl_it.next()) != nullptr)
15862 {
15863 // Skip comptime blocks and test functions.
15864 if (curr_entry->value->id == TldIdCompTime)
15865 continue;
15866 else if (curr_entry->value->id == TldIdFn)
15867 {
15868 FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
15869 if (fn_entry->is_test)
15870 continue;
15871 }
15872
15873 ConstExprValue *definition_val = &definition_array->data.x_array.s_none.elements[definition_index];
15874
15875 definition_val->special = ConstValSpecialStatic;
15876 definition_val->type = type_info_definition_type;
15877
15878 ConstExprValue *inner_fields = create_const_vals(3);
15879 ConstExprValue *name = create_const_str_lit(ira->codegen, curr_entry->key);
15880 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(curr_entry->key), true);
15881 inner_fields[1].special = ConstValSpecialStatic;
15882 inner_fields[1].type = ira->codegen->builtin_types.entry_bool;
15883 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;
15884 inner_fields[2].special = ConstValSpecialStatic;
15885 inner_fields[2].type = type_info_definition_data_type;
15886 inner_fields[2].data.x_union.parent.id = ConstParentIdStruct;
15887 inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val;
15888 inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1;
15889
15890 switch (curr_entry->value->id)
15891 {
15892 case TldIdVar:
15893 {
15894 VariableTableEntry *var = ((TldVar *)curr_entry->value)->var;
15895 ensure_complete_type(ira->codegen, var->value->type);
15896 if (var->value->type->id == TypeTableEntryIdMetaType)
15897 {
15898 // We have a variable of type 'type', so it's actually a type definition.
15899 // 0: Data.Type: type
15900 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
15901 inner_fields[2].data.x_union.payload = var->value;
15902 }
15903 else
15904 {
15905 // We have a variable of another type, so we store the type of the variable.
15906 // 1: Data.Var: type
15907 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);
15908
15909 ConstExprValue *payload = create_const_vals(1);
15910 payload->type = ira->codegen->builtin_types.entry_type;
15911 payload->data.x_type = var->value->type;
15912
15913 inner_fields[2].data.x_union.payload = payload;
15914 }
15915
15916 break;
15917 }
15918 case TldIdFn:
15919 {
15920 // 2: Data.Fn: Data.FnDef
15921 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 2);
15922
15923 FnTableEntry *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
15924 assert(!fn_entry->is_test);
15925
15926 analyze_fn_body(ira->codegen, fn_entry);
15927 if (fn_entry->anal_state == FnAnalStateInvalid)
15928 return;
15929
15930 AstNodeFnProto *fn_node = (AstNodeFnProto *)(fn_entry->proto_node);
15931
15932 ConstExprValue *fn_def_val = create_const_vals(1);
15933 fn_def_val->special = ConstValSpecialStatic;
15934 fn_def_val->type = type_info_fn_def_type;
15935 fn_def_val->data.x_struct.parent.id = ConstParentIdUnion;
15936 fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2];
15937
15938 ConstExprValue *fn_def_fields = create_const_vals(9);
15939 fn_def_val->data.x_struct.fields = fn_def_fields;
15940
15941 // fn_type: type
15942 ensure_field_index(fn_def_val->type, "fn_type", 0);
15943 fn_def_fields[0].special = ConstValSpecialStatic;
15944 fn_def_fields[0].type = ira->codegen->builtin_types.entry_type;
15945 fn_def_fields[0].data.x_type = fn_entry->type_entry;
15946 // inline_type: Data.FnDef.Inline
15947 ensure_field_index(fn_def_val->type, "inline_type", 1);
15948 fn_def_fields[1].special = ConstValSpecialStatic;
15949 fn_def_fields[1].type = type_info_fn_def_inline_type;
15950 bigint_init_unsigned(&fn_def_fields[1].data.x_enum_tag, fn_entry->fn_inline);
15951 // calling_convention: TypeInfo.CallingConvention
15952 ensure_field_index(fn_def_val->type, "calling_convention", 2);
15953 fn_def_fields[2].special = ConstValSpecialStatic;
15954 fn_def_fields[2].type = ir_type_info_get_type(ira, "CallingConvention");
15955 bigint_init_unsigned(&fn_def_fields[2].data.x_enum_tag, fn_node->cc);
15956 // is_var_args: bool
15957 ensure_field_index(fn_def_val->type, "is_var_args", 3);
15958 bool is_varargs = fn_node->is_var_args;
15959 fn_def_fields[3].special = ConstValSpecialStatic;
15960 fn_def_fields[3].type = ira->codegen->builtin_types.entry_bool;
15961 fn_def_fields[3].data.x_bool = is_varargs;
15962 // is_extern: bool
15963 ensure_field_index(fn_def_val->type, "is_extern", 4);
15964 fn_def_fields[4].special = ConstValSpecialStatic;
15965 fn_def_fields[4].type = ira->codegen->builtin_types.entry_bool;
15966 fn_def_fields[4].data.x_bool = fn_node->is_extern;
15967 // is_export: bool
15968 ensure_field_index(fn_def_val->type, "is_export", 5);
15969 fn_def_fields[5].special = ConstValSpecialStatic;
15970 fn_def_fields[5].type = ira->codegen->builtin_types.entry_bool;
15971 fn_def_fields[5].data.x_bool = fn_node->is_export;
15972 // lib_name: ?[]const u8
15973 ensure_field_index(fn_def_val->type, "lib_name", 6);
15974 fn_def_fields[6].special = ConstValSpecialStatic;
15975 fn_def_fields[6].type = get_maybe_type(ira->codegen,
15976 get_slice_type(ira->codegen, get_pointer_to_type(ira->codegen,
15977 ira->codegen->builtin_types.entry_u8, true)));
15978 if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0)
15979 {
15980 fn_def_fields[6].data.x_maybe = create_const_vals(1);
15981 ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name);
15982 init_const_slice(ira->codegen, fn_def_fields[6].data.x_maybe, lib_name, 0, buf_len(fn_node->lib_name), true);
15983 }
15984 else
15985 fn_def_fields[6].data.x_maybe = nullptr;
15986 // return_type: type
15987 ensure_field_index(fn_def_val->type, "return_type", 7);
15988 fn_def_fields[7].special = ConstValSpecialStatic;
15989 fn_def_fields[7].type = ira->codegen->builtin_types.entry_type;
15990 if (fn_entry->src_implicit_return_type != nullptr)
15991 fn_def_fields[7].data.x_type = fn_entry->src_implicit_return_type;
15992 else if (fn_entry->type_entry->data.fn.gen_return_type != nullptr)
15993 fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.gen_return_type;
15994 else
15995 fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
15996 // arg_names: [][] const u8
15997 ensure_field_index(fn_def_val->type, "arg_names", 8);
15998 size_t fn_arg_count = fn_entry->variable_list.length;
15999 ConstExprValue *fn_arg_name_array = create_const_vals(1);
16000 fn_arg_name_array->special = ConstValSpecialStatic;
16001 fn_arg_name_array->type = get_array_type(ira->codegen, get_slice_type(ira->codegen,
16002 get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true)), fn_arg_count);
16003 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
16004 fn_arg_name_array->data.x_array.s_none.parent.id = ConstParentIdNone;
16005 fn_arg_name_array->data.x_array.s_none.elements = create_const_vals(fn_arg_count);
16006
16007 init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);
16008
16009 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++)
16010 {
16011 VariableTableEntry *arg_var = fn_entry->variable_list.at(fn_arg_index);
16012 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.s_none.elements[fn_arg_index];
16013 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);
16014 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true);
16015 fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray;
16016 fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array;
16017 fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;
16018 }
16019
16020 inner_fields[2].data.x_union.payload = fn_def_val;
16021 break;
16022 }
16023 case TldIdContainer:
16024 {
16025 TypeTableEntry *type_entry = ((TldContainer *)curr_entry->value)->type_entry;
16026 ensure_complete_type(ira->codegen, type_entry);
16027 // This is a type.
16028 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
16029
16030 ConstExprValue *payload = create_const_vals(1);
16031 payload->type = ira->codegen->builtin_types.entry_type;
16032 payload->data.x_type = type_entry;
16033
16034 inner_fields[2].data.x_union.payload = payload;
16035
16036 break;
16037 }
16038 default:
16039 zig_unreachable();
16040 }
16041
16042 definition_val->data.x_struct.fields = inner_fields;
16043 definition_index++;
16044 }
16045
16046 assert(definition_index == definition_count);
16047}
16048
16049static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry)
16050{
16051 assert(type_entry != nullptr);
16052 assert(!type_is_invalid(type_entry));
16053
16054 ensure_complete_type(ira->codegen, type_entry);
16055
16056 const auto make_enum_field_val = [ira](ConstExprValue *enum_field_val, TypeEnumField *enum_field,
16057 TypeTableEntry *type_info_enum_field_type) {
16058 enum_field_val->special = ConstValSpecialStatic;
16059 enum_field_val->type = type_info_enum_field_type;
16060
16061 ConstExprValue *inner_fields = create_const_vals(2);
16062 inner_fields[1].special = ConstValSpecialStatic;
16063 inner_fields[1].type = ira->codegen->builtin_types.entry_usize;
16064
16065 ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name);
16066 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(enum_field->name), true);
16067
16068 bigint_init_bigint(&inner_fields[1].data.x_bigint, &enum_field->value);
16069
16070 enum_field_val->data.x_struct.fields = inner_fields;
16071 };
16072
16073 ConstExprValue *result = nullptr;
16074 switch (type_entry->id)
16075 {
16076 case TypeTableEntryIdInvalid:
16077 zig_unreachable();
16078 case TypeTableEntryIdMetaType:
16079 case TypeTableEntryIdVoid:
16080 case TypeTableEntryIdBool:
16081 case TypeTableEntryIdUnreachable:
16082 case TypeTableEntryIdNumLitFloat:
16083 case TypeTableEntryIdNumLitInt:
16084 case TypeTableEntryIdUndefLit:
16085 case TypeTableEntryIdNullLit:
16086 case TypeTableEntryIdNamespace:
16087 case TypeTableEntryIdBlock:
16088 case TypeTableEntryIdArgTuple:
16089 case TypeTableEntryIdOpaque:
16090 return nullptr;
16091 default:
16092 {
16093 // Lookup an available value in our cache.
16094 auto entry = ira->codegen->type_info_cache.maybe_get(type_entry);
16095 if (entry != nullptr)
16096 return entry->value;
16097
16098 // Fallthrough if we don't find one.
16099 }
16100 case TypeTableEntryIdInt:
16101 {
16102 result = create_const_vals(1);
16103 result->special = ConstValSpecialStatic;
16104 result->type = ir_type_info_get_type(ira, "Int");
16105
16106 ConstExprValue *fields = create_const_vals(2);
16107 result->data.x_struct.fields = fields;
16108
16109 // is_signed: bool
16110 ensure_field_index(result->type, "is_signed", 0);
16111 fields[0].special = ConstValSpecialStatic;
16112 fields[0].type = ira->codegen->builtin_types.entry_bool;
16113 fields[0].data.x_bool = type_entry->data.integral.is_signed;
16114 // bits: u8
16115 ensure_field_index(result->type, "bits", 1);
16116 fields[1].special = ConstValSpecialStatic;
16117 fields[1].type = ira->codegen->builtin_types.entry_u8;
16118 bigint_init_unsigned(&fields[1].data.x_bigint, type_entry->data.integral.bit_count);
16119
16120 break;
16121 }
16122 case TypeTableEntryIdFloat:
16123 {
16124 result = create_const_vals(1);
16125 result->special = ConstValSpecialStatic;
16126 result->type = ir_type_info_get_type(ira, "Float");
16127
16128 ConstExprValue *fields = create_const_vals(1);
16129 result->data.x_struct.fields = fields;
16130
16131 // bits: u8
16132 ensure_field_index(result->type, "bits", 0);
16133 fields[0].special = ConstValSpecialStatic;
16134 fields[0].type = ira->codegen->builtin_types.entry_u8;
16135 bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.floating.bit_count);
16136
16137 break;
16138 }
16139 case TypeTableEntryIdPointer:
16140 {
16141 result = create_const_vals(1);
16142 result->special = ConstValSpecialStatic;
16143 result->type = ir_type_info_get_type(ira, "Pointer");
16144
16145 ConstExprValue *fields = create_const_vals(4);
16146 result->data.x_struct.fields = fields;
16147
16148 // is_const: bool
16149 ensure_field_index(result->type, "is_const", 0);
16150 fields[0].special = ConstValSpecialStatic;
16151 fields[0].type = ira->codegen->builtin_types.entry_bool;
16152 fields[0].data.x_bool = type_entry->data.pointer.is_const;
16153 // is_volatile: bool
16154 ensure_field_index(result->type, "is_volatile", 1);
16155 fields[1].special = ConstValSpecialStatic;
16156 fields[1].type = ira->codegen->builtin_types.entry_bool;
16157 fields[1].data.x_bool = type_entry->data.pointer.is_volatile;
16158 // alignment: u32
16159 ensure_field_index(result->type, "alignment", 2);
16160 fields[2].special = ConstValSpecialStatic;
16161 fields[2].type = ira->codegen->builtin_types.entry_u32;
16162 bigint_init_unsigned(&fields[2].data.x_bigint, type_entry->data.pointer.alignment);
16163 // child: type
16164 ensure_field_index(result->type, "child", 3);
16165 fields[3].special = ConstValSpecialStatic;
16166 fields[3].type = ira->codegen->builtin_types.entry_type;
16167 fields[3].data.x_type = type_entry->data.pointer.child_type;
16168
16169 break;
16170 }
16171 case TypeTableEntryIdArray:
16172 {
16173 result = create_const_vals(1);
16174 result->special = ConstValSpecialStatic;
16175 result->type = ir_type_info_get_type(ira, "Array");
16176
16177 ConstExprValue *fields = create_const_vals(2);
16178 result->data.x_struct.fields = fields;
16179
16180 // len: usize
16181 ensure_field_index(result->type, "len", 0);
16182 fields[0].special = ConstValSpecialStatic;
16183 fields[0].type = ira->codegen->builtin_types.entry_usize;
16184 bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.array.len);
16185 // child: type
16186 ensure_field_index(result->type, "child", 1);
16187 fields[1].special = ConstValSpecialStatic;
16188 fields[1].type = ira->codegen->builtin_types.entry_type;
16189 fields[1].data.x_type = type_entry->data.array.child_type;
16190
16191 break;
16192 }
16193 case TypeTableEntryIdMaybe:
16194 {
16195 result = create_const_vals(1);
16196 result->special = ConstValSpecialStatic;
16197 result->type = ir_type_info_get_type(ira, "Nullable");
16198
16199 ConstExprValue *fields = create_const_vals(1);
16200 result->data.x_struct.fields = fields;
16201
16202 // child: type
16203 ensure_field_index(result->type, "child", 0);
16204 fields[0].special = ConstValSpecialStatic;
16205 fields[0].type = ira->codegen->builtin_types.entry_type;
16206 fields[0].data.x_type = type_entry->data.maybe.child_type;
16207
16208 break;
16209 }
16210 case TypeTableEntryIdPromise:
16211 {
16212 result = create_const_vals(1);
16213 result->special = ConstValSpecialStatic;
16214 result->type = ir_type_info_get_type(ira, "Promise");
16215
16216 ConstExprValue *fields = create_const_vals(1);
16217 result->data.x_struct.fields = fields;
16218
16219 // @TODO ?type instead of using @typeOf(undefined) when we have no type.
16220 // child: type
16221 ensure_field_index(result->type, "child", 0);
16222 fields[0].special = ConstValSpecialStatic;
16223 fields[0].type = ira->codegen->builtin_types.entry_type;
16224
16225 if (type_entry->data.promise.result_type == nullptr)
16226 fields[0].data.x_type = ira->codegen->builtin_types.entry_undef;
16227 else
16228 fields[0].data.x_type = type_entry->data.promise.result_type;
16229
16230 break;
16231 }
16232 case TypeTableEntryIdEnum:
16233 {
16234 result = create_const_vals(1);
16235 result->special = ConstValSpecialStatic;
16236 result->type = ir_type_info_get_type(ira, "Enum");
16237
16238 ConstExprValue *fields = create_const_vals(4);
16239 result->data.x_struct.fields = fields;
16240
16241 // layout: ContainerLayout
16242 ensure_field_index(result->type, "layout", 0);
16243 fields[0].special = ConstValSpecialStatic;
16244 fields[0].type = ir_type_info_get_type(ira, "ContainerLayout");
16245 bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.enumeration.layout);
16246 // tag_type: type
16247 ensure_field_index(result->type, "tag_type", 1);
16248 fields[1].special = ConstValSpecialStatic;
16249 fields[1].type = ira->codegen->builtin_types.entry_type;
16250 fields[1].data.x_type = type_entry->data.enumeration.tag_int_type;
16251 // fields: []TypeInfo.EnumField
16252 ensure_field_index(result->type, "fields", 2);
16253
16254 TypeTableEntry *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField");
16255 uint32_t enum_field_count = type_entry->data.enumeration.src_field_count;
16256
16257 ConstExprValue *enum_field_array = create_const_vals(1);
16258 enum_field_array->special = ConstValSpecialStatic;
16259 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);
16260 enum_field_array->data.x_array.special = ConstArraySpecialNone;
16261 enum_field_array->data.x_array.s_none.parent.id = ConstParentIdNone;
16262 enum_field_array->data.x_array.s_none.elements = create_const_vals(enum_field_count);
16263
16264 init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false);
16265
16266 for (uint32_t enum_field_index = 0; enum_field_index < enum_field_count; enum_field_index++)
16267 {
16268 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
16269 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.s_none.elements[enum_field_index];
16270 make_enum_field_val(enum_field_val, enum_field, type_info_enum_field_type);
16271 enum_field_val->data.x_struct.parent.id = ConstParentIdArray;
16272 enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array;
16273 enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index;
16274 }
16275 // defs: []TypeInfo.Definition
16276 ensure_field_index(result->type, "defs", 3);
16277 ir_make_type_info_defs(ira, &fields[3], type_entry->data.enumeration.decls_scope);
16278
16279 break;
16280 }
16281 case TypeTableEntryIdErrorSet:
16282 {
16283 result = create_const_vals(1);
16284 result->special = ConstValSpecialStatic;
16285 result->type = ir_type_info_get_type(ira, "ErrorSet");
16286
16287 ConstExprValue *fields = create_const_vals(1);
16288 result->data.x_struct.fields = fields;
16289
16290 // errors: []TypeInfo.Error
16291 ensure_field_index(result->type, "errors", 0);
16292
16293 TypeTableEntry *type_info_error_type = ir_type_info_get_type(ira, "Error");
16294 uint32_t error_count = type_entry->data.error_set.err_count;
16295 ConstExprValue *error_array = create_const_vals(1);
16296 error_array->special = ConstValSpecialStatic;
16297 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);
16298 error_array->data.x_array.special = ConstArraySpecialNone;
16299 error_array->data.x_array.s_none.parent.id = ConstParentIdNone;
16300 error_array->data.x_array.s_none.elements = create_const_vals(error_count);
16301
16302 init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);
16303 for (uint32_t error_index = 0; error_index < error_count; error_index++)
16304 {
16305 ErrorTableEntry *error = type_entry->data.error_set.errors[error_index];
16306 ConstExprValue *error_val = &error_array->data.x_array.s_none.elements[error_index];
16307
16308 error_val->special = ConstValSpecialStatic;
16309 error_val->type = type_info_error_type;
16310
16311 ConstExprValue *inner_fields = create_const_vals(2);
16312 inner_fields[1].special = ConstValSpecialStatic;
16313 inner_fields[1].type = ira->codegen->builtin_types.entry_usize;
16314
16315 ConstExprValue *name = nullptr;
16316 if (error->cached_error_name_val != nullptr)
16317 name = error->cached_error_name_val;
16318 if (name == nullptr)
16319 name = create_const_str_lit(ira->codegen, &error->name);
16320 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(&error->name), true);
16321 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);
16322
16323 error_val->data.x_struct.fields = inner_fields;
16324 error_val->data.x_struct.parent.id = ConstParentIdArray;
16325 error_val->data.x_struct.parent.data.p_array.array_val = error_array;
16326 error_val->data.x_struct.parent.data.p_array.elem_index = error_index;
16327 }
16328
16329 break;
16330 }
16331 case TypeTableEntryIdErrorUnion:
16332 {
16333 result = create_const_vals(1);
16334 result->special = ConstValSpecialStatic;
16335 result->type = ir_type_info_get_type(ira, "ErrorUnion");
16336
16337 ConstExprValue *fields = create_const_vals(2);
16338 result->data.x_struct.fields = fields;
16339
16340 // error_set: type
16341 ensure_field_index(result->type, "error_set", 0);
16342 fields[0].special = ConstValSpecialStatic;
16343 fields[0].type = ira->codegen->builtin_types.entry_type;
16344 fields[0].data.x_type = type_entry->data.error_union.err_set_type;
16345
16346 // payload: type
16347 ensure_field_index(result->type, "payload", 1);
16348 fields[1].special = ConstValSpecialStatic;
16349 fields[1].type = ira->codegen->builtin_types.entry_type;
16350 fields[1].data.x_type = type_entry->data.error_union.payload_type;
16351
16352 break;
16353 }
16354 case TypeTableEntryIdUnion:
16355 {
16356 result = create_const_vals(1);
16357 result->special = ConstValSpecialStatic;
16358 result->type = ir_type_info_get_type(ira, "Union");
16359
16360 ConstExprValue *fields = create_const_vals(4);
16361 result->data.x_struct.fields = fields;
16362
16363 // layout: ContainerLayout
16364 ensure_field_index(result->type, "layout", 0);
16365 fields[0].special = ConstValSpecialStatic;
16366 fields[0].type = ir_type_info_get_type(ira, "ContainerLayout");
16367 bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.unionation.layout);
16368 // tag_type: type
16369 ensure_field_index(result->type, "tag_type", 1);
16370 fields[1].special = ConstValSpecialStatic;
16371 fields[1].type = ira->codegen->builtin_types.entry_type;
16372 // @TODO ?type instead of using @typeOf(undefined) when we have no type.
16373 AstNode *union_decl_node = type_entry->data.unionation.decl_node;
16374 if (union_decl_node->data.container_decl.auto_enum ||
16375 union_decl_node->data.container_decl.init_arg_expr != nullptr)
16376 {
16377 fields[1].data.x_type = type_entry->data.unionation.tag_type;
16378 }
16379 else
16380 fields[1].data.x_type = ira->codegen->builtin_types.entry_undef;
16381 // fields: []TypeInfo.UnionField
16382 ensure_field_index(result->type, "fields", 2);
16383
16384 TypeTableEntry *type_info_union_field_type = ir_type_info_get_type(ira, "UnionField");
16385 uint32_t union_field_count = type_entry->data.unionation.src_field_count;
16386
16387 ConstExprValue *union_field_array = create_const_vals(1);
16388 union_field_array->special = ConstValSpecialStatic;
16389 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);
16390 union_field_array->data.x_array.special = ConstArraySpecialNone;
16391 union_field_array->data.x_array.s_none.parent.id = ConstParentIdNone;
16392 union_field_array->data.x_array.s_none.elements = create_const_vals(union_field_count);
16393
16394 init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false);
16395
16396 TypeTableEntry *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField");
16397
16398 for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++)
16399 {
16400 TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index];
16401 ConstExprValue *union_field_val = &union_field_array->data.x_array.s_none.elements[union_field_index];
16402
16403 union_field_val->special = ConstValSpecialStatic;
16404 union_field_val->type = type_info_union_field_type;
16405
16406 ConstExprValue *inner_fields = create_const_vals(3);
16407 inner_fields[1].special = ConstValSpecialStatic;
16408 inner_fields[1].type = get_maybe_type(ira->codegen, type_info_enum_field_type);
16409
16410 if (fields[1].data.x_type == ira->codegen->builtin_types.entry_undef)
16411 inner_fields[1].data.x_maybe = nullptr;
16412 else
16413 {
16414 inner_fields[1].data.x_maybe = create_const_vals(1);
16415 make_enum_field_val(inner_fields[1].data.x_maybe, union_field->enum_field, type_info_enum_field_type);
16416 }
16417
16418 inner_fields[2].special = ConstValSpecialStatic;
16419 inner_fields[2].type = ira->codegen->builtin_types.entry_type;
16420 inner_fields[2].data.x_type = union_field->type_entry;
16421
16422 ConstExprValue *name = create_const_str_lit(ira->codegen, union_field->name);
16423 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);
16424
16425 union_field_val->data.x_struct.fields = inner_fields;
16426 union_field_val->data.x_struct.parent.id = ConstParentIdArray;
16427 union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array;
16428 union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index;
16429 }
16430 // defs: []TypeInfo.Definition
16431 ensure_field_index(result->type, "defs", 3);
16432 ir_make_type_info_defs(ira, &fields[3], type_entry->data.unionation.decls_scope);
16433
16434 break;
16435 }
16436 case TypeTableEntryIdStruct:
16437 {
16438 result = create_const_vals(1);
16439 result->special = ConstValSpecialStatic;
16440 result->type = ir_type_info_get_type(ira, "Struct");
16441
16442 ConstExprValue *fields = create_const_vals(3);
16443 result->data.x_struct.fields = fields;
16444
16445 // layout: ContainerLayout
16446 ensure_field_index(result->type, "layout", 0);
16447 fields[0].special = ConstValSpecialStatic;
16448 fields[0].type = ir_type_info_get_type(ira, "ContainerLayout");
16449 bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.structure.layout);
16450 // fields: []TypeInfo.StructField
16451 ensure_field_index(result->type, "fields", 1);
16452
16453 TypeTableEntry *type_info_struct_field_type = ir_type_info_get_type(ira, "StructField");
16454 uint32_t struct_field_count = type_entry->data.structure.src_field_count;
16455
16456 ConstExprValue *struct_field_array = create_const_vals(1);
16457 struct_field_array->special = ConstValSpecialStatic;
16458 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);
16459 struct_field_array->data.x_array.special = ConstArraySpecialNone;
16460 struct_field_array->data.x_array.s_none.parent.id = ConstParentIdNone;
16461 struct_field_array->data.x_array.s_none.elements = create_const_vals(struct_field_count);
16462
16463 init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false);
16464
16465 for (uint32_t struct_field_index = 0; struct_field_index < struct_field_count; struct_field_index++)
16466 {
16467 TypeStructField *struct_field = &type_entry->data.structure.fields[struct_field_index];
16468 ConstExprValue *struct_field_val = &struct_field_array->data.x_array.s_none.elements[struct_field_index];
16469
16470 struct_field_val->special = ConstValSpecialStatic;
16471 struct_field_val->type = type_info_struct_field_type;
16472
16473 ConstExprValue *inner_fields = create_const_vals(3);
16474 inner_fields[1].special = ConstValSpecialStatic;
16475 inner_fields[1].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_usize);
16476
16477 if (!type_has_bits(struct_field->type_entry))
16478 inner_fields[1].data.x_maybe = nullptr;
16479 else
16480 {
16481 size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, type_entry->type_ref, struct_field->gen_index);
16482 inner_fields[1].data.x_maybe = create_const_vals(1);
16483 inner_fields[1].data.x_maybe->type = ira->codegen->builtin_types.entry_usize;
16484 bigint_init_unsigned(&inner_fields[1].data.x_maybe->data.x_bigint, byte_offset);
16485 }
16486
16487 inner_fields[2].special = ConstValSpecialStatic;
16488 inner_fields[2].type = ira->codegen->builtin_types.entry_type;
16489 inner_fields[2].data.x_type = struct_field->type_entry;
16490
16491 ConstExprValue *name = create_const_str_lit(ira->codegen, struct_field->name);
16492 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);
16493
16494 struct_field_val->data.x_struct.fields = inner_fields;
16495 struct_field_val->data.x_struct.parent.id = ConstParentIdArray;
16496 struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array;
16497 struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index;
16498 }
16499 // defs: []TypeInfo.Definition
16500 ensure_field_index(result->type, "defs", 2);
16501 ir_make_type_info_defs(ira, &fields[2], type_entry->data.structure.decls_scope);
16502
16503 break;
16504 }
16505 case TypeTableEntryIdFn:
16506 {
16507 result = create_const_vals(1);
16508 result->special = ConstValSpecialStatic;
16509 result->type = ir_type_info_get_type(ira, "Fn");
16510
16511 ConstExprValue *fields = create_const_vals(6);
16512 result->data.x_struct.fields = fields;
16513
16514 // @TODO Fix type = undefined with ?type
16515
16516 // calling_convention: TypeInfo.CallingConvention
16517 ensure_field_index(result->type, "calling_convention", 0);
16518 fields[0].special = ConstValSpecialStatic;
16519 fields[0].type = ir_type_info_get_type(ira, "CallingConvention");
16520 bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.fn.fn_type_id.cc);
16521 // is_generic: bool
16522 ensure_field_index(result->type, "is_generic", 1);
16523 bool is_generic = type_entry->data.fn.is_generic;
16524 fields[1].special = ConstValSpecialStatic;
16525 fields[1].type = ira->codegen->builtin_types.entry_bool;
16526 fields[1].data.x_bool = is_generic;
16527 // is_varargs: bool
16528 ensure_field_index(result->type, "is_var_args", 2);
16529 bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
16530 fields[2].special = ConstValSpecialStatic;
16531 fields[2].type = ira->codegen->builtin_types.entry_bool;
16532 fields[2].data.x_bool = type_entry->data.fn.fn_type_id.is_var_args;
16533 // return_type: type
16534 ensure_field_index(result->type, "return_type", 3);
16535 fields[3].special = ConstValSpecialStatic;
16536 fields[3].type = ira->codegen->builtin_types.entry_type;
16537 if (type_entry->data.fn.fn_type_id.return_type == nullptr)
16538 fields[3].data.x_type = ira->codegen->builtin_types.entry_undef;
16539 else
16540 fields[3].data.x_type = type_entry->data.fn.fn_type_id.return_type;
16541 // async_allocator_type: type
16542 ensure_field_index(result->type, "async_allocator_type", 4);
16543 fields[4].special = ConstValSpecialStatic;
16544 fields[4].type = ira->codegen->builtin_types.entry_type;
16545 if (type_entry->data.fn.fn_type_id.async_allocator_type == nullptr)
16546 fields[4].data.x_type = ira->codegen->builtin_types.entry_undef;
16547 else
16548 fields[4].data.x_type = type_entry->data.fn.fn_type_id.async_allocator_type;
16549 // args: []TypeInfo.FnArg
16550 TypeTableEntry *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg");
16551 size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count -
16552 (is_varargs && type_entry->data.fn.fn_type_id.cc != CallingConventionC);
16553
16554 ConstExprValue *fn_arg_array = create_const_vals(1);
16555 fn_arg_array->special = ConstValSpecialStatic;
16556 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);
16557 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
16558 fn_arg_array->data.x_array.s_none.parent.id = ConstParentIdNone;
16559 fn_arg_array->data.x_array.s_none.elements = create_const_vals(fn_arg_count);
16560
16561 init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false);
16562
16563 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++)
16564 {
16565 FnTypeParamInfo *fn_param_info = &type_entry->data.fn.fn_type_id.param_info[fn_arg_index];
16566 ConstExprValue *fn_arg_val = &fn_arg_array->data.x_array.s_none.elements[fn_arg_index];
16567
16568 fn_arg_val->special = ConstValSpecialStatic;
16569 fn_arg_val->type = type_info_fn_arg_type;
16570
16571 bool arg_is_generic = fn_param_info->type == nullptr;
16572 if (arg_is_generic) assert(is_generic);
16573
16574 ConstExprValue *inner_fields = create_const_vals(3);
16575 inner_fields[0].special = ConstValSpecialStatic;
16576 inner_fields[0].type = ira->codegen->builtin_types.entry_bool;
16577 inner_fields[0].data.x_bool = arg_is_generic;
16578 inner_fields[1].special = ConstValSpecialStatic;
16579 inner_fields[1].type = ira->codegen->builtin_types.entry_bool;
16580 inner_fields[1].data.x_bool = fn_param_info->is_noalias;
16581 inner_fields[2].special = ConstValSpecialStatic;
16582 inner_fields[2].type = ira->codegen->builtin_types.entry_type;
16583
16584 if (arg_is_generic)
16585 inner_fields[2].data.x_type = ira->codegen->builtin_types.entry_undef;
16586 else
16587 inner_fields[2].data.x_type = fn_param_info->type;
16588
16589 fn_arg_val->data.x_struct.fields = inner_fields;
16590 fn_arg_val->data.x_struct.parent.id = ConstParentIdArray;
16591 fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array;
16592 fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;
16593 }
16594
16595 break;
16596 }
16597 case TypeTableEntryIdBoundFn:
16598 {
16599 TypeTableEntry *fn_type = type_entry->data.bound_fn.fn_type;
16600 assert(fn_type->id == TypeTableEntryIdFn);
16601 result = ir_make_type_info_value(ira, fn_type);
16602
16603 break;
16604 }
16605 }
16606
16607 assert(result != nullptr);
16608 ira->codegen->type_info_cache.put(type_entry, result);
16609 return result;
16610}
16611
16612static TypeTableEntry *ir_analyze_instruction_type_info(IrAnalyze *ira,
16613 IrInstructionTypeInfo *instruction)
16614{
16615 IrInstruction *type_value = instruction->type_value->other;
16616 TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
16617 if (type_is_invalid(type_entry))
16618 return ira->codegen->builtin_types.entry_invalid;
16619
16620 TypeTableEntry *result_type = ir_type_info_get_type(ira, nullptr);
16621
16622 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
16623 out_val->type = result_type;
16624 bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry->id));
16625
16626 ConstExprValue *payload = ir_make_type_info_value(ira, type_entry);
16627 out_val->data.x_union.payload = payload;
16628
16629 if (payload != nullptr)
16630 {
16631 assert(payload->type->id == TypeTableEntryIdStruct);
16632 payload->data.x_struct.parent.id = ConstParentIdUnion;
16633 payload->data.x_struct.parent.data.p_union.union_val = out_val;
16634 }
16635
16636 return result_type;
16637}
16638
1568216639static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira,
1568316640 IrInstructionTypeId *instruction)
1568416641{
......@@ -18580,6 +19537,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1858019537 return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction);
1858119538 case IrInstructionIdOffsetOf:
1858219539 return ir_analyze_instruction_offset_of(ira, (IrInstructionOffsetOf *)instruction);
19540 case IrInstructionIdTypeInfo:
19541 return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction);
1858319542 case IrInstructionIdTypeId:
1858419543 return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction);
1858519544 case IrInstructionIdSetEvalBranchQuota:
......@@ -18846,6 +19805,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1884619805 case IrInstructionIdTagName:
1884719806 case IrInstructionIdFieldParentPtr:
1884819807 case IrInstructionIdOffsetOf:
19808 case IrInstructionIdTypeInfo:
1884919809 case IrInstructionIdTypeId:
1885019810 case IrInstructionIdAlignCast:
1885119811 case IrInstructionIdOpaqueType:
src/ir_print.cpp+9
......@@ -966,6 +966,12 @@ static void ir_print_offset_of(IrPrint *irp, IrInstructionOffsetOf *instruction)
966966 fprintf(irp->f, ")");
967967}
968968
969static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction) {
970 fprintf(irp->f, "@typeInfo(");
971 ir_print_other_instruction(irp, instruction->type_value);
972 fprintf(irp->f, ")");
973}
974
969975static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) {
970976 fprintf(irp->f, "@typeId(");
971977 ir_print_other_instruction(irp, instruction->type_value);
......@@ -1536,6 +1542,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
15361542 case IrInstructionIdOffsetOf:
15371543 ir_print_offset_of(irp, (IrInstructionOffsetOf *)instruction);
15381544 break;
1545 case IrInstructionIdTypeInfo:
1546 ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction);
1547 break;
15391548 case IrInstructionIdTypeId:
15401549 ir_print_type_id(irp, (IrInstructionTypeId *)instruction);
15411550 break;
test/behavior.zig+1
......@@ -36,6 +36,7 @@ comptime {
3636 _ = @import("cases/pub_enum/index.zig");
3737 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
3838 _ = @import("cases/reflection.zig");
39 _ = @import("cases/type_info.zig");
3940 _ = @import("cases/sizeof_and_typeof.zig");
4041 _ = @import("cases/slice.zig");
4142 _ = @import("cases/struct.zig");
test/cases/type_info.zig created+181
......@@ -0,0 +1,181 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const TypeInfo = @import("builtin").TypeInfo;
4const TypeId = @import("builtin").TypeId;
5
6test "type info: tag type, void info" {
7 comptime {
8 assert(@TagType(TypeInfo) == TypeId);
9 const void_info = @typeInfo(void);
10 assert(TypeId(void_info) == TypeId.Void);
11 assert(void_info.Void == {});
12 }
13}
14
15test "type info: integer, floating point type info" {
16 comptime {
17 const u8_info = @typeInfo(u8);
18 assert(TypeId(u8_info) == TypeId.Int);
19 assert(!u8_info.Int.is_signed);
20 assert(u8_info.Int.bits == 8);
21
22 const f64_info = @typeInfo(f64);
23 assert(TypeId(f64_info) == TypeId.Float);
24 assert(f64_info.Float.bits == 64);
25 }
26}
27
28test "type info: pointer, array and nullable type info" {
29 comptime {
30 const u32_ptr_info = @typeInfo(&u32);
31 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
32 assert(u32_ptr_info.Pointer.is_const == false);
33 assert(u32_ptr_info.Pointer.is_volatile == false);
34 assert(u32_ptr_info.Pointer.alignment == 4);
35 assert(u32_ptr_info.Pointer.child == u32);
36
37 const arr_info = @typeInfo([42]bool);
38 assert(TypeId(arr_info) == TypeId.Array);
39 assert(arr_info.Array.len == 42);
40 assert(arr_info.Array.child == bool);
41
42 const null_info = @typeInfo(?void);
43 assert(TypeId(null_info) == TypeId.Nullable);
44 assert(null_info.Nullable.child == void);
45 }
46}
47
48test "type info: promise info" {
49 comptime {
50 const null_promise_info = @typeInfo(promise);
51 assert(TypeId(null_promise_info) == TypeId.Promise);
52 assert(null_promise_info.Promise.child == @typeOf(undefined));
53
54 const promise_info = @typeInfo(promise->usize);
55 assert(TypeId(promise_info) == TypeId.Promise);
56 assert(promise_info.Promise.child == usize);
57 }
58
59}
60
61test "type info: error set, error union info" {
62 comptime {
63 const TestErrorSet = error {
64 First,
65 Second,
66 Third,
67 };
68
69 const error_set_info = @typeInfo(TestErrorSet);
70 assert(TypeId(error_set_info) == TypeId.ErrorSet);
71 assert(error_set_info.ErrorSet.errors.len == 3);
72 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
73 assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third));
74
75 const error_union_info = @typeInfo(TestErrorSet!usize);
76 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
77 assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
78 assert(error_union_info.ErrorUnion.payload == usize);
79 }
80}
81
82test "type info: enum info" {
83 comptime {
84 const Os = @import("builtin").Os;
85
86 const os_info = @typeInfo(Os);
87 assert(TypeId(os_info) == TypeId.Enum);
88 assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
89 assert(os_info.Enum.fields.len == 32);
90 assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
91 assert(os_info.Enum.fields[10].value == 10);
92 assert(os_info.Enum.tag_type == u5);
93 assert(os_info.Enum.defs.len == 0);
94 }
95}
96
97test "type info: union info" {
98 comptime {
99 const typeinfo_info = @typeInfo(TypeInfo);
100 assert(TypeId(typeinfo_info) == TypeId.Union);
101 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
102 assert(typeinfo_info.Union.tag_type == TypeId);
103 assert(typeinfo_info.Union.fields.len == 25);
104 assert(typeinfo_info.Union.fields[4].enum_field != null);
105 assert((??typeinfo_info.Union.fields[4].enum_field).value == 4);
106 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
107 assert(typeinfo_info.Union.defs.len == 20);
108
109 const TestNoTagUnion = union {
110 Foo: void,
111 Bar: u32,
112 };
113
114 const notag_union_info = @typeInfo(TestNoTagUnion);
115 assert(TypeId(notag_union_info) == TypeId.Union);
116 assert(notag_union_info.Union.tag_type == @typeOf(undefined));
117 assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
118 assert(notag_union_info.Union.fields.len == 2);
119 assert(notag_union_info.Union.fields[0].enum_field == null);
120 assert(notag_union_info.Union.fields[1].field_type == u32);
121
122 const TestExternUnion = extern union {
123 foo: &c_void,
124 };
125
126 const extern_union_info = @typeInfo(TestExternUnion);
127 assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
128 assert(extern_union_info.Union.tag_type == @typeOf(undefined));
129 assert(extern_union_info.Union.fields[0].enum_field == null);
130 assert(extern_union_info.Union.fields[0].field_type == &c_void);
131 }
132}
133
134test "type info: struct info" {
135 comptime {
136 const struct_info = @typeInfo(TestStruct);
137 assert(TypeId(struct_info) == TypeId.Struct);
138 assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
139 assert(struct_info.Struct.fields.len == 3);
140 assert(struct_info.Struct.fields[1].offset == null);
141 assert(struct_info.Struct.fields[2].field_type == &TestStruct);
142 assert(struct_info.Struct.defs.len == 2);
143 assert(struct_info.Struct.defs[0].is_pub);
144 assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
145 assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
146 assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
147 assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void);
148 }
149}
150
151const TestStruct = packed struct {
152 const Self = this;
153
154 fieldA: usize,
155 fieldB: void,
156 fieldC: &Self,
157
158 pub fn foo(self: &const Self) void {}
159};
160
161test "type info: function type info" {
162 comptime {
163 const fn_info = @typeInfo(@typeOf(foo));
164 assert(TypeId(fn_info) == TypeId.Fn);
165 assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
166 assert(fn_info.Fn.is_generic);
167 assert(fn_info.Fn.args.len == 2);
168 assert(fn_info.Fn.is_var_args);
169 assert(fn_info.Fn.return_type == @typeOf(undefined));
170 assert(fn_info.Fn.async_allocator_type == @typeOf(undefined));
171
172 const test_instance: TestStruct = undefined;
173 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
174 assert(TypeId(bound_fn_info) == TypeId.BoundFn);
175 assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct);
176 }
177}
178
179fn foo(comptime a: usize, b: bool, args: ...) usize {
180 return 0;
181}
test/cases/union.zig+10
......@@ -45,6 +45,16 @@ test "basic unions" {
4545 assert(foo.float == 12.34);
4646}
4747
48test "comptime union field access" {
49 comptime {
50 var foo = Foo { .int = 0 };
51 assert(foo.int == 0);
52
53 foo = Foo { .float = 42.42 };
54 assert(foo.float == 42.42);
55 }
56}
57
4858test "init union with runtime value" {
4959 var foo: Foo = undefined;
5060
test/compile_errors.zig+12-1
......@@ -3210,6 +3210,18 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
32103210 ,
32113211 ".tmp_source.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset");
32123212
3213 cases.add("invalid union field access in comptime",
3214 \\const Foo = union {
3215 \\ Bar: u8,
3216 \\ Baz: void,
3217 \\};
3218 \\comptime {
3219 \\ var foo = Foo {.Baz = {}};
3220 \\ const bar_val = foo.Bar;
3221 \\}
3222 ,
3223 ".tmp_source.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set");
3224
32133225 cases.add("getting return type of generic function",
32143226 \\fn generic(a: var) void {}
32153227 \\comptime {
......@@ -3225,5 +3237,4 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
32253237 \\}
32263238 ,
32273239 ".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic");
3228
32293240}