diff --git a/doc/langref.md b/doc/langref.md index 1849ef0351..c53d3f8fc2 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -625,3 +625,7 @@ Converts a pointer of one type to a pointer of another type. ### @intToPtr(comptime DestType: type, int: usize) -> DestType Converts an integer to a pointer. To convert the other way, use `usize(ptr)`. + +### @enumTagName(value: var) -> []const u8 + +Converts an enum tag name to a slice of bytes. Example: diff --git a/src/all_types.hpp b/src/all_types.hpp index 741109b9ab..2d34c12c7a 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -966,6 +966,8 @@ struct TypeTableEntryEnum { struct TypeTableEntryEnumTag { TypeTableEntry *enum_type; TypeTableEntry *int_type; + bool generate_name_table; + LLVMValueRef name_table; }; struct TypeTableEntryUnion { @@ -1200,6 +1202,7 @@ enum BuiltinFnId { BuiltinFnIdPanic, BuiltinFnIdPtrCast, BuiltinFnIdIntToPtr, + BuiltinFnIdEnumTagName, }; struct BuiltinFnEntry { @@ -1464,6 +1467,8 @@ struct CodeGen { Buf global_asm; ZigList link_objects; + + ZigList name_table_enums; }; enum VarLinkage { @@ -1742,6 +1747,7 @@ enum IrInstructionId { IrInstructionIdSetGlobalLinkage, IrInstructionIdDeclRef, IrInstructionIdPanic, + IrInstructionIdEnumTagName, }; struct IrInstruction { @@ -2481,6 +2487,12 @@ struct IrInstructionPanic { IrInstruction *msg; }; +struct IrInstructionEnumTagName { + IrInstruction base; + + IrInstruction *target; +}; + static const size_t slice_ptr_index = 0; static const size_t slice_len_index = 1; diff --git a/src/analyze.cpp b/src/analyze.cpp index 3cb67ca03f..5de319c550 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1181,7 +1181,7 @@ bool type_is_invalid(TypeTableEntry *type_entry) { } -static TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type) { +TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type) { TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnumTag); buf_resize(&entry->name, 0); diff --git a/src/analyze.hpp b/src/analyze.hpp index 574aa5ffb7..b21a3675a5 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -149,5 +149,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val); TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits); ConstParent *get_const_val_parent(ConstExprValue *value); FnTableEntry *get_extern_panic_fn(CodeGen *g); +TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type); #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index edd2cd181e..575010c9d6 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2134,6 +2134,29 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, ""); } +static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable, + IrInstructionEnumTagName *instruction) +{ + TypeTableEntry *enum_tag_type = instruction->target->value.type; + assert(enum_tag_type->data.enum_tag.generate_name_table); + + LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); + if (ir_want_debug_safety(g, &instruction->base)) { + TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type; + size_t field_count = enum_type->data.enumeration.src_field_count; + LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(enum_tag_value)); + LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(enum_tag_value), field_count, false); + add_bounds_check(g, enum_tag_value, LLVMIntUGE, zero, LLVMIntULT, end_val); + } + + LLVMValueRef indices[] = { + LLVMConstNull(g->builtin_types.entry_usize->type_ref), + enum_tag_value, + }; + return LLVMBuildInBoundsGEP(g->builder, enum_tag_type->data.enum_tag.name_table, indices, 2, ""); +} + + static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { switch (atomic_order) { case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered; @@ -2830,6 +2853,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction); case IrInstructionIdPanic: return ir_render_panic(g, executable, (IrInstructionPanic *)instruction); + case IrInstructionIdEnumTagName: + return ir_render_enum_tag_name(g, executable, (IrInstructionEnumTagName *)instruction); } zig_unreachable(); } @@ -3390,6 +3415,46 @@ static void generate_error_name_table(CodeGen *g) { LLVMSetUnnamedAddr(g->err_name_table, true); } +static void generate_enum_name_tables(CodeGen *g) { + TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); + TypeTableEntry *u8_ptr_type = str_type->data.structure.fields[0].type_entry; + + for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) { + TypeTableEntry *enum_tag_type = g->name_table_enums.at(enum_i); + assert(enum_tag_type->id == TypeTableEntryIdEnumTag); + TypeTableEntry *enum_type = enum_tag_type->data.enum_tag.enum_type; + + size_t field_count = enum_type->data.enumeration.src_field_count; + LLVMValueRef *values = allocate(field_count); + for (size_t field_i = 0; field_i < field_count; field_i += 1) { + Buf *name = enum_type->data.enumeration.fields[field_i].name; + + LLVMValueRef str_init = LLVMConstString(buf_ptr(name), buf_len(name), true); + LLVMValueRef str_global = LLVMAddGlobal(g->module, LLVMTypeOf(str_init), ""); + LLVMSetInitializer(str_global, str_init); + LLVMSetLinkage(str_global, LLVMPrivateLinkage); + LLVMSetGlobalConstant(str_global, true); + LLVMSetUnnamedAddr(str_global, true); + + LLVMValueRef fields[] = { + LLVMConstBitCast(str_global, u8_ptr_type->type_ref), + LLVMConstInt(g->builtin_types.entry_usize->type_ref, buf_len(name), false), + }; + values[field_i] = LLVMConstNamedStruct(str_type->type_ref, fields, 2); + } + + LLVMValueRef name_table_init = LLVMConstArray(str_type->type_ref, values, field_count); + + Buf *table_name = buf_sprintf("%s_name_table", buf_ptr(&enum_type->name)); + LLVMValueRef name_table = LLVMAddGlobal(g->module, LLVMTypeOf(name_table_init), buf_ptr(table_name)); + LLVMSetInitializer(name_table, name_table_init); + LLVMSetLinkage(name_table, LLVMPrivateLinkage); + LLVMSetGlobalConstant(name_table, true); + LLVMSetUnnamedAddr(name_table, true); + enum_tag_type->data.enum_tag.name_table = name_table; + } +} + static void build_all_basic_blocks(CodeGen *g, FnTableEntry *fn) { IrExecutable *executable = &fn->analyzed_executable; assert(executable->basic_block_list.length > 0); @@ -3428,6 +3493,7 @@ static void do_code_gen(CodeGen *g) { delete_unused_builtin_fns(g); generate_error_name_table(g); + generate_enum_name_tables(g); // Generate module level variables for (size_t i = 0; i < g->global_vars.length; i += 1) { @@ -3800,7 +3866,8 @@ static const GlobalLinkageValue global_linkage_values[] = { static void init_enum_debug_info(CodeGen *g, TypeTableEntry *enum_type) { uint32_t field_count = enum_type->data.enumeration.src_field_count; - TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); + TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); + TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); enum_type->data.enumeration.tag_type = tag_type_entry; ZigLLVMDIEnumerator **di_enumerators = allocate(field_count); @@ -4327,6 +4394,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrcast", 2); create_builtin_fn(g, BuiltinFnIdIntToPtr, "intToPtr", 2); + create_builtin_fn(g, BuiltinFnIdEnumTagName, "enumTagName", 1); } static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) { diff --git a/src/ir.cpp b/src/ir.cpp index b3f647db70..8aefb4b7bf 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -541,6 +541,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPanic *) { return IrInstructionIdPanic; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTagName *) { + return IrInstructionIdEnumTagName; +} + template static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { T *special_instruction = allocate(1); @@ -2130,6 +2134,17 @@ static IrInstruction *ir_build_panic(IrBuilder *irb, Scope *scope, AstNode *sour return &instruction->base; } +static IrInstruction *ir_build_enum_tag_name(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *target) +{ + IrInstructionEnumTagName *instruction = ir_build_instruction(irb, scope, source_node); + instruction->target = target; + + ir_ref_instruction(target, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { return nullptr; } @@ -2787,6 +2802,13 @@ static IrInstruction *ir_instruction_panic_get_dep(IrInstructionPanic *instructi } } +static IrInstruction *ir_instruction_enumtagname_get_dep(IrInstructionEnumTagName *instruction, size_t index) { + switch (index) { + case 0: return instruction->target; + default: return nullptr; + } +} + static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { switch (instruction->id) { case IrInstructionIdInvalid: @@ -2975,6 +2997,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index); case IrInstructionIdPanic: return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index); + case IrInstructionIdEnumTagName: + return ir_instruction_enumtagname_get_dep((IrInstructionEnumTagName *) instruction, index); } zig_unreachable(); } @@ -4239,6 +4263,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_int_to_ptr(irb, scope, node, arg0_value, arg1_value); } + case BuiltinFnIdEnumTagName: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + IrInstruction *actual_tag = ir_build_enum_tag(irb, scope, node, arg0_value); + return ir_build_enum_tag_name(irb, scope, node, actual_tag); + } } zig_unreachable(); } @@ -10290,6 +10324,8 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ return ira->codegen->invalid_instruction; } + TypeTableEntry *tag_type = value->value.type->data.enumeration.tag_type; + if (instr_is_comptime(value)) { ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); if (!val) @@ -10297,13 +10333,15 @@ static IrInstruction *ir_analyze_enum_tag(IrAnalyze *ira, IrInstruction *source_ IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, source_instr->scope, source_instr->source_node); - const_instruction->base.value.type = value->value.type->data.enumeration.tag_type; + const_instruction->base.value.type = tag_type; const_instruction->base.value.special = ConstValSpecialStatic; bignum_init_unsigned(&const_instruction->base.value.data.x_bignum, val->data.x_enum.tag); return &const_instruction->base; } - zig_panic("TODO runtime enum tag instruction"); + IrInstruction *result = ir_build_enum_tag(&ira->new_irb, source_instr->scope, source_instr->source_node, value); + result->value.type = tag_type; + return result; } static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, @@ -11097,6 +11135,35 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc return str_type; } +static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructionEnumTagName *instruction) { + IrInstruction *target = instruction->target->other; + if (type_is_invalid(target->value.type)) + return ira->codegen->builtin_types.entry_invalid; + + assert(target->value.type->id == TypeTableEntryIdEnumTag); + + if (instr_is_comptime(target)) { + TypeTableEntry *enum_type = target->value.type->data.enum_tag.enum_type; + uint64_t tag_value = target->value.data.x_bignum.data.x_uint; + TypeEnumField *field = &enum_type->data.enumeration.fields[tag_value]; + ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name); + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); + init_const_slice(ira->codegen, out_val, array_val, 0, buf_len(field->name), true); + return out_val->type; + } + + if (!target->value.type->data.enum_tag.generate_name_table) { + target->value.type->data.enum_tag.generate_name_table = true; + ira->codegen->name_table_enums.append(target->value.type); + } + + IrInstruction *result = ir_build_enum_tag_name(&ira->new_irb, instruction->base.scope, + instruction->base.source_node, target); + ir_link_new_instruction(result, &instruction->base); + result->value.type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); + return result->value.type; +} + static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) { IrInstruction *type_value = instruction->type_value->other; TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); @@ -12641,6 +12708,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction); case IrInstructionIdIntToPtr: return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction); + case IrInstructionIdEnumTagName: + return ir_analyze_instruction_enum_tag_name(ira, (IrInstructionEnumTagName *)instruction); case IrInstructionIdMaybeWrap: case IrInstructionIdErrWrapCode: case IrInstructionIdErrWrapPayload: @@ -12792,7 +12861,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdRef: case IrInstructionIdMinValue: case IrInstructionIdMaxValue: - case IrInstructionIdErrName: case IrInstructionIdEmbedFile: case IrInstructionIdDivExact: case IrInstructionIdTruncate: @@ -12819,9 +12887,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdIntToErr: case IrInstructionIdErrToInt: case IrInstructionIdTestType: - case IrInstructionIdTypeName: case IrInstructionIdCanImplicitCast: case IrInstructionIdDeclRef: + case IrInstructionIdErrName: + case IrInstructionIdTypeName: + case IrInstructionIdEnumTagName: return false; case IrInstructionIdAsm: { diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 1a839cd20f..dbad27afb7 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -816,15 +816,18 @@ static void ir_print_check_switch_prongs(IrPrint *irp, IrInstructionCheckSwitchP } static void ir_print_test_type(IrPrint *irp, IrInstructionTestType *instruction) { - fprintf(irp->f, "@testType("); + fprintf(irp->f, "testtype "); ir_print_other_instruction(irp, instruction->type_value); - fprintf(irp->f, ")"); } static void ir_print_type_name(IrPrint *irp, IrInstructionTypeName *instruction) { - fprintf(irp->f, "@typeName("); + fprintf(irp->f, "typename "); ir_print_other_instruction(irp, instruction->type_value); - fprintf(irp->f, ")"); +} + +static void ir_print_enum_tag_name(IrPrint *irp, IrInstructionEnumTagName *instruction) { + fprintf(irp->f, "enumtagname "); + ir_print_other_instruction(irp, instruction->target); } static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCast *instruction) { @@ -1131,6 +1134,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdTypeName: ir_print_type_name(irp, (IrInstructionTypeName *)instruction); break; + case IrInstructionIdEnumTagName: + ir_print_enum_tag_name(irp, (IrInstructionEnumTagName *)instruction); + break; case IrInstructionIdCanImplicitCast: ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction); break; diff --git a/std/build.zig b/std/build.zig index 6f26112ce8..bf741b5b95 100644 --- a/std/build.zig +++ b/std/build.zig @@ -137,13 +137,13 @@ pub const Builder = struct { Target.Native => {}, Target.Cross => |cross_target| { %return zig_args.append("--target-arch"); - %return zig_args.append(targetArchName(cross_target.arch)); + %return zig_args.append(@enumTagName(cross_target.arch)); %return zig_args.append("--target-os"); - %return zig_args.append(targetOsName(cross_target.os)); + %return zig_args.append(@enumTagName(cross_target.os)); %return zig_args.append("--target-environ"); - %return zig_args.append(targetEnvironName(cross_target.environ)); + %return zig_args.append(@enumTagName(cross_target.environ)); }, } @@ -458,131 +458,3 @@ fn printInvocation(exe_name: []const u8, args: &const List([]const u8)) { } %%io.stderr.printf("\n"); } - -// TODO issue #299 -fn targetOsName(target_os: Os) -> []const u8 { - return switch (target_os) { - Os.freestanding => "freestanding", - Os.cloudabi => "cloudabi", - Os.darwin => "darwin", - Os.dragonfly => "dragonfly", - Os.freebsd => "freebsd", - Os.ios => "ios", - Os.kfreebsd => "kfreebsd", - Os.linux => "linux", - Os.lv2 => "lv2", - Os.macosx => "macosx", - Os.netbsd => "netbsd", - Os.openbsd => "openbsd", - Os.solaris => "solaris", - Os.windows => "windows", - Os.haiku => "haiku", - Os.minix => "minix", - Os.rtems => "rtems", - Os.nacl => "nacl", - Os.cnk => "cnk", - Os.bitrig => "bitrig", - Os.aix => "aix", - Os.cuda => "cuda", - Os.nvcl => "nvcl", - Os.amdhsa => "amdhsa", - Os.ps4 => "ps4", - Os.elfiamcu => "elfiamcu", - Os.tvos => "tvos", - Os.watchos => "watchos", - Os.mesa3d => "mesa3d", - }; -} - -// TODO issue #299 -fn targetArchName(target_arch: Arch) -> []const u8 { - return switch (target_arch) { - Arch.armv8_2a => "armv8_2a", - Arch.armv8_1a => "armv8_1a", - Arch.armv8 => "armv8", - Arch.armv8m_baseline => "armv8m_baseline", - Arch.armv8m_mainline => "armv8m_mainline", - Arch.armv7 => "armv7", - Arch.armv7em => "armv7em", - Arch.armv7m => "armv7m", - Arch.armv7s => "armv7s", - Arch.armv7k => "armv7k", - Arch.armv6 => "armv6", - Arch.armv6m => "armv6m", - Arch.armv6k => "armv6k", - Arch.armv6t2 => "armv6t2", - Arch.armv5 => "armv5", - Arch.armv5te => "armv5te", - Arch.armv4t => "armv4t", - Arch.armeb => "armeb", - Arch.aarch64 => "aarch64", - Arch.aarch64_be => "aarch64_be", - Arch.avr => "avr", - Arch.bpfel => "bpfel", - Arch.bpfeb => "bpfeb", - Arch.hexagon => "hexagon", - Arch.mips => "mips", - Arch.mipsel => "mipsel", - Arch.mips64 => "mips64", - Arch.mips64el => "mips64el", - Arch.msp430 => "msp430", - Arch.powerpc => "powerpc", - Arch.powerpc64 => "powerpc64", - Arch.powerpc64le => "powerpc64le", - Arch.r600 => "r600", - Arch.amdgcn => "amdgcn", - Arch.sparc => "sparc", - Arch.sparcv9 => "sparcv9", - Arch.sparcel => "sparcel", - Arch.s390x => "s390x", - Arch.tce => "tce", - Arch.thumb => "thumb", - Arch.thumbeb => "thumbeb", - Arch.i386 => "i386", - Arch.x86_64 => "x86_64", - Arch.xcore => "xcore", - Arch.nvptx => "nvptx", - Arch.nvptx64 => "nvptx64", - Arch.le32 => "le32", - Arch.le64 => "le64", - Arch.amdil => "amdil", - Arch.amdil64 => "amdil64", - Arch.hsail => "hsail", - Arch.hsail64 => "hsail64", - Arch.spir => "spir", - Arch.spir64 => "spir64", - Arch.kalimbav3 => "kalimbav3", - Arch.kalimbav4 => "kalimbav4", - Arch.kalimbav5 => "kalimbav5", - Arch.shave => "shave", - Arch.lanai => "lanai", - Arch.wasm32 => "wasm32", - Arch.wasm64 => "wasm64", - Arch.renderscript32 => "renderscript32", - Arch.renderscript64 => "renderscript64", - }; -} - -// TODO issue #299 -fn targetEnvironName(target_environ: Environ) -> []const u8 { - return switch (target_environ) { - Environ.gnu => "gnu", - Environ.gnuabi64 => "gnuabi64", - Environ.gnueabi => "gnueabi", - Environ.gnueabihf => "gnueabihf", - Environ.gnux32 => "gnux32", - Environ.code16 => "code16", - Environ.eabi => "eabi", - Environ.eabihf => "eabihf", - Environ.android => "android", - Environ.musl => "musl", - Environ.musleabi => "musleabi", - Environ.musleabihf => "musleabihf", - Environ.msvc => "msvc", - Environ.itanium => "itanium", - Environ.cygnus => "cygnus", - Environ.amdopencl => "amdopencl", - Environ.coreclr => "coreclr", - }; -} - diff --git a/std/os/index.zig b/std/os/index.zig index 0699e9acd7..b2cc6fabe2 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -272,7 +272,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con return posixExecveErrnoToErr(posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr))); } - const PATH = getEnv("PATH") ?? ([]const u8)("/usr/local/bin:/bin/:/usr/bin"); // TODO issue #299 + const PATH = getEnv("PATH") ?? "/usr/local/bin:/bin/:/usr/bin"; // PATH.len because it is >= the largest search_path // +1 for the / to join the search path and exe_path // +1 for the null terminating byte diff --git a/test/cases/enum.zig b/test/cases/enum.zig index 4892ec6eba..44254a60d0 100644 --- a/test/cases/enum.zig +++ b/test/cases/enum.zig @@ -1,4 +1,5 @@ const assert = @import("std").debug.assert; +const mem = @import("std").mem; test "enumType" { const foo1 = Foo.One {13}; @@ -103,3 +104,19 @@ const IntToEnumNumber = enum { Three, Four, }; + + +test "enumTagName builtin function" { + assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); + comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); +} + +fn testEnumTagNameBare(n: BareNumber) -> []const u8 { + return @enumTagName(n); +} + +const BareNumber = enum { + One, + Two, + Three, +};