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 {
321321
322322 var header_stack_size: usize = 0;
323323 var last_action = Action.Open;
324 var last_columns: ?u8 = null;
324325
325326 var toc_buf = try std.Buffer.initSize(allocator, 0);
326327 defer toc_buf.deinit();
......@@ -361,7 +362,23 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
361362 _ = try eatToken(tokenizer, Token.Id.Separator);
362363 const content_token = try eatToken(tokenizer, Token.Id.TagContent);
363364 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
366383 header_stack_size += 1;
367384
......@@ -381,10 +398,15 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
381398 if (last_action == Action.Open) {
382399 try toc.writeByte('\n');
383400 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 }
385406 } else {
386407 last_action = Action.Open;
387408 }
409 last_columns = columns;
388410 try toc.writeByteNTimes(' ', 4 + header_stack_size * 4);
389411 try toc.print("<li><a id=\"toc-{}\" href=\"#{}\">{}</a>", urlized, urlized, content);
390412 } 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 {
63236323 {#header_close#}
63246324
63256325 {#header_close#}
6326 {#header_open|Builtin Functions#}
6326 {#header_open|Builtin Functions|3col#}
63276327 <p>
63286328 Builtin functions are provided by the compiler and are prefixed with <code>@</code>.
63296329 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; }
72327232 This function returns an integer type with the given signness and bit count. The maximum
72337233 bit count for an integer type is {#syntax#}65535{#endsyntax#}.
72347234 </p>
7235 <p>
7236 Deprecated. Use {#link|@Type#}.
7237 </p>
72357238 {#header_close#}
72367239
72377240 {#header_open|@memberCount#}
......@@ -7871,6 +7874,57 @@ test "integer truncation" {
78717874 </p>
78727875 {#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
78747928 {#header_open|@typeId#}
78757929 <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>
78767930 <p>
src/all_types.hpp+16
......@@ -54,6 +54,14 @@ enum PtrLen {
5454 PtrLenC,
5555};
5656
57// This one corresponds to the builtin.zig enum.
58enum BuiltinPtrSize {
59 BuiltinPtrSizeOne,
60 BuiltinPtrSizeMany,
61 BuiltinPtrSizeSlice,
62 BuiltinPtrSizeC,
63};
64
5765enum UndefAllowed {
5866 UndefOk,
5967 UndefBad,
......@@ -1534,6 +1542,7 @@ enum BuiltinFnId {
15341542 BuiltinFnIdMemberName,
15351543 BuiltinFnIdField,
15361544 BuiltinFnIdTypeInfo,
1545 BuiltinFnIdType,
15371546 BuiltinFnIdHasField,
15381547 BuiltinFnIdTypeof,
15391548 BuiltinFnIdAddWithOverflow,
......@@ -2436,6 +2445,7 @@ enum IrInstructionId {
24362445 IrInstructionIdByteOffsetOf,
24372446 IrInstructionIdBitOffsetOf,
24382447 IrInstructionIdTypeInfo,
2448 IrInstructionIdType,
24392449 IrInstructionIdHasField,
24402450 IrInstructionIdTypeId,
24412451 IrInstructionIdSetEvalBranchQuota,
......@@ -3472,6 +3482,12 @@ struct IrInstructionTypeInfo {
34723482 IrInstruction *type_value;
34733483};
34743484
3485struct IrInstructionType {
3486 IrInstruction base;
3487
3488 IrInstruction *type_info;
3489};
3490
34753491struct IrInstructionHasField {
34763492 IrInstruction base;
34773493
src/codegen.cpp+21-14
......@@ -5770,6 +5770,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
57705770 case IrInstructionIdByteOffsetOf:
57715771 case IrInstructionIdBitOffsetOf:
57725772 case IrInstructionIdTypeInfo:
5773 case IrInstructionIdType:
57735774 case IrInstructionIdHasField:
57745775 case IrInstructionIdTypeId:
57755776 case IrInstructionIdSetEvalBranchQuota:
......@@ -7597,6 +7598,7 @@ static void define_builtin_fns(CodeGen *g) {
75977598 create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2);
75987599 create_builtin_fn(g, BuiltinFnIdField, "field", 2);
75997600 create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1);
7601 create_builtin_fn(g, BuiltinFnIdType, "Type", 1);
76007602 create_builtin_fn(g, BuiltinFnIdHasField, "hasField", 2);
76017603 create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf
76027604 create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4);
......@@ -8159,20 +8161,25 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
81598161 " };\n"
81608162 " };\n"
81618163 "};\n\n");
8162 assert(ContainerLayoutAuto == 0);
8163 assert(ContainerLayoutExtern == 1);
8164 assert(ContainerLayoutPacked == 2);
8165
8166 assert(CallingConventionUnspecified == 0);
8167 assert(CallingConventionC == 1);
8168 assert(CallingConventionCold == 2);
8169 assert(CallingConventionNaked == 3);
8170 assert(CallingConventionStdcall == 4);
8171 assert(CallingConventionAsync == 5);
8172
8173 assert(FnInlineAuto == 0);
8174 assert(FnInlineAlways == 1);
8175 assert(FnInlineNever == 2);
8164 static_assert(ContainerLayoutAuto == 0, "");
8165 static_assert(ContainerLayoutExtern == 1, "");
8166 static_assert(ContainerLayoutPacked == 2, "");
8167
8168 static_assert(CallingConventionUnspecified == 0, "");
8169 static_assert(CallingConventionC == 1, "");
8170 static_assert(CallingConventionCold == 2, "");
8171 static_assert(CallingConventionNaked == 3, "");
8172 static_assert(CallingConventionStdcall == 4, "");
8173 static_assert(CallingConventionAsync == 5, "");
8174
8175 static_assert(FnInlineAuto == 0, "");
8176 static_assert(FnInlineAlways == 1, "");
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, "");
81768183 }
81778184 {
81788185 buf_appendf(contents,
src/ir.cpp+181-6
......@@ -912,6 +912,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) {
912912 return IrInstructionIdTypeInfo;
913913}
914914
915static constexpr IrInstructionId ir_instruction_id(IrInstructionType *) {
916 return IrInstructionIdType;
917}
918
915919static constexpr IrInstructionId ir_instruction_id(IrInstructionHasField *) {
916920 return IrInstructionIdHasField;
917921}
......@@ -2907,6 +2911,15 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
29072911 return &instruction->base;
29082912}
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
29102923static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
29112924 IrInstruction *type_value)
29122925{
......@@ -5046,6 +5059,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
50465059 IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);
50475060 return ir_lval_wrap(irb, scope, type_info, lval, result_loc);
50485061 }
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 }
50495072 case BuiltinFnIdBreakpoint:
50505073 return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc);
50515074 case BuiltinFnIdReturnAddress:
......@@ -20092,14 +20115,27 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
2009220115 return ErrorNone;
2009320116}
2009420117
20095static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {
20118static BuiltinPtrSize ptr_len_to_size_enum_index(PtrLen ptr_len) {
2009620119 switch (ptr_len) {
2009720120 case PtrLenSingle:
20098 return 0;
20121 return BuiltinPtrSizeOne;
2009920122 case PtrLenUnknown:
20100 return 1;
20123 return BuiltinPtrSizeMany;
2010120124 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;
2010320139 }
2010420140 zig_unreachable();
2010520141}
......@@ -20107,10 +20143,10 @@ static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {
2010720143static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
2010820144 Error err;
2010920145 ZigType *attrs_type;
20110 uint32_t size_enum_index;
20146 BuiltinPtrSize size_enum_index;
2011120147 if (is_slice(ptr_type_entry)) {
2011220148 attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry;
20113 size_enum_index = 2;
20149 size_enum_index = BuiltinPtrSizeSlice;
2011420150 } else if (ptr_type_entry->id == ZigTypeIdPointer) {
2011520151 attrs_type = ptr_type_entry;
2011620152 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,
2078920825 return result;
2079020826}
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
2079220964static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
2079320965 IrInstructionTypeId *instruction)
2079420966{
......@@ -25295,6 +25467,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2529525467 return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction);
2529625468 case IrInstructionIdTypeInfo:
2529725469 return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction);
25470 case IrInstructionIdType:
25471 return ir_analyze_instruction_type(ira, (IrInstructionType *)instruction);
2529825472 case IrInstructionIdHasField:
2529925473 return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction);
2530025474 case IrInstructionIdTypeId:
......@@ -25598,6 +25772,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2559825772 case IrInstructionIdByteOffsetOf:
2559925773 case IrInstructionIdBitOffsetOf:
2560025774 case IrInstructionIdTypeInfo:
25775 case IrInstructionIdType:
2560125776 case IrInstructionIdHasField:
2560225777 case IrInstructionIdTypeId:
2560325778 case IrInstructionIdAlignCast:
src/ir_print.cpp+11
......@@ -280,6 +280,8 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {
280280 return "BitOffsetOf";
281281 case IrInstructionIdTypeInfo:
282282 return "TypeInfo";
283 case IrInstructionIdType:
284 return "Type";
283285 case IrInstructionIdHasField:
284286 return "HasField";
285287 case IrInstructionIdTypeId:
......@@ -1627,6 +1629,12 @@ static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction)
16271629 fprintf(irp->f, ")");
16281630}
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
16301638static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction) {
16311639 fprintf(irp->f, "@hasField(");
16321640 ir_print_other_instruction(irp, instruction->container_type);
......@@ -2258,6 +2266,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
22582266 case IrInstructionIdTypeInfo:
22592267 ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction);
22602268 break;
2269 case IrInstructionIdType:
2270 ir_print_type(irp, (IrInstructionType *)instruction);
2271 break;
22612272 case IrInstructionIdHasField:
22622273 ir_print_has_field(irp, (IrInstructionHasField *)instruction);
22632274 break;
test/compile_errors.zig+52
......@@ -2,6 +2,58 @@ const tests = @import("tests.zig");
22const builtin = @import("builtin");
33
44pub 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
557 cases.add(
658 "wrong type for result ptr to @asyncCall",
759 \\export fn entry() void {
test/stage1/behavior.zig+1
......@@ -93,6 +93,7 @@ comptime {
9393 _ = @import("behavior/this.zig");
9494 _ = @import("behavior/truncate.zig");
9595 _ = @import("behavior/try.zig");
96 _ = @import("behavior/type.zig");
9697 _ = @import("behavior/type_info.zig");
9798 _ = @import("behavior/typename.zig");
9899 _ = @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}