authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-04 11:12:24-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-04 11:12:24-04:00
log53a6aea216d7b1e6b6072d30f2d51ed801d9e0f9
tree41809dbfec90af3c6320239cd186f9ede7b8b8e1
parent77a5f888be664f9ef09e2c93f52338448e992e00
parentac7703f65f7acc9137e28ded97659fbaadea4e66
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'marler8997-typeBuiltin'


9 files changed, 468 insertions(+), 23 deletions(-)

doc/docgen.zig+24-2
...@@ -321,6 +321,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -321,6 +321,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
321321
322 var header_stack_size: usize = 0;322 var header_stack_size: usize = 0;
323 var last_action = Action.Open;323 var last_action = Action.Open;
324 var last_columns: ?u8 = null;
324325
325 var toc_buf = try std.Buffer.initSize(allocator, 0);326 var toc_buf = try std.Buffer.initSize(allocator, 0);
326 defer toc_buf.deinit();327 defer toc_buf.deinit();
...@@ -361,7 +362,23 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -361,7 +362,23 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
361 _ = try eatToken(tokenizer, Token.Id.Separator);362 _ = try eatToken(tokenizer, Token.Id.Separator);
362 const content_token = try eatToken(tokenizer, Token.Id.TagContent);363 const content_token = try eatToken(tokenizer, Token.Id.TagContent);
363 const content = tokenizer.buffer[content_token.start..content_token.end];364 const content = tokenizer.buffer[content_token.start..content_token.end];
364 _ = try eatToken(tokenizer, Token.Id.BracketClose);365 var columns: ?u8 = null;
366 while (true) {
367 const bracket_tok = tokenizer.next();
368 switch (bracket_tok.id) {
369 .BracketClose => break,
370 .Separator => continue,
371 .TagContent => {
372 const param = tokenizer.buffer[bracket_tok.start..bracket_tok.end];
373 if (mem.eql(u8, param, "3col")) {
374 columns = 3;
375 } else {
376 return parseError(tokenizer, bracket_tok, "unrecognized header_open param: {}", param);
377 }
378 },
379 else => return parseError(tokenizer, bracket_tok, "invalid header_open token"),
380 }
381 }
365382
366 header_stack_size += 1;383 header_stack_size += 1;
367384
...@@ -381,10 +398,15 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -381,10 +398,15 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
381 if (last_action == Action.Open) {398 if (last_action == Action.Open) {
382 try toc.writeByte('\n');399 try toc.writeByte('\n');
383 try toc.writeByteNTimes(' ', header_stack_size * 4);400 try toc.writeByteNTimes(' ', header_stack_size * 4);
384 try toc.write("<ul>\n");401 if (last_columns) |n| {
402 try toc.print("<ul style=\"columns: {}\">\n", n);
403 } else {
404 try toc.write("<ul>\n");
405 }
385 } else {406 } else {
386 last_action = Action.Open;407 last_action = Action.Open;
387 }408 }
409 last_columns = columns;
388 try toc.writeByteNTimes(' ', 4 + header_stack_size * 4);410 try toc.writeByteNTimes(' ', 4 + header_stack_size * 4);
389 try toc.print("<li><a id=\"toc-{}\" href=\"#{}\">{}</a>", urlized, urlized, content);411 try toc.print("<li><a id=\"toc-{}\" href=\"#{}\">{}</a>", urlized, urlized, content);
390 } else if (mem.eql(u8, tag_name, "header_close")) {412 } else if (mem.eql(u8, tag_name, "header_close")) {
doc/langref.html.in+55-1
...@@ -6323,7 +6323,7 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 {...@@ -6323,7 +6323,7 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 {
6323 {#header_close#}6323 {#header_close#}
63246324
6325 {#header_close#}6325 {#header_close#}
6326 {#header_open|Builtin Functions#}6326 {#header_open|Builtin Functions|3col#}
6327 <p>6327 <p>
6328 Builtin functions are provided by the compiler and are prefixed with <code>@</code>.6328 Builtin functions are provided by the compiler and are prefixed with <code>@</code>.
6329 The {#syntax#}comptime{#endsyntax#} keyword on a parameter means that the parameter must be known6329 The {#syntax#}comptime{#endsyntax#} keyword on a parameter means that the parameter must be known
...@@ -7232,6 +7232,9 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -7232,6 +7232,9 @@ fn add(a: i32, b: i32) i32 { return a + b; }
7232 This function returns an integer type with the given signness and bit count. The maximum7232 This function returns an integer type with the given signness and bit count. The maximum
7233 bit count for an integer type is {#syntax#}65535{#endsyntax#}.7233 bit count for an integer type is {#syntax#}65535{#endsyntax#}.
7234 </p>7234 </p>
7235 <p>
7236 Deprecated. Use {#link|@Type#}.
7237 </p>
7235 {#header_close#}7238 {#header_close#}
72367239
7237 {#header_open|@memberCount#}7240 {#header_open|@memberCount#}
...@@ -7871,6 +7874,57 @@ test "integer truncation" {...@@ -7871,6 +7874,57 @@ test "integer truncation" {
7871 </p>7874 </p>
7872 {#header_close#}7875 {#header_close#}
78737876
7877 {#header_open|@Type#}
7878 <pre>{#syntax#}@Type(comptime info: @import("builtin").TypeInfo) type{#endsyntax#}</pre>
7879 <p>
7880 This function is the inverse of {#link|@typeInfo#}. It reifies type information
7881 into a {#syntax#}type{#endsyntax#}.
7882 </p>
7883 <p>
7884 It is available for the following types:
7885 </p>
7886 <ul>
7887 <li>{#syntax#}type{#endsyntax#}</li>
7888 <li>{#syntax#}noreturn{#endsyntax#}</li>
7889 <li>{#syntax#}void{#endsyntax#}</li>
7890 <li>{#syntax#}bool{#endsyntax#}</li>
7891 <li>{#link|Integers#}</li> - The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}.
7892 <li>{#link|Floats#}</li>
7893 <li>{#link|Pointers#}</li>
7894 <li>{#syntax#}comptime_int{#endsyntax#}</li>
7895 <li>{#syntax#}comptime_float{#endsyntax#}</li>
7896 <li>{#syntax#}@typeOf(undefined){#endsyntax#}</li>
7897 <li>{#syntax#}@typeOf(null){#endsyntax#}</li>
7898 </ul>
7899 <p>
7900 For these types it is a
7901 <a href="https://github.com/ziglang/zig/issues/2907">TODO in the compiler to implement</a>:
7902 </p>
7903 <ul>
7904 <li>Array</li>
7905 <li>Optional</li>
7906 <li>ErrorUnion</li>
7907 <li>ErrorSet</li>
7908 <li>Enum</li>
7909 <li>Opaque</li>
7910 <li>FnFrame</li>
7911 <li>AnyFrame</li>
7912 <li>Vector</li>
7913 <li>EnumLiteral</li>
7914 </ul>
7915 <p>
7916 For these types, {#syntax#}@Type{#endsyntax#} is not available.
7917 <a href="https://github.com/ziglang/zig/issues/383">There is an open proposal to allow unions and structs</a>.
7918 </p>
7919 <ul>
7920 <li>{#link|union#}</li>
7921 <li>{#link|Functions#}</li>
7922 <li>BoundFn</li>
7923 <li>ArgTuple</li>
7924 <li>{#link|struct#}</li>
7925 </ul>
7926 {#header_close#}
7927
7874 {#header_open|@typeId#}7928 {#header_open|@typeId#}
7875 <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>7929 <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>
7876 <p>7930 <p>
src/all_types.hpp+16
...@@ -54,6 +54,14 @@ enum PtrLen {...@@ -54,6 +54,14 @@ enum PtrLen {
54 PtrLenC,54 PtrLenC,
55};55};
5656
57// This one corresponds to the builtin.zig enum.
58enum BuiltinPtrSize {
59 BuiltinPtrSizeOne,
60 BuiltinPtrSizeMany,
61 BuiltinPtrSizeSlice,
62 BuiltinPtrSizeC,
63};
64
57enum UndefAllowed {65enum UndefAllowed {
58 UndefOk,66 UndefOk,
59 UndefBad,67 UndefBad,
...@@ -1534,6 +1542,7 @@ enum BuiltinFnId {...@@ -1534,6 +1542,7 @@ enum BuiltinFnId {
1534 BuiltinFnIdMemberName,1542 BuiltinFnIdMemberName,
1535 BuiltinFnIdField,1543 BuiltinFnIdField,
1536 BuiltinFnIdTypeInfo,1544 BuiltinFnIdTypeInfo,
1545 BuiltinFnIdType,
1537 BuiltinFnIdHasField,1546 BuiltinFnIdHasField,
1538 BuiltinFnIdTypeof,1547 BuiltinFnIdTypeof,
1539 BuiltinFnIdAddWithOverflow,1548 BuiltinFnIdAddWithOverflow,
...@@ -2436,6 +2445,7 @@ enum IrInstructionId {...@@ -2436,6 +2445,7 @@ enum IrInstructionId {
2436 IrInstructionIdByteOffsetOf,2445 IrInstructionIdByteOffsetOf,
2437 IrInstructionIdBitOffsetOf,2446 IrInstructionIdBitOffsetOf,
2438 IrInstructionIdTypeInfo,2447 IrInstructionIdTypeInfo,
2448 IrInstructionIdType,
2439 IrInstructionIdHasField,2449 IrInstructionIdHasField,
2440 IrInstructionIdTypeId,2450 IrInstructionIdTypeId,
2441 IrInstructionIdSetEvalBranchQuota,2451 IrInstructionIdSetEvalBranchQuota,
...@@ -3472,6 +3482,12 @@ struct IrInstructionTypeInfo {...@@ -3472,6 +3482,12 @@ struct IrInstructionTypeInfo {
3472 IrInstruction *type_value;3482 IrInstruction *type_value;
3473};3483};
34743484
3485struct IrInstructionType {
3486 IrInstruction base;
3487
3488 IrInstruction *type_info;
3489};
3490
3475struct IrInstructionHasField {3491struct IrInstructionHasField {
3476 IrInstruction base;3492 IrInstruction base;
34773493
src/codegen.cpp+21-14
...@@ -5770,6 +5770,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5770,6 +5770,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5770 case IrInstructionIdByteOffsetOf:5770 case IrInstructionIdByteOffsetOf:
5771 case IrInstructionIdBitOffsetOf:5771 case IrInstructionIdBitOffsetOf:
5772 case IrInstructionIdTypeInfo:5772 case IrInstructionIdTypeInfo:
5773 case IrInstructionIdType:
5773 case IrInstructionIdHasField:5774 case IrInstructionIdHasField:
5774 case IrInstructionIdTypeId:5775 case IrInstructionIdTypeId:
5775 case IrInstructionIdSetEvalBranchQuota:5776 case IrInstructionIdSetEvalBranchQuota:
...@@ -7597,6 +7598,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -7597,6 +7598,7 @@ static void define_builtin_fns(CodeGen *g) {
7597 create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2);7598 create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2);
7598 create_builtin_fn(g, BuiltinFnIdField, "field", 2);7599 create_builtin_fn(g, BuiltinFnIdField, "field", 2);
7599 create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1);7600 create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1);
7601 create_builtin_fn(g, BuiltinFnIdType, "Type", 1);
7600 create_builtin_fn(g, BuiltinFnIdHasField, "hasField", 2);7602 create_builtin_fn(g, BuiltinFnIdHasField, "hasField", 2);
7601 create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf7603 create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf
7602 create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4);7604 create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4);
...@@ -8159,20 +8161,25 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -8159,20 +8161,25 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
8159 " };\n"8161 " };\n"
8160 " };\n"8162 " };\n"
8161 "};\n\n");8163 "};\n\n");
8162 assert(ContainerLayoutAuto == 0);8164 static_assert(ContainerLayoutAuto == 0, "");
8163 assert(ContainerLayoutExtern == 1);8165 static_assert(ContainerLayoutExtern == 1, "");
8164 assert(ContainerLayoutPacked == 2);8166 static_assert(ContainerLayoutPacked == 2, "");
81658167
8166 assert(CallingConventionUnspecified == 0);8168 static_assert(CallingConventionUnspecified == 0, "");
8167 assert(CallingConventionC == 1);8169 static_assert(CallingConventionC == 1, "");
8168 assert(CallingConventionCold == 2);8170 static_assert(CallingConventionCold == 2, "");
8169 assert(CallingConventionNaked == 3);8171 static_assert(CallingConventionNaked == 3, "");
8170 assert(CallingConventionStdcall == 4);8172 static_assert(CallingConventionStdcall == 4, "");
8171 assert(CallingConventionAsync == 5);8173 static_assert(CallingConventionAsync == 5, "");
81728174
8173 assert(FnInlineAuto == 0);8175 static_assert(FnInlineAuto == 0, "");
8174 assert(FnInlineAlways == 1);8176 static_assert(FnInlineAlways == 1, "");
8175 assert(FnInlineNever == 2);8177 static_assert(FnInlineNever == 2, "");
8178
8179 static_assert(BuiltinPtrSizeOne == 0, "");
8180 static_assert(BuiltinPtrSizeMany == 1, "");
8181 static_assert(BuiltinPtrSizeSlice == 2, "");
8182 static_assert(BuiltinPtrSizeC == 3, "");
8176 }8183 }
8177 {8184 {
8178 buf_appendf(contents,8185 buf_appendf(contents,
src/ir.cpp+181-6
...@@ -912,6 +912,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) {...@@ -912,6 +912,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) {
912 return IrInstructionIdTypeInfo;912 return IrInstructionIdTypeInfo;
913}913}
914914
915static constexpr IrInstructionId ir_instruction_id(IrInstructionType *) {
916 return IrInstructionIdType;
917}
918
915static constexpr IrInstructionId ir_instruction_id(IrInstructionHasField *) {919static constexpr IrInstructionId ir_instruction_id(IrInstructionHasField *) {
916 return IrInstructionIdHasField;920 return IrInstructionIdHasField;
917}921}
...@@ -2907,6 +2911,15 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *...@@ -2907,6 +2911,15 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
2907 return &instruction->base;2911 return &instruction->base;
2908}2912}
29092913
2914static IrInstruction *ir_build_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_info) {
2915 IrInstructionType *instruction = ir_build_instruction<IrInstructionType>(irb, scope, source_node);
2916 instruction->type_info = type_info;
2917
2918 ir_ref_instruction(type_info, irb->current_basic_block);
2919
2920 return &instruction->base;
2921}
2922
2910static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,2923static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
2911 IrInstruction *type_value)2924 IrInstruction *type_value)
2912{2925{
...@@ -5046,6 +5059,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5046,6 +5059,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5046 IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);5059 IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);
5047 return ir_lval_wrap(irb, scope, type_info, lval, result_loc);5060 return ir_lval_wrap(irb, scope, type_info, lval, result_loc);
5048 }5061 }
5062 case BuiltinFnIdType:
5063 {
5064 AstNode *arg_node = node->data.fn_call_expr.params.at(0);
5065 IrInstruction *arg = ir_gen_node(irb, arg_node, scope);
5066 if (arg == irb->codegen->invalid_instruction)
5067 return arg;
5068
5069 IrInstruction *type = ir_build_type(irb, scope, node, arg);
5070 return ir_lval_wrap(irb, scope, type, lval, result_loc);
5071 }
5049 case BuiltinFnIdBreakpoint:5072 case BuiltinFnIdBreakpoint:
5050 return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc);5073 return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc);
5051 case BuiltinFnIdReturnAddress:5074 case BuiltinFnIdReturnAddress:
...@@ -20092,14 +20115,27 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -20092,14 +20115,27 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
20092 return ErrorNone;20115 return ErrorNone;
20093}20116}
2009420117
20095static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {20118static BuiltinPtrSize ptr_len_to_size_enum_index(PtrLen ptr_len) {
20096 switch (ptr_len) {20119 switch (ptr_len) {
20097 case PtrLenSingle:20120 case PtrLenSingle:
20098 return 0;20121 return BuiltinPtrSizeOne;
20099 case PtrLenUnknown:20122 case PtrLenUnknown:
20100 return 1;20123 return BuiltinPtrSizeMany;
20101 case PtrLenC:20124 case PtrLenC:
20102 return 3;20125 return BuiltinPtrSizeC;
20126 }
20127 zig_unreachable();
20128}
20129
20130static PtrLen size_enum_index_to_ptr_len(BuiltinPtrSize size_enum_index) {
20131 switch (size_enum_index) {
20132 case BuiltinPtrSizeOne:
20133 return PtrLenSingle;
20134 case BuiltinPtrSizeMany:
20135 case BuiltinPtrSizeSlice:
20136 return PtrLenUnknown;
20137 case BuiltinPtrSizeC:
20138 return PtrLenC;
20103 }20139 }
20104 zig_unreachable();20140 zig_unreachable();
20105}20141}
...@@ -20107,10 +20143,10 @@ static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {...@@ -20107,10 +20143,10 @@ static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {
20107static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {20143static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
20108 Error err;20144 Error err;
20109 ZigType *attrs_type;20145 ZigType *attrs_type;
20110 uint32_t size_enum_index;20146 BuiltinPtrSize size_enum_index;
20111 if (is_slice(ptr_type_entry)) {20147 if (is_slice(ptr_type_entry)) {
20112 attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry;20148 attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry;
20113 size_enum_index = 2;20149 size_enum_index = BuiltinPtrSizeSlice;
20114 } else if (ptr_type_entry->id == ZigTypeIdPointer) {20150 } else if (ptr_type_entry->id == ZigTypeIdPointer) {
20115 attrs_type = ptr_type_entry;20151 attrs_type = ptr_type_entry;
20116 size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len);20152 size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len);
...@@ -20789,6 +20825,142 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,...@@ -20789,6 +20825,142 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
20789 return result;20825 return result;
20790}20826}
2079120827
20828static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
20829{
20830 ensure_field_index(struct_value->type, name, field_index);
20831 assert(struct_value->data.x_struct.fields[field_index].special == ConstValSpecialStatic);
20832 return &struct_value->data.x_struct.fields[field_index];
20833}
20834
20835static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
20836{
20837 ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);
20838 assert(value->type == ira->codegen->builtin_types.entry_bool);
20839 return value->data.x_bool;
20840}
20841
20842static BigInt *get_const_field_lit_int(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
20843{
20844 ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);
20845 assert(value->type == ira->codegen->builtin_types.entry_num_lit_int);
20846 return &value->data.x_bigint;
20847}
20848
20849static ZigType *get_const_field_meta_type(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
20850{
20851 ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);
20852 assert(value->type == ira->codegen->builtin_types.entry_type);
20853 return value->data.x_type;
20854}
20855
20856static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) {
20857 switch (tagTypeId) {
20858 case ZigTypeIdInvalid:
20859 zig_unreachable();
20860 case ZigTypeIdMetaType:
20861 return ira->codegen->builtin_types.entry_type;
20862 case ZigTypeIdVoid:
20863 return ira->codegen->builtin_types.entry_void;
20864 case ZigTypeIdBool:
20865 return ira->codegen->builtin_types.entry_bool;
20866 case ZigTypeIdUnreachable:
20867 return ira->codegen->builtin_types.entry_unreachable;
20868 case ZigTypeIdInt:
20869 assert(payload->special == ConstValSpecialStatic);
20870 assert(payload->type == ir_type_info_get_type(ira, "Int", nullptr));
20871 return get_int_type(ira->codegen,
20872 get_const_field_bool(ira, payload, "is_signed", 0),
20873 bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 1)));
20874 case ZigTypeIdFloat:
20875 {
20876 assert(payload->special == ConstValSpecialStatic);
20877 assert(payload->type == ir_type_info_get_type(ira, "Float", nullptr));
20878 uint32_t bits = bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 0));
20879 switch (bits) {
20880 case 16: return ira->codegen->builtin_types.entry_f16;
20881 case 32: return ira->codegen->builtin_types.entry_f32;
20882 case 64: return ira->codegen->builtin_types.entry_f64;
20883 case 128: return ira->codegen->builtin_types.entry_f128;
20884 }
20885 ir_add_error(ira, instruction,
20886 buf_sprintf("%d-bit float unsupported", bits));
20887 return nullptr;
20888 }
20889 case ZigTypeIdPointer:
20890 {
20891 ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr);
20892 assert(payload->special == ConstValSpecialStatic);
20893 assert(payload->type == type_info_pointer_type);
20894 ConstExprValue *size_value = get_const_field(ira, payload, "size", 0);
20895 assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));
20896 BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);
20897 PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);
20898 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen,
20899 get_const_field_meta_type(ira, payload, "child", 4),
20900 get_const_field_bool(ira, payload, "is_const", 1),
20901 get_const_field_bool(ira, payload, "is_volatile", 2),
20902 ptr_len,
20903 bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)),
20904 0, // bit_offset_in_host
20905 0, // host_int_bytes
20906 get_const_field_bool(ira, payload, "is_allowzero", 5)
20907 );
20908 if (size_enum_index != 2)
20909 return ptr_type;
20910 return get_slice_type(ira->codegen, ptr_type);
20911 }
20912 case ZigTypeIdComptimeFloat:
20913 return ira->codegen->builtin_types.entry_num_lit_float;
20914 case ZigTypeIdComptimeInt:
20915 return ira->codegen->builtin_types.entry_num_lit_int;
20916 case ZigTypeIdUndefined:
20917 return ira->codegen->builtin_types.entry_undef;
20918 case ZigTypeIdNull:
20919 return ira->codegen->builtin_types.entry_null;
20920 case ZigTypeIdArray:
20921 case ZigTypeIdOptional:
20922 case ZigTypeIdErrorUnion:
20923 case ZigTypeIdErrorSet:
20924 case ZigTypeIdEnum:
20925 case ZigTypeIdOpaque:
20926 case ZigTypeIdFnFrame:
20927 case ZigTypeIdAnyFrame:
20928 case ZigTypeIdVector:
20929 case ZigTypeIdEnumLiteral:
20930 ir_add_error(ira, instruction, buf_sprintf(
20931 "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));
20932 return nullptr;
20933 case ZigTypeIdUnion:
20934 case ZigTypeIdFn:
20935 case ZigTypeIdBoundFn:
20936 case ZigTypeIdArgTuple:
20937 case ZigTypeIdStruct:
20938 ir_add_error(ira, instruction, buf_sprintf(
20939 "@Type not availble for 'TypeInfo.%s'", type_id_name(tagTypeId)));
20940 return nullptr;
20941 }
20942 zig_unreachable();
20943}
20944
20945static IrInstruction *ir_analyze_instruction_type(IrAnalyze *ira, IrInstructionType *instruction) {
20946 IrInstruction *type_info_ir = instruction->type_info->child;
20947 if (type_is_invalid(type_info_ir->value.type))
20948 return ira->codegen->invalid_instruction;
20949
20950 IrInstruction *casted_ir = ir_implicit_cast(ira, type_info_ir, ir_type_info_get_type(ira, nullptr, nullptr));
20951 if (type_is_invalid(casted_ir->value.type))
20952 return ira->codegen->invalid_instruction;
20953
20954 ConstExprValue *type_info_value = ir_resolve_const(ira, casted_ir, UndefBad);
20955 if (!type_info_value)
20956 return ira->codegen->invalid_instruction;
20957 ZigTypeId typeId = type_id_at_index(bigint_as_usize(&type_info_value->data.x_union.tag));
20958 ZigType *type = type_info_to_type(ira, type_info_ir, typeId, type_info_value->data.x_union.payload);
20959 if (!type)
20960 return ira->codegen->invalid_instruction;
20961 return ir_const_type(ira, &instruction->base, type);
20962}
20963
20792static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,20964static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
20793 IrInstructionTypeId *instruction)20965 IrInstructionTypeId *instruction)
20794{20966{
...@@ -25295,6 +25467,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25295,6 +25467,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25295 return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction);25467 return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction);
25296 case IrInstructionIdTypeInfo:25468 case IrInstructionIdTypeInfo:
25297 return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction);25469 return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction);
25470 case IrInstructionIdType:
25471 return ir_analyze_instruction_type(ira, (IrInstructionType *)instruction);
25298 case IrInstructionIdHasField:25472 case IrInstructionIdHasField:
25299 return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction);25473 return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction);
25300 case IrInstructionIdTypeId:25474 case IrInstructionIdTypeId:
...@@ -25598,6 +25772,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -25598,6 +25772,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
25598 case IrInstructionIdByteOffsetOf:25772 case IrInstructionIdByteOffsetOf:
25599 case IrInstructionIdBitOffsetOf:25773 case IrInstructionIdBitOffsetOf:
25600 case IrInstructionIdTypeInfo:25774 case IrInstructionIdTypeInfo:
25775 case IrInstructionIdType:
25601 case IrInstructionIdHasField:25776 case IrInstructionIdHasField:
25602 case IrInstructionIdTypeId:25777 case IrInstructionIdTypeId:
25603 case IrInstructionIdAlignCast:25778 case IrInstructionIdAlignCast:
src/ir_print.cpp+11
...@@ -280,6 +280,8 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {...@@ -280,6 +280,8 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {
280 return "BitOffsetOf";280 return "BitOffsetOf";
281 case IrInstructionIdTypeInfo:281 case IrInstructionIdTypeInfo:
282 return "TypeInfo";282 return "TypeInfo";
283 case IrInstructionIdType:
284 return "Type";
283 case IrInstructionIdHasField:285 case IrInstructionIdHasField:
284 return "HasField";286 return "HasField";
285 case IrInstructionIdTypeId:287 case IrInstructionIdTypeId:
...@@ -1627,6 +1629,12 @@ static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction)...@@ -1627,6 +1629,12 @@ static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction)
1627 fprintf(irp->f, ")");1629 fprintf(irp->f, ")");
1628}1630}
16291631
1632static void ir_print_type(IrPrint *irp, IrInstructionType *instruction) {
1633 fprintf(irp->f, "@Type(");
1634 ir_print_other_instruction(irp, instruction->type_info);
1635 fprintf(irp->f, ")");
1636}
1637
1630static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction) {1638static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction) {
1631 fprintf(irp->f, "@hasField(");1639 fprintf(irp->f, "@hasField(");
1632 ir_print_other_instruction(irp, instruction->container_type);1640 ir_print_other_instruction(irp, instruction->container_type);
...@@ -2258,6 +2266,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2258,6 +2266,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2258 case IrInstructionIdTypeInfo:2266 case IrInstructionIdTypeInfo:
2259 ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction);2267 ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction);
2260 break;2268 break;
2269 case IrInstructionIdType:
2270 ir_print_type(irp, (IrInstructionType *)instruction);
2271 break;
2261 case IrInstructionIdHasField:2272 case IrInstructionIdHasField:
2262 ir_print_has_field(irp, (IrInstructionHasField *)instruction);2273 ir_print_has_field(irp, (IrInstructionHasField *)instruction);
2263 break;2274 break;
test/compile_errors.zig+52
...@@ -2,6 +2,58 @@ const tests = @import("tests.zig");...@@ -2,6 +2,58 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "attempt to create 17 bit float type",
7 \\const builtin = @import("builtin");
8 \\comptime {
9 \\ _ = @Type(builtin.TypeInfo { .Float = builtin.TypeInfo.Float { .bits = 17 } });
10 \\}
11 ,
12 "tmp.zig:3:32: error: 17-bit float unsupported",
13 );
14
15 cases.add(
16 "wrong type for @Type",
17 \\export fn entry() void {
18 \\ _ = @Type(0);
19 \\}
20 ,
21 "tmp.zig:2:15: error: expected type 'builtin.TypeInfo', found 'comptime_int'",
22 );
23
24 cases.add(
25 "@Type with non-constant expression",
26 \\const builtin = @import("builtin");
27 \\var globalTypeInfo : builtin.TypeInfo = undefined;
28 \\export fn entry() void {
29 \\ _ = @Type(globalTypeInfo);
30 \\}
31 ,
32 "tmp.zig:4:15: error: unable to evaluate constant expression",
33 );
34
35 cases.add(
36 "@Type with TypeInfo.Int",
37 \\const builtin = @import("builtin");
38 \\export fn entry() void {
39 \\ _ = @Type(builtin.TypeInfo.Int {
40 \\ .is_signed = true,
41 \\ .bits = 8,
42 \\ });
43 \\}
44 ,
45 "tmp.zig:3:36: error: expected type 'builtin.TypeInfo', found 'builtin.Int'",
46 );
47
48 cases.add(
49 "Struct unavailable for @Type",
50 \\export fn entry() void {
51 \\ _ = @Type(@typeInfo(struct { }));
52 \\}
53 ,
54 "tmp.zig:2:15: error: @Type not availble for 'TypeInfo.Struct'",
55 );
56
5 cases.add(57 cases.add(
6 "wrong type for result ptr to @asyncCall",58 "wrong type for result ptr to @asyncCall",
7 \\export fn entry() void {59 \\export fn entry() void {
test/stage1/behavior.zig+1
...@@ -93,6 +93,7 @@ comptime {...@@ -93,6 +93,7 @@ comptime {
93 _ = @import("behavior/this.zig");93 _ = @import("behavior/this.zig");
94 _ = @import("behavior/truncate.zig");94 _ = @import("behavior/truncate.zig");
95 _ = @import("behavior/try.zig");95 _ = @import("behavior/try.zig");
96 _ = @import("behavior/type.zig");
96 _ = @import("behavior/type_info.zig");97 _ = @import("behavior/type_info.zig");
97 _ = @import("behavior/typename.zig");98 _ = @import("behavior/typename.zig");
98 _ = @import("behavior/undefined.zig");99 _ = @import("behavior/undefined.zig");
test/stage1/behavior/type.zig created+107
...@@ -0,0 +1,107 @@
1const builtin = @import("builtin");
2const TypeInfo = builtin.TypeInfo;
3
4const std = @import("std");
5const testing = std.testing;
6
7fn testTypes(comptime types: []const type) void {
8 inline for (types) |testType| {
9 testing.expect(testType == @Type(@typeInfo(testType)));
10 }
11}
12
13test "Type.MetaType" {
14 testing.expect(type == @Type(TypeInfo { .Type = undefined }));
15 testTypes([_]type {type});
16}
17
18test "Type.Void" {
19 testing.expect(void == @Type(TypeInfo { .Void = undefined }));
20 testTypes([_]type {void});
21}
22
23test "Type.Bool" {
24 testing.expect(bool == @Type(TypeInfo { .Bool = undefined }));
25 testTypes([_]type {bool});
26}
27
28test "Type.NoReturn" {
29 testing.expect(noreturn == @Type(TypeInfo { .NoReturn = undefined }));
30 testTypes([_]type {noreturn});
31}
32
33test "Type.Int" {
34 testing.expect(u1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 1 } }));
35 testing.expect(i1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 1 } }));
36 testing.expect(u8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 8 } }));
37 testing.expect(i8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 8 } }));
38 testing.expect(u64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 64 } }));
39 testing.expect(i64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 64 } }));
40 testTypes([_]type {u8,u32,i64});
41}
42
43test "Type.Float" {
44 testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 16 } }));
45 testing.expect(f32 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 32 } }));
46 testing.expect(f64 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 64 } }));
47 testing.expect(f128 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 128 } }));
48 testTypes([_]type {f16, f32, f64, f128});
49}
50
51test "Type.Pointer" {
52 testTypes([_]type {
53 // One Value Pointer Types
54 *u8, *const u8,
55 *volatile u8, *const volatile u8,
56 *align(4) u8, *const align(4) u8,
57 *volatile align(4) u8, *const volatile align(4) u8,
58 *align(8) u8, *const align(8) u8,
59 *volatile align(8) u8, *const volatile align(8) u8,
60 *allowzero u8, *const allowzero u8,
61 *volatile allowzero u8, *const volatile allowzero u8,
62 *align(4) allowzero u8, *const align(4) allowzero u8,
63 *volatile align(4) allowzero u8, *const volatile align(4) allowzero u8,
64 // Many Values Pointer Types
65 [*]u8, [*]const u8,
66 [*]volatile u8, [*]const volatile u8,
67 [*]align(4) u8, [*]const align(4) u8,
68 [*]volatile align(4) u8, [*]const volatile align(4) u8,
69 [*]align(8) u8, [*]const align(8) u8,
70 [*]volatile align(8) u8, [*]const volatile align(8) u8,
71 [*]allowzero u8, [*]const allowzero u8,
72 [*]volatile allowzero u8, [*]const volatile allowzero u8,
73 [*]align(4) allowzero u8, [*]const align(4) allowzero u8,
74 [*]volatile align(4) allowzero u8, [*]const volatile align(4) allowzero u8,
75 // Slice Types
76 []u8, []const u8,
77 []volatile u8, []const volatile u8,
78 []align(4) u8, []const align(4) u8,
79 []volatile align(4) u8, []const volatile align(4) u8,
80 []align(8) u8, []const align(8) u8,
81 []volatile align(8) u8, []const volatile align(8) u8,
82 []allowzero u8, []const allowzero u8,
83 []volatile allowzero u8, []const volatile allowzero u8,
84 []align(4) allowzero u8, []const align(4) allowzero u8,
85 []volatile align(4) allowzero u8, []const volatile align(4) allowzero u8,
86 // C Pointer Types
87 [*c]u8, [*c]const u8,
88 [*c]volatile u8, [*c]const volatile u8,
89 [*c]align(4) u8, [*c]const align(4) u8,
90 [*c]volatile align(4) u8, [*c]const volatile align(4) u8,
91 [*c]align(8) u8, [*c]const align(8) u8,
92 [*c]volatile align(8) u8, [*c]const volatile align(8) u8,
93 });
94}
95
96test "Type.ComptimeFloat" {
97 testTypes([_]type {comptime_float});
98}
99test "Type.ComptimeInt" {
100 testTypes([_]type {comptime_int});
101}
102test "Type.Undefined" {
103 testTypes([_]type {@typeOf(undefined)});
104}
105test "Type.Null" {
106 testTypes([_]type {@typeOf(null)});
107}