| author | |
| committer | |
| log | 095591f0b0f0d09bb1589fc404c2e7fdeac4bee4 |
| tree | d98a149b0a2472bdaef45b15bdcd42e4d6a42566 |
| parent | 7611ed3484ad810fe10d3c303a04d66bfa0bd6fd |
closes #29910 files changed, 192 insertions(+), 142 deletions(-)
doc/langref.md+4| ... | @@ -625,3 +625,7 @@ Converts a pointer of one type to a pointer of another type. | ... | @@ -625,3 +625,7 @@ Converts a pointer of one type to a pointer of another type. |
| 625 | ### @intToPtr(comptime DestType: type, int: usize) -> DestType | 625 | ### @intToPtr(comptime DestType: type, int: usize) -> DestType |
| 626 | 626 | ||
| 627 | Converts an integer to a pointer. To convert the other way, use `usize(ptr)`. | 627 | Converts an integer to a pointer. To convert the other way, use `usize(ptr)`. |
| 628 | |||
| 629 | ### @enumTagName(value: var) -> []const u8 | ||
| 630 | |||
| 631 | Converts an enum tag name to a slice of bytes. Example: |
src/all_types.hpp+12| ... | @@ -966,6 +966,8 @@ struct TypeTableEntryEnum { | ... | @@ -966,6 +966,8 @@ struct TypeTableEntryEnum { |
| 966 | struct TypeTableEntryEnumTag { | 966 | struct TypeTableEntryEnumTag { |
| 967 | TypeTableEntry *enum_type; | 967 | TypeTableEntry *enum_type; |
| 968 | TypeTableEntry *int_type; | 968 | TypeTableEntry *int_type; |
| 969 | bool generate_name_table; | ||
| 970 | LLVMValueRef name_table; | ||
| 969 | }; | 971 | }; |
| 970 | 972 | ||
| 971 | struct TypeTableEntryUnion { | 973 | struct TypeTableEntryUnion { |
| ... | @@ -1200,6 +1202,7 @@ enum BuiltinFnId { | ... | @@ -1200,6 +1202,7 @@ enum BuiltinFnId { |
| 1200 | BuiltinFnIdPanic, | 1202 | BuiltinFnIdPanic, |
| 1201 | BuiltinFnIdPtrCast, | 1203 | BuiltinFnIdPtrCast, |
| 1202 | BuiltinFnIdIntToPtr, | 1204 | BuiltinFnIdIntToPtr, |
| 1205 | BuiltinFnIdEnumTagName, | ||
| 1203 | }; | 1206 | }; |
| 1204 | 1207 | ||
| 1205 | struct BuiltinFnEntry { | 1208 | struct BuiltinFnEntry { |
| ... | @@ -1464,6 +1467,8 @@ struct CodeGen { | ... | @@ -1464,6 +1467,8 @@ struct CodeGen { |
| 1464 | 1467 | ||
| 1465 | Buf global_asm; | 1468 | Buf global_asm; |
| 1466 | ZigList<Buf *> link_objects; | 1469 | ZigList<Buf *> link_objects; |
| 1470 | |||
| 1471 | ZigList<TypeTableEntry *> name_table_enums; | ||
| 1467 | }; | 1472 | }; |
| 1468 | 1473 | ||
| 1469 | enum VarLinkage { | 1474 | enum VarLinkage { |
| ... | @@ -1742,6 +1747,7 @@ enum IrInstructionId { | ... | @@ -1742,6 +1747,7 @@ enum IrInstructionId { |
| 1742 | IrInstructionIdSetGlobalLinkage, | 1747 | IrInstructionIdSetGlobalLinkage, |
| 1743 | IrInstructionIdDeclRef, | 1748 | IrInstructionIdDeclRef, |
| 1744 | IrInstructionIdPanic, | 1749 | IrInstructionIdPanic, |
| 1750 | IrInstructionIdEnumTagName, | ||
| 1745 | }; | 1751 | }; |
| 1746 | 1752 | ||
| 1747 | struct IrInstruction { | 1753 | struct IrInstruction { |
| ... | @@ -2481,6 +2487,12 @@ struct IrInstructionPanic { | ... | @@ -2481,6 +2487,12 @@ struct IrInstructionPanic { |
| 2481 | IrInstruction *msg; | 2487 | IrInstruction *msg; |
| 2482 | }; | 2488 | }; |
| 2483 | 2489 | ||
| 2490 | struct IrInstructionEnumTagName { | ||
| 2491 | IrInstruction base; | ||
| 2492 | |||
| 2493 | IrInstruction *target; | ||
| 2494 | }; | ||
| 2495 | |||
| 2484 | static const size_t slice_ptr_index = 0; | 2496 | static const size_t slice_ptr_index = 0; |
| 2485 | static const size_t slice_len_index = 1; | 2497 | static const size_t slice_len_index = 1; |
| 2486 | 2498 |
src/analyze.cpp+1-1| ... | @@ -1181,7 +1181,7 @@ bool type_is_invalid(TypeTableEntry *type_entry) { | ... | @@ -1181,7 +1181,7 @@ bool type_is_invalid(TypeTableEntry *type_entry) { |
| 1181 | } | 1181 | } |
| 1182 | 1182 | ||
| 1183 | 1183 | ||
| 1184 | static TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type) { | 1184 | TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type) { |
| 1185 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnumTag); | 1185 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnumTag); |
| 1186 | 1186 | ||
| 1187 | buf_resize(&entry->name, 0); | 1187 | buf_resize(&entry->name, 0); |
src/analyze.hpp+1| ... | @@ -149,5 +149,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val); | ... | @@ -149,5 +149,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val); |
| 149 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits); | 149 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits); |
| 150 | ConstParent *get_const_val_parent(ConstExprValue *value); | 150 | ConstParent *get_const_val_parent(ConstExprValue *value); |
| 151 | FnTableEntry *get_extern_panic_fn(CodeGen *g); | 151 | FnTableEntry *get_extern_panic_fn(CodeGen *g); |
| 152 | TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type); | ||
| 152 | 153 | ||
| 153 | #endif | 154 | #endif |
src/codegen.cpp+69-1| ... | @@ -2134,6 +2134,29 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -2134,6 +2134,29 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI |
| 2134 | return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, ""); | 2134 | return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, ""); |
| 2135 | } | 2135 | } |
| 2136 | 2136 | ||
| 2137 | static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable, | ||
| 2138 | IrInstructionEnumTagName *instruction) | ||
| 2139 | { | ||
| 2140 | TypeTableEntry *enum_tag_type = instruction->target->value.type; | ||
| 2141 | assert(enum_tag_type->data.enum_tag.generate_name_table); | ||
| 2142 | |||
| 2143 | LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); | ||
| 2144 | if (ir_want_debug_safety(g, &instruction->base)) { | ||
| 2145 | TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type; | ||
| 2146 | size_t field_count = enum_type->data.enumeration.src_field_count; | ||
| 2147 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(enum_tag_value)); | ||
| 2148 | LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(enum_tag_value), field_count, false); | ||
| 2149 | add_bounds_check(g, enum_tag_value, LLVMIntUGE, zero, LLVMIntULT, end_val); | ||
| 2150 | } | ||
| 2151 | |||
| 2152 | LLVMValueRef indices[] = { | ||
| 2153 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), | ||
| 2154 | enum_tag_value, | ||
| 2155 | }; | ||
| 2156 | return LLVMBuildInBoundsGEP(g->builder, enum_tag_type->data.enum_tag.name_table, indices, 2, ""); | ||
| 2157 | } | ||
| 2158 | |||
| 2159 | |||
| 2137 | static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { | 2160 | static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { |
| 2138 | switch (atomic_order) { | 2161 | switch (atomic_order) { |
| 2139 | case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered; | 2162 | case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered; |
| ... | @@ -2830,6 +2853,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -2830,6 +2853,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2830 | return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction); | 2853 | return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction); |
| 2831 | case IrInstructionIdPanic: | 2854 | case IrInstructionIdPanic: |
| 2832 | return ir_render_panic(g, executable, (IrInstructionPanic *)instruction); | 2855 | return ir_render_panic(g, executable, (IrInstructionPanic *)instruction); |
| 2856 | case IrInstructionIdEnumTagName: | ||
| 2857 | return ir_render_enum_tag_name(g, executable, (IrInstructionEnumTagName *)instruction); | ||
| 2833 | } | 2858 | } |
| 2834 | zig_unreachable(); | 2859 | zig_unreachable(); |
| 2835 | } | 2860 | } |
| ... | @@ -3390,6 +3415,46 @@ static void generate_error_name_table(CodeGen *g) { | ... | @@ -3390,6 +3415,46 @@ static void generate_error_name_table(CodeGen *g) { |
| 3390 | LLVMSetUnnamedAddr(g->err_name_table, true); | 3415 | LLVMSetUnnamedAddr(g->err_name_table, true); |
| 3391 | } | 3416 | } |
| 3392 | 3417 | ||
| 3418 | static void generate_enum_name_tables(CodeGen *g) { | ||
| 3419 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | ||
| 3420 | TypeTableEntry *u8_ptr_type = str_type->data.structure.fields[0].type_entry; | ||
| 3421 | |||
| 3422 | for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) { | ||
| 3423 | TypeTableEntry *enum_tag_type = g->name_table_enums.at(enum_i); | ||
| 3424 | assert(enum_tag_type->id == TypeTableEntryIdEnumTag); | ||
| 3425 | TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type; | ||
| 3426 | |||
| 3427 | size_t field_count = enum_type->data.enumeration.src_field_count; | ||
| 3428 | LLVMValueRef *values = allocate<LLVMValueRef>(field_count); | ||
| 3429 | for (size_t field_i = 0; field_i < field_count; field_i += 1) { | ||
| 3430 | Buf *name = enum_type->data.enumeration.fields[field_i].name; | ||
| 3431 | |||
| 3432 | LLVMValueRef str_init = LLVMConstString(buf_ptr(name), buf_len(name), true); | ||
| 3433 | LLVMValueRef str_global = LLVMAddGlobal(g->module, LLVMTypeOf(str_init), ""); | ||
| 3434 | LLVMSetInitializer(str_global, str_init); | ||
| 3435 | LLVMSetLinkage(str_global, LLVMPrivateLinkage); | ||
| 3436 | LLVMSetGlobalConstant(str_global, true); | ||
| 3437 | LLVMSetUnnamedAddr(str_global, true); | ||
| 3438 | |||
| 3439 | LLVMValueRef fields[] = { | ||
| 3440 | LLVMConstBitCast(str_global, u8_ptr_type->type_ref), | ||
| 3441 | LLVMConstInt(g->builtin_types.entry_usize->type_ref, buf_len(name), false), | ||
| 3442 | }; | ||
| 3443 | values[field_i] = LLVMConstNamedStruct(str_type->type_ref, fields, 2); | ||
| 3444 | } | ||
| 3445 | |||
| 3446 | LLVMValueRef name_table_init = LLVMConstArray(str_type->type_ref, values, field_count); | ||
| 3447 | |||
| 3448 | Buf *table_name = buf_sprintf("%s_name_table", buf_ptr(&enum_type->name)); | ||
| 3449 | LLVMValueRef name_table = LLVMAddGlobal(g->module, LLVMTypeOf(name_table_init), buf_ptr(table_name)); | ||
| 3450 | LLVMSetInitializer(name_table, name_table_init); | ||
| 3451 | LLVMSetLinkage(name_table, LLVMPrivateLinkage); | ||
| 3452 | LLVMSetGlobalConstant(name_table, true); | ||
| 3453 | LLVMSetUnnamedAddr(name_table, true); | ||
| 3454 | enum_tag_type->data.enum_tag.name_table = name_table; | ||
| 3455 | } | ||
| 3456 | } | ||
| 3457 | |||
| 3393 | static void build_all_basic_blocks(CodeGen *g, FnTableEntry *fn) { | 3458 | static void build_all_basic_blocks(CodeGen *g, FnTableEntry *fn) { |
| 3394 | IrExecutable *executable = &fn->analyzed_executable; | 3459 | IrExecutable *executable = &fn->analyzed_executable; |
| 3395 | assert(executable->basic_block_list.length > 0); | 3460 | assert(executable->basic_block_list.length > 0); |
| ... | @@ -3428,6 +3493,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -3428,6 +3493,7 @@ static void do_code_gen(CodeGen *g) { |
| 3428 | 3493 | ||
| 3429 | delete_unused_builtin_fns(g); | 3494 | delete_unused_builtin_fns(g); |
| 3430 | generate_error_name_table(g); | 3495 | generate_error_name_table(g); |
| 3496 | generate_enum_name_tables(g); | ||
| 3431 | 3497 | ||
| 3432 | // Generate module level variables | 3498 | // Generate module level variables |
| 3433 | for (size_t i = 0; i < g->global_vars.length; i += 1) { | 3499 | for (size_t i = 0; i < g->global_vars.length; i += 1) { |
| ... | @@ -3800,7 +3866,8 @@ static const GlobalLinkageValue global_linkage_values[] = { | ... | @@ -3800,7 +3866,8 @@ static const GlobalLinkageValue global_linkage_values[] = { |
| 3800 | static void init_enum_debug_info(CodeGen *g, TypeTableEntry *enum_type) { | 3866 | static void init_enum_debug_info(CodeGen *g, TypeTableEntry *enum_type) { |
| 3801 | uint32_t field_count = enum_type->data.enumeration.src_field_count; | 3867 | uint32_t field_count = enum_type->data.enumeration.src_field_count; |
| 3802 | 3868 | ||
| 3803 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); | 3869 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); |
| 3870 | TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); | ||
| 3804 | enum_type->data.enumeration.tag_type = tag_type_entry; | 3871 | enum_type->data.enumeration.tag_type = tag_type_entry; |
| 3805 | 3872 | ||
| 3806 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); | 3873 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); |
| ... | @@ -4327,6 +4394,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -4327,6 +4394,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 4327 | create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); | 4394 | create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); |
| 4328 | create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrcast", 2); | 4395 | create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrcast", 2); |
| 4329 | create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2); | 4396 | create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2); |
| 4397 | create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1); | ||
| 4330 | } | 4398 | } |
| 4331 | 4399 | ||
| 4332 | static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) { | 4400 | static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) { |
src/ir.cpp+74-4| ... | @@ -541,6 +541,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPanic *) { | ... | @@ -541,6 +541,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPanic *) { |
| 541 | return IrInstructionIdPanic; | 541 | return IrInstructionIdPanic; |
| 542 | } | 542 | } |
| 543 | 543 | ||
| 544 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTagName *) { | ||
| 545 | return IrInstructionIdEnumTagName; | ||
| 546 | } | ||
| 547 | |||
| 544 | template<typename T> | 548 | template<typename T> |
| 545 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 549 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 546 | T *special_instruction = allocate<T>(1); | 550 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2130,6 +2134,17 @@ static IrInstruction *ir_build_panic(IrBuilder *irb, Scope *scope, AstNode *sour | ... | @@ -2130,6 +2134,17 @@ static IrInstruction *ir_build_panic(IrBuilder *irb, Scope *scope, AstNode *sour |
| 2130 | return &instruction->base; | 2134 | return &instruction->base; |
| 2131 | } | 2135 | } |
| 2132 | 2136 | ||
| 2137 | static IrInstruction *ir_build_enum_tag_name(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 2138 | IrInstruction *target) | ||
| 2139 | { | ||
| 2140 | IrInstructionEnumTagName *instruction = ir_build_instruction<IrInstructionEnumTagName>(irb, scope, source_node); | ||
| 2141 | instruction->target = target; | ||
| 2142 | |||
| 2143 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 2144 | |||
| 2145 | return &instruction->base; | ||
| 2146 | } | ||
| 2147 | |||
| 2133 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { | 2148 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { |
| 2134 | return nullptr; | 2149 | return nullptr; |
| 2135 | } | 2150 | } |
| ... | @@ -2787,6 +2802,13 @@ static IrInstruction *ir_instruction_panic_get_dep(IrInstructionPanic *instructi | ... | @@ -2787,6 +2802,13 @@ static IrInstruction *ir_instruction_panic_get_dep(IrInstructionPanic *instructi |
| 2787 | } | 2802 | } |
| 2788 | } | 2803 | } |
| 2789 | 2804 | ||
| 2805 | static IrInstruction *ir_instruction_enumtagname_get_dep(IrInstructionEnumTagName *instruction, size_t index) { | ||
| 2806 | switch (index) { | ||
| 2807 | case 0: return instruction->target; | ||
| 2808 | default: return nullptr; | ||
| 2809 | } | ||
| 2810 | } | ||
| 2811 | |||
| 2790 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { | 2812 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { |
| 2791 | switch (instruction->id) { | 2813 | switch (instruction->id) { |
| 2792 | case IrInstructionIdInvalid: | 2814 | case IrInstructionIdInvalid: |
| ... | @@ -2975,6 +2997,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -2975,6 +2997,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 2975 | return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index); | 2997 | return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index); |
| 2976 | case IrInstructionIdPanic: | 2998 | case IrInstructionIdPanic: |
| 2977 | return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index); | 2999 | return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index); |
| 3000 | case IrInstructionIdEnumTagName: | ||
| 3001 | return ir_instruction_enumtagname_get_dep((IrInstructionEnumTagName *) instruction, index); | ||
| 2978 | } | 3002 | } |
| 2979 | zig_unreachable(); | 3003 | zig_unreachable(); |
| 2980 | } | 3004 | } |
| ... | @@ -4239,6 +4263,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4239,6 +4263,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4239 | 4263 | ||
| 4240 | return ir_build_int_to_ptr(irb, scope, node, arg0_value, arg1_value); | 4264 | return ir_build_int_to_ptr(irb, scope, node, arg0_value, arg1_value); |
| 4241 | } | 4265 | } |
| 4266 | case BuiltinFnIdEnumTagName: | ||
| 4267 | { | ||
| 4268 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4269 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 4270 | if (arg0_value == irb->codegen->invalid_instruction) | ||
| 4271 | return arg0_value; | ||
| 4272 | |||
| 4273 | IrInstruction *actual_tag = ir_build_enum_tag(irb, scope, node, arg0_value); | ||
| 4274 | return ir_build_enum_tag_name(irb, scope, node, actual_tag); | ||
| 4275 | } | ||
| 4242 | } | 4276 | } |
| 4243 | zig_unreachable(); | 4277 | zig_unreachable(); |
| 4244 | } | 4278 | } |
| ... | @@ -10290,6 +10324,8 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -10290,6 +10324,8 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ |
| 10290 | return ira->codegen->invalid_instruction; | 10324 | return ira->codegen->invalid_instruction; |
| 10291 | } | 10325 | } |
| 10292 | 10326 | ||
| 10327 | TypeTableEntry *tag_type = value->value.type->data.enumeration.tag_type; | ||
| 10328 | |||
| 10293 | if (instr_is_comptime(value)) { | 10329 | if (instr_is_comptime(value)) { |
| 10294 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | 10330 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| 10295 | if (!val) | 10331 | if (!val) |
| ... | @@ -10297,13 +10333,15 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -10297,13 +10333,15 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ |
| 10297 | 10333 | ||
| 10298 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | 10334 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 10299 | source_instr->scope, source_instr->source_node); | 10335 | source_instr->scope, source_instr->source_node); |
| 10300 | const_instruction->base.value.type = value->value.type->data.enumeration.tag_type; | 10336 | const_instruction->base.value.type = tag_type; |
| 10301 | const_instruction->base.value.special = ConstValSpecialStatic; | 10337 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 10302 | bignum_init_unsigned(&const_instruction->base.value.data.x_bignum, val->data.x_enum.tag); | 10338 | bignum_init_unsigned(&const_instruction->base.value.data.x_bignum, val->data.x_enum.tag); |
| 10303 | return &const_instruction->base; | 10339 | return &const_instruction->base; |
| 10304 | } | 10340 | } |
| 10305 | 10341 | ||
| 10306 | zig_panic("TODO runtime enum tag instruction"); | 10342 | IrInstruction *result = ir_build_enum_tag(&ira->new_irb, source_instr->scope, source_instr->source_node, value); |
| 10343 | result->value.type = tag_type; | ||
| 10344 | return result; | ||
| 10307 | } | 10345 | } |
| 10308 | 10346 | ||
| 10309 | static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, | 10347 | static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| ... | @@ -11097,6 +11135,35 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc | ... | @@ -11097,6 +11135,35 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc |
| 11097 | return str_type; | 11135 | return str_type; |
| 11098 | } | 11136 | } |
| 11099 | 11137 | ||
| 11138 | static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructionEnumTagName *instruction) { | ||
| 11139 | IrInstruction *target = instruction->target->other; | ||
| 11140 | if (type_is_invalid(target->value.type)) | ||
| 11141 | return ira->codegen->builtin_types.entry_invalid; | ||
| 11142 | |||
| 11143 | assert(target->value.type->id == TypeTableEntryIdEnumTag); | ||
| 11144 | |||
| 11145 | if (instr_is_comptime(target)) { | ||
| 11146 | TypeTableEntry *enum_type = target->value.type->data.enum_tag.enum_type; | ||
| 11147 | uint64_t tag_value = target->value.data.x_bignum.data.x_uint; | ||
| 11148 | TypeEnumField *field = &enum_type->data.enumeration.fields[tag_value]; | ||
| 11149 | ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name); | ||
| 11150 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 11151 | init_const_slice(ira->codegen, out_val, array_val, 0, buf_len(field->name), true); | ||
| 11152 | return out_val->type; | ||
| 11153 | } | ||
| 11154 | |||
| 11155 | if (!target->value.type->data.enum_tag.generate_name_table) { | ||
| 11156 | target->value.type->data.enum_tag.generate_name_table = true; | ||
| 11157 | ira->codegen->name_table_enums.append(target->value.type); | ||
| 11158 | } | ||
| 11159 | |||
| 11160 | IrInstruction *result = ir_build_enum_tag_name(&ira->new_irb, instruction->base.scope, | ||
| 11161 | instruction->base.source_node, target); | ||
| 11162 | ir_link_new_instruction(result, &instruction->base); | ||
| 11163 | result->value.type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | ||
| 11164 | return result->value.type; | ||
| 11165 | } | ||
| 11166 | |||
| 11100 | static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) { | 11167 | static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) { |
| 11101 | IrInstruction *type_value = instruction->type_value->other; | 11168 | IrInstruction *type_value = instruction->type_value->other; |
| 11102 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); | 11169 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| ... | @@ -12641,6 +12708,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -12641,6 +12708,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 12641 | return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction); | 12708 | return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction); |
| 12642 | case IrInstructionIdIntToPtr: | 12709 | case IrInstructionIdIntToPtr: |
| 12643 | return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction); | 12710 | return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction); |
| 12711 | case IrInstructionIdEnumTagName: | ||
| 12712 | return ir_analyze_instruction_enum_tag_name(ira, (IrInstructionEnumTagName *)instruction); | ||
| 12644 | case IrInstructionIdMaybeWrap: | 12713 | case IrInstructionIdMaybeWrap: |
| 12645 | case IrInstructionIdErrWrapCode: | 12714 | case IrInstructionIdErrWrapCode: |
| 12646 | case IrInstructionIdErrWrapPayload: | 12715 | case IrInstructionIdErrWrapPayload: |
| ... | @@ -12792,7 +12861,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -12792,7 +12861,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 12792 | case IrInstructionIdRef: | 12861 | case IrInstructionIdRef: |
| 12793 | case IrInstructionIdMinValue: | 12862 | case IrInstructionIdMinValue: |
| 12794 | case IrInstructionIdMaxValue: | 12863 | case IrInstructionIdMaxValue: |
| 12795 | case IrInstructionIdErrName: | ||
| 12796 | case IrInstructionIdEmbedFile: | 12864 | case IrInstructionIdEmbedFile: |
| 12797 | case IrInstructionIdDivExact: | 12865 | case IrInstructionIdDivExact: |
| 12798 | case IrInstructionIdTruncate: | 12866 | case IrInstructionIdTruncate: |
| ... | @@ -12819,9 +12887,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -12819,9 +12887,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 12819 | case IrInstructionIdIntToErr: | 12887 | case IrInstructionIdIntToErr: |
| 12820 | case IrInstructionIdErrToInt: | 12888 | case IrInstructionIdErrToInt: |
| 12821 | case IrInstructionIdTestType: | 12889 | case IrInstructionIdTestType: |
| 12822 | case IrInstructionIdTypeName: | ||
| 12823 | case IrInstructionIdCanImplicitCast: | 12890 | case IrInstructionIdCanImplicitCast: |
| 12824 | case IrInstructionIdDeclRef: | 12891 | case IrInstructionIdDeclRef: |
| 12892 | case IrInstructionIdErrName: | ||
| 12893 | case IrInstructionIdTypeName: | ||
| 12894 | case IrInstructionIdEnumTagName: | ||
| 12825 | return false; | 12895 | return false; |
| 12826 | case IrInstructionIdAsm: | 12896 | case IrInstructionIdAsm: |
| 12827 | { | 12897 | { |
src/ir_print.cpp+10-4| ... | @@ -816,15 +816,18 @@ static void ir_print_check_switch_prongs(IrPrint *irp, IrInstructionCheckSwitchP | ... | @@ -816,15 +816,18 @@ static void ir_print_check_switch_prongs(IrPrint *irp, IrInstructionCheckSwitchP |
| 816 | } | 816 | } |
| 817 | 817 | ||
| 818 | static void ir_print_test_type(IrPrint *irp, IrInstructionTestType *instruction) { | 818 | static void ir_print_test_type(IrPrint *irp, IrInstructionTestType *instruction) { |
| 819 | fprintf(irp->f, "@testType("); | 819 | fprintf(irp->f, "testtype "); |
| 820 | ir_print_other_instruction(irp, instruction->type_value); | 820 | ir_print_other_instruction(irp, instruction->type_value); |
| 821 | fprintf(irp->f, ")"); | ||
| 822 | } | 821 | } |
| 823 | 822 | ||
| 824 | static void ir_print_type_name(IrPrint *irp, IrInstructionTypeName *instruction) { | 823 | static void ir_print_type_name(IrPrint *irp, IrInstructionTypeName *instruction) { |
| 825 | fprintf(irp->f, "@typeName("); | 824 | fprintf(irp->f, "typename "); |
| 826 | ir_print_other_instruction(irp, instruction->type_value); | 825 | ir_print_other_instruction(irp, instruction->type_value); |
| 827 | fprintf(irp->f, ")"); | 826 | } |
| 827 | |||
| 828 | static void ir_print_enum_tag_name(IrPrint *irp, IrInstructionEnumTagName *instruction) { | ||
| 829 | fprintf(irp->f, "enumtagname "); | ||
| 830 | ir_print_other_instruction(irp, instruction->target); | ||
| 828 | } | 831 | } |
| 829 | 832 | ||
| 830 | static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCast *instruction) { | 833 | static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCast *instruction) { |
| ... | @@ -1131,6 +1134,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1131,6 +1134,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1131 | case IrInstructionIdTypeName: | 1134 | case IrInstructionIdTypeName: |
| 1132 | ir_print_type_name(irp, (IrInstructionTypeName *)instruction); | 1135 | ir_print_type_name(irp, (IrInstructionTypeName *)instruction); |
| 1133 | break; | 1136 | break; |
| 1137 | case IrInstructionIdEnumTagName: | ||
| 1138 | ir_print_enum_tag_name(irp, (IrInstructionEnumTagName *)instruction); | ||
| 1139 | break; | ||
| 1134 | case IrInstructionIdCanImplicitCast: | 1140 | case IrInstructionIdCanImplicitCast: |
| 1135 | ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction); | 1141 | ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction); |
| 1136 | break; | 1142 | break; |
std/build.zig+3-131| ... | @@ -137,13 +137,13 @@ pub const Builder = struct { | ... | @@ -137,13 +137,13 @@ pub const Builder = struct { |
| 137 | Target.Native => {}, | 137 | Target.Native => {}, |
| 138 | Target.Cross => |cross_target| { | 138 | Target.Cross => |cross_target| { |
| 139 | %return zig_args.append("--target-arch"); | 139 | %return zig_args.append("--target-arch"); |
| 140 | %return zig_args.append(targetArchName(cross_target.arch)); | 140 | %return zig_args.append(@enumTagName(cross_target.arch)); |
| 141 | 141 | ||
| 142 | %return zig_args.append("--target-os"); | 142 | %return zig_args.append("--target-os"); |
| 143 | %return zig_args.append(targetOsName(cross_target.os)); | 143 | %return zig_args.append(@enumTagName(cross_target.os)); |
| 144 | 144 | ||
| 145 | %return zig_args.append("--target-environ"); | 145 | %return zig_args.append("--target-environ"); |
| 146 | %return zig_args.append(targetEnvironName(cross_target.environ)); | 146 | %return zig_args.append(@enumTagName(cross_target.environ)); |
| 147 | }, | 147 | }, |
| 148 | } | 148 | } |
| 149 | 149 | ||
| ... | @@ -458,131 +458,3 @@ fn printInvocation(exe_name: []const u8, args: &const List([]const u8)) { | ... | @@ -458,131 +458,3 @@ fn printInvocation(exe_name: []const u8, args: &const List([]const u8)) { |
| 458 | } | 458 | } |
| 459 | %%io.stderr.printf("\n"); | 459 | %%io.stderr.printf("\n"); |
| 460 | } | 460 | } |
| 461 | |||
| 462 | // TODO issue #299 | ||
| 463 | fn targetOsName(target_os: Os) -> []const u8 { | ||
| 464 | return switch (target_os) { | ||
| 465 | Os.freestanding => "freestanding", | ||
| 466 | Os.cloudabi => "cloudabi", | ||
| 467 | Os.darwin => "darwin", | ||
| 468 | Os.dragonfly => "dragonfly", | ||
| 469 | Os.freebsd => "freebsd", | ||
| 470 | Os.ios => "ios", | ||
| 471 | Os.kfreebsd => "kfreebsd", | ||
| 472 | Os.linux => "linux", | ||
| 473 | Os.lv2 => "lv2", | ||
| 474 | Os.macosx => "macosx", | ||
| 475 | Os.netbsd => "netbsd", | ||
| 476 | Os.openbsd => "openbsd", | ||
| 477 | Os.solaris => "solaris", | ||
| 478 | Os.windows => "windows", | ||
| 479 | Os.haiku => "haiku", | ||
| 480 | Os.minix => "minix", | ||
| 481 | Os.rtems => "rtems", | ||
| 482 | Os.nacl => "nacl", | ||
| 483 | Os.cnk => "cnk", | ||
| 484 | Os.bitrig => "bitrig", | ||
| 485 | Os.aix => "aix", | ||
| 486 | Os.cuda => "cuda", | ||
| 487 | Os.nvcl => "nvcl", | ||
| 488 | Os.amdhsa => "amdhsa", | ||
| 489 | Os.ps4 => "ps4", | ||
| 490 | Os.elfiamcu => "elfiamcu", | ||
| 491 | Os.tvos => "tvos", | ||
| 492 | Os.watchos => "watchos", | ||
| 493 | Os.mesa3d => "mesa3d", | ||
| 494 | }; | ||
| 495 | } | ||
| 496 | |||
| 497 | // TODO issue #299 | ||
| 498 | fn targetArchName(target_arch: Arch) -> []const u8 { | ||
| 499 | return switch (target_arch) { | ||
| 500 | Arch.armv8_2a => "armv8_2a", | ||
| 501 | Arch.armv8_1a => "armv8_1a", | ||
| 502 | Arch.armv8 => "armv8", | ||
| 503 | Arch.armv8m_baseline => "armv8m_baseline", | ||
| 504 | Arch.armv8m_mainline => "armv8m_mainline", | ||
| 505 | Arch.armv7 => "armv7", | ||
| 506 | Arch.armv7em => "armv7em", | ||
| 507 | Arch.armv7m => "armv7m", | ||
| 508 | Arch.armv7s => "armv7s", | ||
| 509 | Arch.armv7k => "armv7k", | ||
| 510 | Arch.armv6 => "armv6", | ||
| 511 | Arch.armv6m => "armv6m", | ||
| 512 | Arch.armv6k => "armv6k", | ||
| 513 | Arch.armv6t2 => "armv6t2", | ||
| 514 | Arch.armv5 => "armv5", | ||
| 515 | Arch.armv5te => "armv5te", | ||
| 516 | Arch.armv4t => "armv4t", | ||
| 517 | Arch.armeb => "armeb", | ||
| 518 | Arch.aarch64 => "aarch64", | ||
| 519 | Arch.aarch64_be => "aarch64_be", | ||
| 520 | Arch.avr => "avr", | ||
| 521 | Arch.bpfel => "bpfel", | ||
| 522 | Arch.bpfeb => "bpfeb", | ||
| 523 | Arch.hexagon => "hexagon", | ||
| 524 | Arch.mips => "mips", | ||
| 525 | Arch.mipsel => "mipsel", | ||
| 526 | Arch.mips64 => "mips64", | ||
| 527 | Arch.mips64el => "mips64el", | ||
| 528 | Arch.msp430 => "msp430", | ||
| 529 | Arch.powerpc => "powerpc", | ||
| 530 | Arch.powerpc64 => "powerpc64", | ||
| 531 | Arch.powerpc64le => "powerpc64le", | ||
| 532 | Arch.r600 => "r600", | ||
| 533 | Arch.amdgcn => "amdgcn", | ||
| 534 | Arch.sparc => "sparc", | ||
| 535 | Arch.sparcv9 => "sparcv9", | ||
| 536 | Arch.sparcel => "sparcel", | ||
| 537 | Arch.s390x => "s390x", | ||
| 538 | Arch.tce => "tce", | ||
| 539 | Arch.thumb => "thumb", | ||
| 540 | Arch.thumbeb => "thumbeb", | ||
| 541 | Arch.i386 => "i386", | ||
| 542 | Arch.x86_64 => "x86_64", | ||
| 543 | Arch.xcore => "xcore", | ||
| 544 | Arch.nvptx => "nvptx", | ||
| 545 | Arch.nvptx64 => "nvptx64", | ||
| 546 | Arch.le32 => "le32", | ||
| 547 | Arch.le64 => "le64", | ||
| 548 | Arch.amdil => "amdil", | ||
| 549 | Arch.amdil64 => "amdil64", | ||
| 550 | Arch.hsail => "hsail", | ||
| 551 | Arch.hsail64 => "hsail64", | ||
| 552 | Arch.spir => "spir", | ||
| 553 | Arch.spir64 => "spir64", | ||
| 554 | Arch.kalimbav3 => "kalimbav3", | ||
| 555 | Arch.kalimbav4 => "kalimbav4", | ||
| 556 | Arch.kalimbav5 => "kalimbav5", | ||
| 557 | Arch.shave => "shave", | ||
| 558 | Arch.lanai => "lanai", | ||
| 559 | Arch.wasm32 => "wasm32", | ||
| 560 | Arch.wasm64 => "wasm64", | ||
| 561 | Arch.renderscript32 => "renderscript32", | ||
| 562 | Arch.renderscript64 => "renderscript64", | ||
| 563 | }; | ||
| 564 | } | ||
| 565 | |||
| 566 | // TODO issue #299 | ||
| 567 | fn targetEnvironName(target_environ: Environ) -> []const u8 { | ||
| 568 | return switch (target_environ) { | ||
| 569 | Environ.gnu => "gnu", | ||
| 570 | Environ.gnuabi64 => "gnuabi64", | ||
| 571 | Environ.gnueabi => "gnueabi", | ||
| 572 | Environ.gnueabihf => "gnueabihf", | ||
| 573 | Environ.gnux32 => "gnux32", | ||
| 574 | Environ.code16 => "code16", | ||
| 575 | Environ.eabi => "eabi", | ||
| 576 | Environ.eabihf => "eabihf", | ||
| 577 | Environ.android => "android", | ||
| 578 | Environ.musl => "musl", | ||
| 579 | Environ.musleabi => "musleabi", | ||
| 580 | Environ.musleabihf => "musleabihf", | ||
| 581 | Environ.msvc => "msvc", | ||
| 582 | Environ.itanium => "itanium", | ||
| 583 | Environ.cygnus => "cygnus", | ||
| 584 | Environ.amdopencl => "amdopencl", | ||
| 585 | Environ.coreclr => "coreclr", | ||
| 586 | }; | ||
| 587 | } | ||
| 588 |
std/os/index.zig+1-1| ... | @@ -272,7 +272,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con | ... | @@ -272,7 +272,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con |
| 272 | return posixExecveErrnoToErr(posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr))); | 272 | return posixExecveErrnoToErr(posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr))); |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | const PATH = getEnv("PATH") ?? ([]const u8)("/usr/local/bin:/bin/:/usr/bin"); // TODO issue #299 | 275 | const PATH = getEnv("PATH") ?? "/usr/local/bin:/bin/:/usr/bin"; |
| 276 | // PATH.len because it is >= the largest search_path | 276 | // PATH.len because it is >= the largest search_path |
| 277 | // +1 for the / to join the search path and exe_path | 277 | // +1 for the / to join the search path and exe_path |
| 278 | // +1 for the null terminating byte | 278 | // +1 for the null terminating byte |
test/cases/enum.zig+17| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const mem = @import("std").mem; | ||
| 2 | 3 | ||
| 3 | test "enumType" { | 4 | test "enumType" { |
| 4 | const foo1 = Foo.One {13}; | 5 | const foo1 = Foo.One {13}; |
| ... | @@ -103,3 +104,19 @@ const IntToEnumNumber = enum { | ... | @@ -103,3 +104,19 @@ const IntToEnumNumber = enum { |
| 103 | Three, | 104 | Three, |
| 104 | Four, | 105 | Four, |
| 105 | }; | 106 | }; |
| 107 | |||
| 108 | |||
| 109 | test "enumTagName builtin function" { | ||
| 110 | assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | ||
| 111 | comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | ||
| 112 | } | ||
| 113 | |||
| 114 | fn testEnumTagNameBare(n: BareNumber) -> []const u8 { | ||
| 115 | return @enumTagName(n); | ||
| 116 | } | ||
| 117 | |||
| 118 | const BareNumber = enum { | ||
| 119 | One, | ||
| 120 | Two, | ||
| 121 | Three, | ||
| 122 | }; |