| author | |
| committer | |
| log | b728cb6d4e882592129eef2e37f8fcd8fda78822 |
| tree | 9929bf826b52e9c29dfaa8c8eee930504d788a3f |
| parent | 77a5f888be664f9ef09e2c93f52338448e992e00 |
7 files changed, 364 insertions(+), 0 deletions(-)
src/all_types.hpp+8| ... | @@ -1534,6 +1534,7 @@ enum BuiltinFnId { | ... | @@ -1534,6 +1534,7 @@ enum BuiltinFnId { |
| 1534 | BuiltinFnIdMemberName, | 1534 | BuiltinFnIdMemberName, |
| 1535 | BuiltinFnIdField, | 1535 | BuiltinFnIdField, |
| 1536 | BuiltinFnIdTypeInfo, | 1536 | BuiltinFnIdTypeInfo, |
| 1537 | BuiltinFnIdType, | ||
| 1537 | BuiltinFnIdHasField, | 1538 | BuiltinFnIdHasField, |
| 1538 | BuiltinFnIdTypeof, | 1539 | BuiltinFnIdTypeof, |
| 1539 | BuiltinFnIdAddWithOverflow, | 1540 | BuiltinFnIdAddWithOverflow, |
| ... | @@ -2436,6 +2437,7 @@ enum IrInstructionId { | ... | @@ -2436,6 +2437,7 @@ enum IrInstructionId { |
| 2436 | IrInstructionIdByteOffsetOf, | 2437 | IrInstructionIdByteOffsetOf, |
| 2437 | IrInstructionIdBitOffsetOf, | 2438 | IrInstructionIdBitOffsetOf, |
| 2438 | IrInstructionIdTypeInfo, | 2439 | IrInstructionIdTypeInfo, |
| 2440 | IrInstructionIdType, | ||
| 2439 | IrInstructionIdHasField, | 2441 | IrInstructionIdHasField, |
| 2440 | IrInstructionIdTypeId, | 2442 | IrInstructionIdTypeId, |
| 2441 | IrInstructionIdSetEvalBranchQuota, | 2443 | IrInstructionIdSetEvalBranchQuota, |
| ... | @@ -3472,6 +3474,12 @@ struct IrInstructionTypeInfo { | ... | @@ -3472,6 +3474,12 @@ struct IrInstructionTypeInfo { |
| 3472 | IrInstruction *type_value; | 3474 | IrInstruction *type_value; |
| 3473 | }; | 3475 | }; |
| 3474 | 3476 | ||
| 3477 | struct IrInstructionType { | ||
| 3478 | IrInstruction base; | ||
| 3479 | |||
| 3480 | IrInstruction *type_info; | ||
| 3481 | }; | ||
| 3482 | |||
| 3475 | struct IrInstructionHasField { | 3483 | struct IrInstructionHasField { |
| 3476 | IrInstruction base; | 3484 | IrInstruction base; |
| 3477 | 3485 |
src/codegen.cpp+2| ... | @@ -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 TypeOf | 7603 | 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); |
src/ir.cpp+179| ... | @@ -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 | } |
| 914 | 914 | ||
| 915 | static constexpr IrInstructionId ir_instruction_id(IrInstructionType *) { | ||
| 916 | return IrInstructionIdType; | ||
| 917 | } | ||
| 918 | |||
| 915 | static constexpr IrInstructionId ir_instruction_id(IrInstructionHasField *) { | 919 | static 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 | } |
| 2909 | 2913 | ||
| 2914 | static 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 | |||
| 2910 | static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2923 | static 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: |
| ... | @@ -20104,6 +20127,18 @@ static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) { | ... | @@ -20104,6 +20127,18 @@ static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) { |
| 20104 | zig_unreachable(); | 20127 | zig_unreachable(); |
| 20105 | } | 20128 | } |
| 20106 | 20129 | ||
| 20130 | static PtrLen size_enum_index_to_ptr_len(uint32_t size_enum_index) { | ||
| 20131 | switch (size_enum_index) { | ||
| 20132 | case 0: | ||
| 20133 | return PtrLenSingle; | ||
| 20134 | case 1: | ||
| 20135 | return PtrLenUnknown; | ||
| 20136 | case 3: | ||
| 20137 | return PtrLenC; | ||
| 20138 | } | ||
| 20139 | zig_unreachable(); | ||
| 20140 | } | ||
| 20141 | |||
| 20107 | static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) { | 20142 | static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) { |
| 20108 | Error err; | 20143 | Error err; |
| 20109 | ZigType *attrs_type; | 20144 | ZigType *attrs_type; |
| ... | @@ -20789,6 +20824,147 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, | ... | @@ -20789,6 +20824,147 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, |
| 20789 | return result; | 20824 | return result; |
| 20790 | } | 20825 | } |
| 20791 | 20826 | ||
| 20827 | static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) | ||
| 20828 | { | ||
| 20829 | ensure_field_index(struct_value->type, name, field_index); | ||
| 20830 | assert(struct_value->data.x_struct.fields[field_index].special == ConstValSpecialStatic); | ||
| 20831 | return &struct_value->data.x_struct.fields[field_index]; | ||
| 20832 | } | ||
| 20833 | |||
| 20834 | static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) | ||
| 20835 | { | ||
| 20836 | ConstExprValue *value = get_const_field(ira, struct_value, name, field_index); | ||
| 20837 | assert(value->type == ira->codegen->builtin_types.entry_bool); | ||
| 20838 | return value->data.x_bool; | ||
| 20839 | } | ||
| 20840 | |||
| 20841 | static BigInt *get_const_field_lit_int(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) | ||
| 20842 | { | ||
| 20843 | ConstExprValue *value = get_const_field(ira, struct_value, name, field_index); | ||
| 20844 | assert(value->type == ira->codegen->builtin_types.entry_num_lit_int); | ||
| 20845 | return &value->data.x_bigint; | ||
| 20846 | } | ||
| 20847 | |||
| 20848 | static ZigType *get_const_field_meta_type(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) | ||
| 20849 | { | ||
| 20850 | ConstExprValue *value = get_const_field(ira, struct_value, name, field_index); | ||
| 20851 | assert(value->type == ira->codegen->builtin_types.entry_type); | ||
| 20852 | return value->data.x_type; | ||
| 20853 | } | ||
| 20854 | |||
| 20855 | static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) { | ||
| 20856 | switch (tagTypeId) { | ||
| 20857 | case ZigTypeIdInvalid: | ||
| 20858 | zig_unreachable(); | ||
| 20859 | case ZigTypeIdMetaType: | ||
| 20860 | return ira->codegen->builtin_types.entry_type; | ||
| 20861 | case ZigTypeIdVoid: | ||
| 20862 | return ira->codegen->builtin_types.entry_void; | ||
| 20863 | case ZigTypeIdBool: | ||
| 20864 | return ira->codegen->builtin_types.entry_bool; | ||
| 20865 | case ZigTypeIdUnreachable: | ||
| 20866 | return ira->codegen->builtin_types.entry_unreachable; | ||
| 20867 | case ZigTypeIdInt: | ||
| 20868 | assert(payload->special == ConstValSpecialStatic); | ||
| 20869 | assert(payload->type == ir_type_info_get_type(ira, "Int", nullptr)); | ||
| 20870 | return get_int_type(ira->codegen, | ||
| 20871 | get_const_field_bool(ira, payload, "is_signed", 0), | ||
| 20872 | bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 1))); | ||
| 20873 | case ZigTypeIdFloat: | ||
| 20874 | { | ||
| 20875 | assert(payload->special == ConstValSpecialStatic); | ||
| 20876 | assert(payload->type == ir_type_info_get_type(ira, "Float", nullptr)); | ||
| 20877 | uint32_t bits = bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 0)); | ||
| 20878 | switch (bits) { | ||
| 20879 | case 16: return ira->codegen->builtin_types.entry_f16; | ||
| 20880 | case 32: return ira->codegen->builtin_types.entry_f32; | ||
| 20881 | case 64: return ira->codegen->builtin_types.entry_f64; | ||
| 20882 | case 128: return ira->codegen->builtin_types.entry_f128; | ||
| 20883 | } | ||
| 20884 | ir_add_error(ira, instruction, | ||
| 20885 | buf_sprintf("%d-bit float unsupported", bits)); | ||
| 20886 | return nullptr; | ||
| 20887 | } | ||
| 20888 | case ZigTypeIdPointer: | ||
| 20889 | { | ||
| 20890 | ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr); | ||
| 20891 | assert(payload->special == ConstValSpecialStatic); | ||
| 20892 | assert(payload->type == type_info_pointer_type); | ||
| 20893 | ConstExprValue *size_value = get_const_field(ira, payload, "size", 0); | ||
| 20894 | assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type)); | ||
| 20895 | uint32_t size_enum_index = bigint_as_u32(&size_value->data.x_enum_tag); | ||
| 20896 | PtrLen ptr_len; | ||
| 20897 | if (size_enum_index == 2) { | ||
| 20898 | ptr_len = PtrLenUnknown; // TODO: is this right? | ||
| 20899 | } else { | ||
| 20900 | ptr_len = size_enum_index_to_ptr_len(size_enum_index); | ||
| 20901 | } | ||
| 20902 | ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, | ||
| 20903 | get_const_field_meta_type(ira, payload, "child", 4), | ||
| 20904 | get_const_field_bool(ira, payload, "is_const", 1), | ||
| 20905 | get_const_field_bool(ira, payload, "is_volatile", 2), | ||
| 20906 | ptr_len, | ||
| 20907 | bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)), | ||
| 20908 | 0, // bit_offset_in_host??? | ||
| 20909 | 0, // host_int_bytes??? | ||
| 20910 | get_const_field_bool(ira, payload, "is_allowzero", 5) | ||
| 20911 | ); | ||
| 20912 | if (size_enum_index != 2) | ||
| 20913 | return ptr_type; | ||
| 20914 | return get_slice_type(ira->codegen, ptr_type); | ||
| 20915 | } | ||
| 20916 | case ZigTypeIdComptimeFloat: | ||
| 20917 | return ira->codegen->builtin_types.entry_num_lit_float; | ||
| 20918 | case ZigTypeIdComptimeInt: | ||
| 20919 | return ira->codegen->builtin_types.entry_num_lit_int; | ||
| 20920 | case ZigTypeIdUndefined: | ||
| 20921 | return ira->codegen->builtin_types.entry_undef; | ||
| 20922 | case ZigTypeIdNull: | ||
| 20923 | return ira->codegen->builtin_types.entry_null; | ||
| 20924 | case ZigTypeIdArray: | ||
| 20925 | case ZigTypeIdOptional: | ||
| 20926 | case ZigTypeIdErrorUnion: | ||
| 20927 | case ZigTypeIdErrorSet: | ||
| 20928 | case ZigTypeIdEnum: | ||
| 20929 | case ZigTypeIdOpaque: | ||
| 20930 | case ZigTypeIdFnFrame: | ||
| 20931 | case ZigTypeIdAnyFrame: | ||
| 20932 | case ZigTypeIdVector: | ||
| 20933 | case ZigTypeIdEnumLiteral: | ||
| 20934 | ir_add_error(ira, instruction, buf_sprintf( | ||
| 20935 | "TODO implement @Type forr 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907\n", type_id_name(tagTypeId))); | ||
| 20936 | return nullptr; | ||
| 20937 | case ZigTypeIdUnion: | ||
| 20938 | case ZigTypeIdFn: | ||
| 20939 | case ZigTypeIdBoundFn: | ||
| 20940 | case ZigTypeIdArgTuple: | ||
| 20941 | case ZigTypeIdStruct: | ||
| 20942 | ir_add_error(ira, instruction, buf_sprintf( | ||
| 20943 | "@Type not availble for 'TypeInfo.%s'\n", type_id_name(tagTypeId))); | ||
| 20944 | return nullptr; | ||
| 20945 | } | ||
| 20946 | zig_unreachable(); | ||
| 20947 | } | ||
| 20948 | |||
| 20949 | static IrInstruction *ir_analyze_instruction_type(IrAnalyze *ira, IrInstructionType *instruction) { | ||
| 20950 | IrInstruction *type_info_ir = instruction->type_info->child; | ||
| 20951 | if (type_is_invalid(type_info_ir->value.type)) | ||
| 20952 | return ira->codegen->invalid_instruction; | ||
| 20953 | |||
| 20954 | IrInstruction *casted_ir = ir_implicit_cast(ira, type_info_ir, ir_type_info_get_type(ira, nullptr, nullptr)); | ||
| 20955 | if (type_is_invalid(casted_ir->value.type)) | ||
| 20956 | return ira->codegen->invalid_instruction; | ||
| 20957 | |||
| 20958 | ConstExprValue *type_info_value = ir_resolve_const(ira, casted_ir, UndefBad); | ||
| 20959 | if (!type_info_value) | ||
| 20960 | return ira->codegen->invalid_instruction; | ||
| 20961 | ZigTypeId typeId = type_id_at_index(bigint_as_usize(&type_info_value->data.x_union.tag)); | ||
| 20962 | ZigType *type = type_info_to_type(ira, type_info_ir, typeId, type_info_value->data.x_union.payload); | ||
| 20963 | if (!type) | ||
| 20964 | return ira->codegen->invalid_instruction; | ||
| 20965 | return ir_const_type(ira, &instruction->base, type); | ||
| 20966 | } | ||
| 20967 | |||
| 20792 | static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira, | 20968 | static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira, |
| 20793 | IrInstructionTypeId *instruction) | 20969 | IrInstructionTypeId *instruction) |
| 20794 | { | 20970 | { |
| ... | @@ -25295,6 +25471,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction | ... | @@ -25295,6 +25471,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 25295 | return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction); | 25471 | return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction); |
| 25296 | case IrInstructionIdTypeInfo: | 25472 | case IrInstructionIdTypeInfo: |
| 25297 | return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction); | 25473 | return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction); |
| 25474 | case IrInstructionIdType: | ||
| 25475 | return ir_analyze_instruction_type(ira, (IrInstructionType *)instruction); | ||
| 25298 | case IrInstructionIdHasField: | 25476 | case IrInstructionIdHasField: |
| 25299 | return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction); | 25477 | return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction); |
| 25300 | case IrInstructionIdTypeId: | 25478 | case IrInstructionIdTypeId: |
| ... | @@ -25598,6 +25776,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -25598,6 +25776,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 25598 | case IrInstructionIdByteOffsetOf: | 25776 | case IrInstructionIdByteOffsetOf: |
| 25599 | case IrInstructionIdBitOffsetOf: | 25777 | case IrInstructionIdBitOffsetOf: |
| 25600 | case IrInstructionIdTypeInfo: | 25778 | case IrInstructionIdTypeInfo: |
| 25779 | case IrInstructionIdType: | ||
| 25601 | case IrInstructionIdHasField: | 25780 | case IrInstructionIdHasField: |
| 25602 | case IrInstructionIdTypeId: | 25781 | case IrInstructionIdTypeId: |
| 25603 | case IrInstructionIdAlignCast: | 25782 | 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 | } |
| 1629 | 1631 | ||
| 1632 | static 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 | |||
| 1630 | static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction) { | 1638 | static 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"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | |||
| 6 | cases.add( | ||
| 7 | "wrong type for @Type", | ||
| 8 | \\export fn entry() void { | ||
| 9 | \\ _ = @Type(0); | ||
| 10 | \\} | ||
| 11 | , | ||
| 12 | "tmp.zig:2:15: error: expected type 'builtin.TypeInfo', found 'comptime_int'", | ||
| 13 | ); | ||
| 14 | |||
| 15 | cases.add( | ||
| 16 | "@Type with non-constant expression", | ||
| 17 | \\const builtin = @import("builtin"); | ||
| 18 | \\var globalTypeInfo : builtin.TypeInfo = undefined; | ||
| 19 | \\export fn entry() void { | ||
| 20 | \\ _ = @Type(globalTypeInfo); | ||
| 21 | \\} | ||
| 22 | , | ||
| 23 | "tmp.zig:4:15: error: unable to evaluate constant expression", | ||
| 24 | ); | ||
| 25 | |||
| 26 | cases.add( | ||
| 27 | "@Type with TypeInfo.Int", | ||
| 28 | \\const builtin = @import("builtin"); | ||
| 29 | \\export fn entry() void { | ||
| 30 | \\ _ = @Type(builtin.TypeInfo.Int { | ||
| 31 | \\ .is_signed = true, | ||
| 32 | \\ .bits = 8, | ||
| 33 | \\ }); | ||
| 34 | \\} | ||
| 35 | , | ||
| 36 | "tmp.zig:3:36: error: expected type 'builtin.TypeInfo', found 'builtin.Int'", | ||
| 37 | ); | ||
| 38 | |||
| 39 | cases.add( | ||
| 40 | "Struct unavailable for @Type", | ||
| 41 | \\export fn entry() void { | ||
| 42 | \\ _ = @Type(@typeInfo(struct { })); | ||
| 43 | \\} | ||
| 44 | , | ||
| 45 | "tmp.zig:2:15: error: @Type not availble for 'TypeInfo.Struct'", | ||
| 46 | ); | ||
| 47 | |||
| 48 | cases.add( | ||
| 49 | "array not implemented for @Type", | ||
| 50 | \\export fn entry() void { | ||
| 51 | \\ _ = @Type(@typeInfo(enum{x})); | ||
| 52 | \\} | ||
| 53 | , | ||
| 54 | "tmp.zig:2:15: error: TODO implement @Type forr 'TypeInfo.Enum': see https://github.com/ziglang/zig/issues/2907", | ||
| 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+111| ... | @@ -0,0 +1,111 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const TypeInfo = builtin.TypeInfo; | ||
| 3 | |||
| 4 | const std = @import("std"); | ||
| 5 | const testing = std.testing; | ||
| 6 | |||
| 7 | fn testTypes(comptime types: []const type) void { | ||
| 8 | inline for (types) |testType| { | ||
| 9 | testing.expect(testType == @Type(@typeInfo(testType))); | ||
| 10 | } | ||
| 11 | } | ||
| 12 | |||
| 13 | test "Type.MetaType" { | ||
| 14 | testing.expect(type == @Type(TypeInfo { .Type = undefined })); | ||
| 15 | testTypes([_]type {type}); | ||
| 16 | } | ||
| 17 | |||
| 18 | test "Type.Void" { | ||
| 19 | testing.expect(void == @Type(TypeInfo { .Void = undefined })); | ||
| 20 | testTypes([_]type {void}); | ||
| 21 | } | ||
| 22 | |||
| 23 | test "Type.Bool" { | ||
| 24 | testing.expect(bool == @Type(TypeInfo { .Bool = undefined })); | ||
| 25 | testTypes([_]type {bool}); | ||
| 26 | } | ||
| 27 | |||
| 28 | test "Type.NoReturn" { | ||
| 29 | testing.expect(noreturn == @Type(TypeInfo { .NoReturn = undefined })); | ||
| 30 | testTypes([_]type {noreturn}); | ||
| 31 | } | ||
| 32 | |||
| 33 | test "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 | // TODO: should this work? | ||
| 42 | //testing.expect(u1 == @Type(TypeInfo.Int { .is_signed = false, .bits = 1 } )); | ||
| 43 | } | ||
| 44 | |||
| 45 | test "Type.Float" { | ||
| 46 | testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 16 } })); | ||
| 47 | testing.expect(f32 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 32 } })); | ||
| 48 | testing.expect(f64 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 64 } })); | ||
| 49 | testing.expect(f128 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 128 } })); | ||
| 50 | testTypes([_]type {f16, f32, f64, f128}); | ||
| 51 | // error: 17-bit float unsupported | ||
| 52 | //testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 17 } })); | ||
| 53 | } | ||
| 54 | |||
| 55 | test "Type.Pointer" { | ||
| 56 | testTypes([_]type { | ||
| 57 | // One Value Pointer Types | ||
| 58 | *u8, *const u8, | ||
| 59 | *volatile u8, *const volatile u8, | ||
| 60 | *align(4) u8, *const align(4) u8, | ||
| 61 | *volatile align(4) u8, *const volatile align(4) u8, | ||
| 62 | *align(8) u8, *const align(8) u8, | ||
| 63 | *volatile align(8) u8, *const volatile align(8) u8, | ||
| 64 | *allowzero u8, *const allowzero u8, | ||
| 65 | *volatile allowzero u8, *const volatile allowzero u8, | ||
| 66 | *align(4) allowzero u8, *const align(4) allowzero u8, | ||
| 67 | *volatile align(4) allowzero u8, *const volatile align(4) allowzero u8, | ||
| 68 | // Many Values Pointer Types | ||
| 69 | [*]u8, [*]const u8, | ||
| 70 | [*]volatile u8, [*]const volatile u8, | ||
| 71 | [*]align(4) u8, [*]const align(4) u8, | ||
| 72 | [*]volatile align(4) u8, [*]const volatile align(4) u8, | ||
| 73 | [*]align(8) u8, [*]const align(8) u8, | ||
| 74 | [*]volatile align(8) u8, [*]const volatile align(8) u8, | ||
| 75 | [*]allowzero u8, [*]const allowzero u8, | ||
| 76 | [*]volatile allowzero u8, [*]const volatile allowzero u8, | ||
| 77 | [*]align(4) allowzero u8, [*]const align(4) allowzero u8, | ||
| 78 | [*]volatile align(4) allowzero u8, [*]const volatile align(4) allowzero u8, | ||
| 79 | // Slice Types | ||
| 80 | []u8, []const u8, | ||
| 81 | []volatile u8, []const volatile u8, | ||
| 82 | []align(4) u8, []const align(4) u8, | ||
| 83 | []volatile align(4) u8, []const volatile align(4) u8, | ||
| 84 | []align(8) u8, []const align(8) u8, | ||
| 85 | []volatile align(8) u8, []const volatile align(8) u8, | ||
| 86 | []allowzero u8, []const allowzero u8, | ||
| 87 | []volatile allowzero u8, []const volatile allowzero u8, | ||
| 88 | []align(4) allowzero u8, []const align(4) allowzero u8, | ||
| 89 | []volatile align(4) allowzero u8, []const volatile align(4) allowzero u8, | ||
| 90 | // C Pointer Types | ||
| 91 | [*c]u8, [*c]const u8, | ||
| 92 | [*c]volatile u8, [*c]const volatile u8, | ||
| 93 | [*c]align(4) u8, [*c]const align(4) u8, | ||
| 94 | [*c]volatile align(4) u8, [*c]const volatile align(4) u8, | ||
| 95 | [*c]align(8) u8, [*c]const align(8) u8, | ||
| 96 | [*c]volatile align(8) u8, [*c]const volatile align(8) u8, | ||
| 97 | }); | ||
| 98 | } | ||
| 99 | |||
| 100 | test "Type.ComptimeFloat" { | ||
| 101 | testTypes([_]type {comptime_float}); | ||
| 102 | } | ||
| 103 | test "Type.ComptimeInt" { | ||
| 104 | testTypes([_]type {comptime_int}); | ||
| 105 | } | ||
| 106 | test "Type.Undefined" { | ||
| 107 | testTypes([_]type {@typeOf(undefined)}); | ||
| 108 | } | ||
| 109 | test "Type.Null" { | ||
| 110 | testTypes([_]type {@typeOf(null)}); | ||
| 111 | } | ||