diff --git a/build.zig b/build.zig index 16185eebf4..d99165a6de 100644 --- a/build.zig +++ b/build.zig @@ -104,7 +104,7 @@ pub fn build(b: *Builder) !void { } const modes = chosen_modes[0..chosen_mode_index]; - test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes)); + test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes)); test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes)); @@ -299,8 +299,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { } else if (exe.target.isFreeBSD()) { try addCxxKnownPath(b, ctx, exe, "libc++.a", null); exe.linkSystemLibrary("pthread"); - } - else if (exe.target.isDarwin()) { + } else if (exe.target.isDarwin()) { if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) { // Compiler is GCC. try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null); diff --git a/doc/langref.html.in b/doc/langref.html.in index 6e03d3ec6d..909c0f5817 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -4327,7 +4327,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {

For example, if we were to introduce another function to the above snippet:

- {#code_begin|test_err|unable to evaluate constant expression#} + {#code_begin|test_err|values of type 'type' must be comptime known#} fn max(comptime T: type, a: T, b: T) T { return if (a > b) a else b; } @@ -5905,13 +5905,13 @@ fn add(a: i32, b: i32) i32 { return a + b; } This function is a low level intrinsic with no safety mechanisms. Most code should not use this function, instead using something like this:

-
{#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}
+
{#syntax#}for (source[0..byte_count]) |b, i| dest[i] = b;{#endsyntax#}

The optimizer is intelligent enough to turn the above snippet into a memcpy.

There is also a standard library function for this:

{#syntax#}const mem = @import("std").mem;
-mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}
+mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#} {#header_close#} {#header_open|@memset#} @@ -5923,7 +5923,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#} This function is a low level intrinsic with no safety mechanisms. Most code should not use this function, instead using something like this:

-
{#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}
+
{#syntax#}for (dest[0..byte_count]) |*b| b.* = c;{#endsyntax#}

The optimizer is intelligent enough to turn the above snippet into a memset.

@@ -6592,9 +6592,10 @@ pub const TypeInfo = union(TypeId) { {#header_close#} {#header_open|@typeName#} -
{#syntax#}@typeName(T: type) []u8{#endsyntax#}
+
{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}

- This function returns the string representation of a type. + This function returns the string representation of a type, as + an array. It is equivalent to a string literal of the type name.

{#header_close#} diff --git a/src/all_types.hpp b/src/all_types.hpp index 91b24e3110..4b134361a3 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -56,9 +56,6 @@ struct IrExecutable { size_t next_debug_id; size_t *backward_branch_count; size_t backward_branch_quota; - bool invalid; - bool is_inline; - bool is_generic_instantiation; ZigFn *fn_entry; Buf *c_import_buf; AstNode *source_node; @@ -78,6 +75,10 @@ struct IrExecutable { IrBasicBlock *coro_suspend_block; IrBasicBlock *coro_final_cleanup_block; ZigVar *coro_allocator_var; + + bool invalid; + bool is_inline; + bool is_generic_instantiation; }; enum OutType { @@ -90,6 +91,9 @@ enum OutType { enum ConstParentId { ConstParentIdNone, ConstParentIdStruct, + ConstParentIdErrUnionCode, + ConstParentIdErrUnionPayload, + ConstParentIdOptionalPayload, ConstParentIdArray, ConstParentIdUnion, ConstParentIdScalar, @@ -107,6 +111,15 @@ struct ConstParent { ConstExprValue *struct_val; size_t field_index; } p_struct; + struct { + ConstExprValue *err_union_val; + } p_err_union_code; + struct { + ConstExprValue *err_union_val; + } p_err_union_payload; + struct { + ConstExprValue *optional_val; + } p_optional_payload; struct { ConstExprValue *union_val; } p_union; @@ -118,13 +131,11 @@ struct ConstParent { struct ConstStructValue { ConstExprValue *fields; - ConstParent parent; }; struct ConstUnionValue { BigInt tag; ConstExprValue *payload; - ConstParent parent; }; enum ConstArraySpecial { @@ -138,7 +149,6 @@ struct ConstArrayValue { union { struct { ConstExprValue *elements; - ConstParent parent; } s_none; Buf *s_buf; } data; @@ -153,19 +163,29 @@ enum ConstPtrSpecial { ConstPtrSpecialBaseArray, // The pointer points to a field in an underlying struct. ConstPtrSpecialBaseStruct, + // The pointer points to the error set field of an error union + ConstPtrSpecialBaseErrorUnionCode, + // The pointer points to the payload field of an error union + ConstPtrSpecialBaseErrorUnionPayload, + // The pointer points to the payload field of an optional + ConstPtrSpecialBaseOptionalPayload, // This means that we did a compile-time pointer reinterpret and we cannot // understand the value of pointee at compile time. However, we will still // emit a binary with a compile time known address. // In this case index is the numeric address value. - // We also use this for null pointer. We need the data layout for ConstCastOnly == true - // types to be the same, so all optionals of pointer types use x_ptr - // instead of x_optional ConstPtrSpecialHardCodedAddr, // This means that the pointer represents memory of assigning to _. // That is, storing discards the data, and loading is invalid. ConstPtrSpecialDiscard, // This is actually a function. ConstPtrSpecialFunction, + // This means the pointer is null. This is only allowed when the type is ?*T. + // We use this instead of ConstPtrSpecialHardCodedAddr because often we check + // for that value to avoid doing comptime work. + // We need the data layout for ConstCastOnly == true + // types to be the same, so all optionals of pointer types use x_ptr + // instead of x_optional. + ConstPtrSpecialNull, }; enum ConstPtrMut { @@ -199,6 +219,15 @@ struct ConstPtrValue { ConstExprValue *struct_val; size_t field_index; } base_struct; + struct { + ConstExprValue *err_union_val; + } base_err_union_code; + struct { + ConstExprValue *err_union_val; + } base_err_union_payload; + struct { + ConstExprValue *optional_val; + } base_optional_payload; struct { uint64_t addr; } hard_coded_addr; @@ -209,7 +238,7 @@ struct ConstPtrValue { }; struct ConstErrValue { - ErrorTableEntry *err; + ConstExprValue *error_set; ConstExprValue *payload; }; @@ -265,6 +294,7 @@ struct ConstGlobalRefs { struct ConstExprValue { ZigType *type; ConstValSpecial special; + ConstParent parent; ConstGlobalRefs *global_refs; union { @@ -433,7 +463,7 @@ enum NodeType { NodeTypeArrayType, NodeTypeErrorType, NodeTypeIfErrorExpr, - NodeTypeTestExpr, + NodeTypeIfOptional, NodeTypeErrorSetDecl, NodeTypeCancel, NodeTypeResume, @@ -677,7 +707,7 @@ struct AstNodeUse { AstNode *expr; TldResolution resolution; - IrInstruction *value; + ConstExprValue *value; }; struct AstNodeIfBoolExpr { @@ -1610,7 +1640,7 @@ struct CodeGen { HashMap fn_type_table; HashMap error_table; HashMap generic_table; - HashMap memoized_fn_eval_table; + HashMap memoized_fn_eval_table; HashMap llvm_fn_table; HashMap exported_symbol_names; HashMap external_prototypes; @@ -1802,10 +1832,9 @@ enum VarLinkage { struct ZigVar { Buf name; - ConstExprValue *value; + ConstExprValue *const_value; + ZigType *var_type; LLVMValueRef value_ref; - bool src_is_const; - bool gen_is_const; IrInstruction *is_comptime; // which node is the declaration of the variable AstNode *decl_node; @@ -1815,17 +1844,21 @@ struct ZigVar { Scope *parent_scope; Scope *child_scope; LLVMValueRef param_value_ref; - bool shadowable; size_t mem_slot_index; IrExecutable *owner_exec; size_t ref_count; - VarLinkage linkage; - uint32_t align_bytes; // In an inline loop, multiple variables may be created, // In this case, a reference to a variable should follow // this pointer to the redefined variable. ZigVar *next_var; + + uint32_t align_bytes; + VarLinkage linkage; + + bool shadowable; + bool src_is_const; + bool gen_is_const; }; struct ErrorTableEntry { @@ -1891,10 +1924,11 @@ struct ScopeBlock { ZigList *incoming_values; ZigList *incoming_blocks; - bool safety_off; AstNode *safety_set_node; - bool fast_math_on; AstNode *fast_math_set_node; + + bool safety_off; + bool fast_math_on; }; // This scope is created from every defer expression. @@ -2030,8 +2064,19 @@ struct IrBasicBlock { IrInstruction *must_be_comptime_source_instr; }; +// These instructions are in transition to having "pass 1" instructions +// and "pass 2" instructions. The pass 1 instructions are suffixed with Src +// and pass 2 are suffixed with Gen. +// Once all instructions are separated in this way, they'll have different +// base types for better type safety. +// Src instructions are generated by ir_gen_* functions in ir.cpp from AST. +// ir_analyze_* functions consume Src instructions and produce Gen instructions. +// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. +// Src instructions do not have type information; Gen instructions do. enum IrInstructionId { IrInstructionIdInvalid, + IrInstructionIdDeclVarSrc, + IrInstructionIdDeclVarGen, IrInstructionIdBr, IrInstructionIdCondBr, IrInstructionIdSwitchBr, @@ -2040,7 +2085,6 @@ enum IrInstructionId { IrInstructionIdPhi, IrInstructionIdUnOp, IrInstructionIdBinOp, - IrInstructionIdDeclVar, IrInstructionIdLoadPtr, IrInstructionIdStorePtr, IrInstructionIdFieldPtr, @@ -2069,7 +2113,7 @@ enum IrInstructionId { IrInstructionIdAsm, IrInstructionIdSizeOf, IrInstructionIdTestNonNull, - IrInstructionIdUnwrapOptional, + IrInstructionIdOptionalUnwrapPtr, IrInstructionIdOptionalWrap, IrInstructionIdUnionTag, IrInstructionIdClz, @@ -2085,7 +2129,8 @@ enum IrInstructionId { IrInstructionIdCompileLog, IrInstructionIdErrName, IrInstructionIdEmbedFile, - IrInstructionIdCmpxchg, + IrInstructionIdCmpxchgSrc, + IrInstructionIdCmpxchgGen, IrInstructionIdFence, IrInstructionIdTruncate, IrInstructionIdIntCast, @@ -2114,7 +2159,8 @@ enum IrInstructionId { IrInstructionIdErrWrapPayload, IrInstructionIdFnProto, IrInstructionIdTestComptime, - IrInstructionIdPtrCast, + IrInstructionIdPtrCastSrc, + IrInstructionIdPtrCastGen, IrInstructionIdBitCast, IrInstructionIdWidenOrShorten, IrInstructionIdIntToPtr, @@ -2194,6 +2240,22 @@ struct IrInstruction { bool is_gen; }; +struct IrInstructionDeclVarSrc { + IrInstruction base; + + ZigVar *var; + IrInstruction *var_type; + IrInstruction *align_value; + IrInstruction *init_value; +}; + +struct IrInstructionDeclVarGen { + IrInstruction base; + + ZigVar *var; + IrInstruction *init_value; +}; + struct IrInstructionCondBr { IrInstruction base; @@ -2302,20 +2364,11 @@ struct IrInstructionBinOp { IrInstruction base; IrInstruction *op1; - IrBinOp op_id; IrInstruction *op2; + IrBinOp op_id; bool safety_check_on; }; -struct IrInstructionDeclVar { - IrInstruction base; - - ZigVar *var; - IrInstruction *var_type; - IrInstruction *align_value; - IrInstruction *init_value; -}; - struct IrInstructionLoadPtr { IrInstruction base; @@ -2335,7 +2388,6 @@ struct IrInstructionFieldPtr { IrInstruction *container_ptr; Buf *field_name_buffer; IrInstruction *field_name_expr; - bool is_const; }; struct IrInstructionStructFieldPtr { @@ -2378,13 +2430,13 @@ struct IrInstructionCall { ZigFn *fn_entry; size_t arg_count; IrInstruction **args; - bool is_comptime; LLVMValueRef tmp_ptr; - FnInline fn_inline; - bool is_async; IrInstruction *async_allocator; IrInstruction *new_stack; + FnInline fn_inline; + bool is_async; + bool is_comptime; }; struct IrInstructionConst { @@ -2527,9 +2579,9 @@ struct IrInstructionSliceType { IrInstruction base; IrInstruction *align_value; + IrInstruction *child_type; bool is_const; bool is_volatile; - IrInstruction *child_type; }; struct IrInstructionAsm { @@ -2557,10 +2609,12 @@ struct IrInstructionTestNonNull { IrInstruction *value; }; -struct IrInstructionUnwrapOptional { +// Takes a pointer to an optional value, returns a pointer +// to the payload. +struct IrInstructionOptionalUnwrapPtr { IrInstruction base; - IrInstruction *value; + IrInstruction *base_ptr; bool safety_check_on; }; @@ -2651,7 +2705,7 @@ struct IrInstructionEmbedFile { IrInstruction *name; }; -struct IrInstructionCmpxchg { +struct IrInstructionCmpxchgSrc { IrInstruction base; IrInstruction *type_value; @@ -2661,14 +2715,19 @@ struct IrInstructionCmpxchg { IrInstruction *success_order_value; IrInstruction *failure_order_value; - // if this instruction gets to runtime then we know these values: - ZigType *type; + bool is_weak; +}; + +struct IrInstructionCmpxchgGen { + IrInstruction base; + + IrInstruction *ptr; + IrInstruction *cmp_value; + IrInstruction *new_value; + LLVMValueRef tmp_ptr; AtomicOrder success_order; AtomicOrder failure_order; - bool is_weak; - - LLVMValueRef tmp_ptr; }; struct IrInstructionFence { @@ -2851,7 +2910,7 @@ struct IrInstructionTestErr { struct IrInstructionUnwrapErrCode { IrInstruction base; - IrInstruction *value; + IrInstruction *err_union; }; struct IrInstructionUnwrapErrPayload { @@ -2899,13 +2958,19 @@ struct IrInstructionTestComptime { IrInstruction *value; }; -struct IrInstructionPtrCast { +struct IrInstructionPtrCastSrc { IrInstruction base; IrInstruction *dest_type; IrInstruction *ptr; }; +struct IrInstructionPtrCastGen { + IrInstruction base; + + IrInstruction *ptr; +}; + struct IrInstructionBitCast { IrInstruction base; diff --git a/src/analyze.cpp b/src/analyze.cpp index 15370983fc..194888068c 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -570,7 +570,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { if (child_type->zero_bits) { entry->type_ref = LLVMInt1Type(); entry->di_type = g->builtin_types.entry_bool->di_type; - } else if (type_is_codegen_pointer(child_type)) { + } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) { assert(child_type->di_type); // this is an optimization but also is necessary for calling C // functions where all pointers are maybe pointers @@ -1278,7 +1278,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind return entry; } -static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) { +static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, + Buf *type_name) +{ size_t backward_branch_count = 0; return ir_eval_const_value(g, scope, node, type_entry, &backward_branch_count, default_backward_branch_quota, @@ -1286,12 +1288,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod } ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { - IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); - if (result->value.type->id == ZigTypeIdInvalid) + ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); + if (type_is_invalid(result->type)) return g->builtin_types.entry_invalid; - assert(result->value.special != ConstValSpecialRuntime); - return result->value.data.x_type; + assert(result->special != ConstValSpecialRuntime); + return result->data.x_type; } ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { @@ -1342,11 +1344,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou } static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) { - IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); - if (type_is_invalid(align_result->value.type)) + ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); + if (type_is_invalid(align_result->type)) return false; - uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint); + uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint); if (align_bytes == 0) { add_node_error(g, node, buf_sprintf("alignment must be >= 1")); return false; @@ -1364,12 +1366,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, PtrLenUnknown, 0, 0, 0); ZigType *str_type = get_slice_type(g, ptr_type); - IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr); - if (type_is_invalid(instr->value.type)) + ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr); + if (type_is_invalid(result_val->type)) return false; - ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index]; - ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index]; + ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index]; assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; @@ -2504,20 +2506,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { // In this first pass we resolve explicit tag values. // In a second pass we will fill in the unspecified ones. if (tag_value != nullptr) { - IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); - if (result_inst->value.type->id == ZigTypeIdInvalid) { + ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); + if (type_is_invalid(result->type)) { enum_type->data.enumeration.is_invalid = true; continue; } - assert(result_inst->value.special != ConstValSpecialRuntime); - assert(result_inst->value.type->id == ZigTypeIdInt || - result_inst->value.type->id == ZigTypeIdComptimeInt); - auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); + assert(result->special != ConstValSpecialRuntime); + assert(result->type->id == ZigTypeIdInt || + result->type->id == ZigTypeIdComptimeInt); + auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); if (entry == nullptr) { - bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint); + bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); } else { Buf *val_buf = buf_alloc(); - bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); + bigint_append_buf(val_buf, &result->data.x_bigint, 10); ErrorMsg *msg = add_node_error(g, tag_value, buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); @@ -2944,19 +2946,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { // In a second pass we will fill in the unspecified ones. if (tag_value != nullptr) { ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type; - IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); - if (result_inst->value.type->id == ZigTypeIdInvalid) { + ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); + if (type_is_invalid(result->type)) { union_type->data.unionation.is_invalid = true; continue; } - assert(result_inst->value.special != ConstValSpecialRuntime); - assert(result_inst->value.type->id == ZigTypeIdInt); - auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); + assert(result->special != ConstValSpecialRuntime); + assert(result->type->id == ZigTypeIdInt); + auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); if (entry == nullptr) { - bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint); + bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint); } else { Buf *val_buf = buf_alloc(); - bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); + bigint_append_buf(val_buf, &result->data.x_bigint, 10); ErrorMsg *msg = add_node_error(g, tag_value, buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); @@ -3419,7 +3421,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { resolve_top_level_decl(g, tld, false, tld->source_node); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; - tld_var->var->value = value; + tld_var->var->const_value = value; + tld_var->var->var_type = value->type; tld_var->var->align_bytes = get_abi_alignment(g, value->type); } @@ -3513,7 +3516,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { case NodeTypeArrayType: case NodeTypeErrorType: case NodeTypeIfErrorExpr: - case NodeTypeTestExpr: + case NodeTypeIfOptional: case NodeTypeErrorSetDecl: case NodeTypeCancel: case NodeTypeResume: @@ -3582,13 +3585,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry // Set name to nullptr to make the variable anonymous (not visible to programmer). // TODO merge with definition of add_local_var in ir.cpp ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, - bool is_const, ConstExprValue *value, Tld *src_tld) + bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type) { Error err; - assert(value); + assert(const_value != nullptr); + assert(var_type != nullptr); ZigVar *variable_entry = allocate(1); - variable_entry->value = value; + variable_entry->const_value = const_value; + variable_entry->var_type = var_type; variable_entry->parent_scope = parent_scope; variable_entry->shadowable = false; variable_entry->mem_slot_index = SIZE_MAX; @@ -3597,23 +3602,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf assert(name); buf_init_from_buf(&variable_entry->name, name); - if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) { - variable_entry->value->type = g->builtin_types.entry_invalid; + if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) { + variable_entry->var_type = g->builtin_types.entry_invalid; } else { - variable_entry->align_bytes = get_abi_alignment(g, value->type); + variable_entry->align_bytes = get_abi_alignment(g, var_type); ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr); if (existing_var && !existing_var->shadowable) { ErrorMsg *msg = add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); - variable_entry->value->type = g->builtin_types.entry_invalid; + variable_entry->var_type = g->builtin_types.entry_invalid; } else { ZigType *type; if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) { add_node_error(g, source_node, buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); - variable_entry->value->type = g->builtin_types.entry_invalid; + variable_entry->var_type = g->builtin_types.entry_invalid; } else { Scope *search_scope = nullptr; if (src_tld == nullptr) { @@ -3627,7 +3632,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf ErrorMsg *msg = add_node_error(g, source_node, buf_sprintf("redefinition of '%s'", buf_ptr(name))); add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here")); - variable_entry->value->type = g->builtin_types.entry_invalid; + variable_entry->var_type = g->builtin_types.entry_invalid; } } } @@ -3677,7 +3682,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { linkage = VarLinkageInternal; } - IrInstruction *init_value = nullptr; + ConstExprValue *init_value = nullptr; // TODO more validation for types that can't be used for export/extern variables ZigType *implicit_type = nullptr; @@ -3686,7 +3691,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { } else if (var_decl->expr) { init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol); assert(init_value); - implicit_type = init_value->value.type; + implicit_type = init_value->type; if (implicit_type->id == ZigTypeIdUnreachable) { add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable")); @@ -3704,7 +3709,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant")); implicit_type = g->builtin_types.entry_invalid; } - assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime); + assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime); } else if (linkage != VarLinkageExternal) { add_node_error(g, source_node, buf_sprintf("variables must be initialized")); implicit_type = g->builtin_types.entry_invalid; @@ -3713,19 +3718,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { ZigType *type = explicit_type ? explicit_type : implicit_type; assert(type != nullptr); // should have been caught by the parser - ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type); + ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type); tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, - is_const, init_val, &tld_var->base); + is_const, init_val, &tld_var->base, type); tld_var->var->linkage = linkage; if (implicit_type != nullptr && type_is_invalid(implicit_type)) { - tld_var->var->value->type = g->builtin_types.entry_invalid; + tld_var->var->var_type = g->builtin_types.entry_invalid; } if (var_decl->align_expr != nullptr) { if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) { - tld_var->var->value->type = g->builtin_types.entry_invalid; + tld_var->var->var_type = g->builtin_types.entry_invalid; } } @@ -4090,7 +4095,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { } ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope, - param_name, true, create_const_runtime(param_type), nullptr); + param_name, true, create_const_runtime(param_type), nullptr, param_type); var->src_arg_index = i; fn_table_entry->child_scope = var->child_scope; var->shadowable = var->shadowable || is_var_args; @@ -4228,18 +4233,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * preview_use_decl(g, src_use_node); } - IrInstruction *use_target_value = src_use_node->data.use.value; - if (use_target_value->value.type->id == ZigTypeIdInvalid) { + ConstExprValue *use_target_value = src_use_node->data.use.value; + if (type_is_invalid(use_target_value->type)) { dst_use_node->owner->any_imports_failed = true; return; } dst_use_node->data.use.resolution = TldResolutionOk; - ConstExprValue *const_val = &use_target_value->value; - assert(const_val->special != ConstValSpecialRuntime); + assert(use_target_value->special != ConstValSpecialRuntime); - ImportTableEntry *target_import = const_val->data.x_import; + ImportTableEntry *target_import = use_target_value->data.x_import; assert(target_import); if (target_import->any_imports_failed) { @@ -4302,10 +4306,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) { } node->data.use.resolution = TldResolutionResolving; - IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base, + ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base, node->data.use.expr, g->builtin_types.entry_namespace, nullptr); - if (result->value.type->id == ZigTypeIdInvalid) + if (type_is_invalid(result->type)) node->owner->any_imports_failed = true; node->data.use.value = result; @@ -4486,7 +4490,8 @@ bool handle_is_ptr(ZigType *type_entry) { return type_has_bits(type_entry->data.error_union.payload_type); case ZigTypeIdOptional: return type_has_bits(type_entry->data.maybe.child_type) && - !type_is_codegen_pointer(type_entry->data.maybe.child_type); + !type_is_codegen_pointer(type_entry->data.maybe.child_type) && + type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet; case ZigTypeIdUnion: assert(type_entry->data.unionation.zero_bits_known); if (type_entry->data.unionation.gen_field_count == 0) @@ -4732,6 +4737,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) { return true; } +static uint32_t hash_const_val_error_set(ConstExprValue *const_val) { + assert(const_val->data.x_err_set != nullptr); + return const_val->data.x_err_set->value ^ 2630160122; +} + static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { uint32_t hash_val = 0; switch (const_val->data.x_ptr.mut) { @@ -4763,6 +4773,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val); hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index); return hash_val; + case ConstPtrSpecialBaseErrorUnionCode: + hash_val += (uint32_t)2994743799; + hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val); + return hash_val; + case ConstPtrSpecialBaseErrorUnionPayload: + hash_val += (uint32_t)3456080131; + hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val); + return hash_val; + case ConstPtrSpecialBaseOptionalPayload: + hash_val += (uint32_t)3163140517; + hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val); + return hash_val; case ConstPtrSpecialHardCodedAddr: hash_val += (uint32_t)4048518294; hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr); @@ -4774,6 +4796,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { hash_val += (uint32_t)2590901619; hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); return hash_val; + case ConstPtrSpecialNull: + hash_val += (uint32_t)1486246455; + return hash_val; } zig_unreachable(); } @@ -4872,7 +4897,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { return 2709806591; case ZigTypeIdOptional: if (get_codegen_ptr_type(const_val->type) != nullptr) { - return hash_const_val(const_val) * 1992916303; + return hash_const_val_ptr(const_val) * 1992916303; + } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) { + return hash_const_val_error_set(const_val) * 3147031929; } else { if (const_val->data.x_optional) { return hash_const_val(const_val->data.x_optional) * 1992916303; @@ -4884,8 +4911,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { // TODO better hashing algorithm return 3415065496; case ZigTypeIdErrorSet: - assert(const_val->data.x_err_set != nullptr); - return const_val->data.x_err_set->value ^ 2630160122; + return hash_const_val_error_set(const_val); case ZigTypeIdNamespace: return hash_ptr(const_val->data.x_import); case ZigTypeIdBoundFn: @@ -4987,7 +5013,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { return can_mutate_comptime_var_state(value->data.x_optional); case ZigTypeIdErrorUnion: - if (value->data.x_err_union.err != nullptr) + if (value->data.x_err_union.error_set->data.x_err_set != nullptr) return false; assert(value->data.x_err_union.payload != nullptr); return can_mutate_comptime_var_state(value->data.x_err_union.payload); @@ -5048,9 +5074,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) { while (scope) { if (scope->id == ScopeIdVarDecl) { ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; - if (type_is_invalid(var_scope->var->value->type)) + if (type_is_invalid(var_scope->var->var_type)) return false; - if (can_mutate_comptime_var_state(var_scope->var->value)) + if (can_mutate_comptime_var_state(var_scope->var->const_value)) return false; } else if (scope->id == ScopeIdFnDef) { return true; @@ -5068,7 +5094,7 @@ uint32_t fn_eval_hash(Scope* scope) { while (scope) { if (scope->id == ScopeIdVarDecl) { ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; - result += hash_const_val(var_scope->var->value); + result += hash_const_val(var_scope->var->const_value); } else if (scope->id == ScopeIdFnDef) { ScopeFnDef *fn_scope = (ScopeFnDef *)scope; result += hash_ptr(fn_scope->fn_entry); @@ -5092,10 +5118,16 @@ bool fn_eval_eql(Scope *a, Scope *b) { if (a->id == ScopeIdVarDecl) { ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a; ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b; - if (a_var_scope->var->value->type != b_var_scope->var->value->type) - return false; - if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value)) + if (a_var_scope->var->var_type != b_var_scope->var->var_type) return false; + if (a_var_scope->var->var_type == a_var_scope->var->const_value->type && + b_var_scope->var->var_type == b_var_scope->var->const_value->type) + { + if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value)) + return false; + } else { + zig_panic("TODO comptime ptr reinterpret for fn_eval_eql"); + } } else if (a->id == ScopeIdFnDef) { ScopeFnDef *a_fn_scope = (ScopeFnDef *)a; ScopeFnDef *b_fn_scope = (ScopeFnDef *)b; @@ -5113,6 +5145,7 @@ bool fn_eval_eql(Scope *a, Scope *b) { return false; } +// Whether the type has bits at runtime. bool type_has_bits(ZigType *type_entry) { assert(type_entry); assert(!type_is_invalid(type_entry)); @@ -5120,6 +5153,65 @@ bool type_has_bits(ZigType *type_entry) { return !type_entry->zero_bits; } +// Whether you can infer the value based solely on the type. +OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { + assert(type_entry != nullptr); + Error err; + if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) + return OnePossibleValueInvalid; + switch (type_entry->id) { + case ZigTypeIdInvalid: + zig_unreachable(); + case ZigTypeIdOpaque: + case ZigTypeIdComptimeFloat: + case ZigTypeIdComptimeInt: + case ZigTypeIdMetaType: + case ZigTypeIdNamespace: + case ZigTypeIdBoundFn: + case ZigTypeIdArgTuple: + case ZigTypeIdOptional: + case ZigTypeIdFn: + case ZigTypeIdBool: + case ZigTypeIdFloat: + case ZigTypeIdPromise: + case ZigTypeIdErrorUnion: + return OnePossibleValueNo; + case ZigTypeIdUndefined: + case ZigTypeIdNull: + case ZigTypeIdVoid: + case ZigTypeIdUnreachable: + return OnePossibleValueYes; + case ZigTypeIdArray: + if (type_entry->data.array.len == 0) + return OnePossibleValueYes; + return type_has_one_possible_value(g, type_entry->data.array.child_type); + case ZigTypeIdStruct: + for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { + TypeStructField *field = &type_entry->data.structure.fields[i]; + switch (type_has_one_possible_value(g, field->type_entry)) { + case OnePossibleValueInvalid: + return OnePossibleValueInvalid; + case OnePossibleValueNo: + return OnePossibleValueNo; + case OnePossibleValueYes: + continue; + } + } + return OnePossibleValueYes; + case ZigTypeIdErrorSet: + case ZigTypeIdEnum: + case ZigTypeIdInt: + return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes; + case ZigTypeIdPointer: + return type_has_one_possible_value(g, type_entry->data.pointer.child_type); + case ZigTypeIdUnion: + if (type_entry->data.unionation.src_field_count > 1) + return OnePossibleValueNo; + return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry); + } + zig_unreachable(); +} + ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { Error err; if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) @@ -5574,6 +5666,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index) return false; return true; + case ConstPtrSpecialBaseErrorUnionCode: + if (a->data.x_ptr.data.base_err_union_code.err_union_val != + b->data.x_ptr.data.base_err_union_code.err_union_val && + a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs != + b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs) + { + return false; + } + return true; + case ConstPtrSpecialBaseErrorUnionPayload: + if (a->data.x_ptr.data.base_err_union_payload.err_union_val != + b->data.x_ptr.data.base_err_union_payload.err_union_val && + a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs != + b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs) + { + return false; + } + return true; + case ConstPtrSpecialBaseOptionalPayload: + if (a->data.x_ptr.data.base_optional_payload.optional_val != + b->data.x_ptr.data.base_optional_payload.optional_val && + a->data.x_ptr.data.base_optional_payload.optional_val->global_refs != + b->data.x_ptr.data.base_optional_payload.optional_val->global_refs) + { + return false; + } + return true; case ConstPtrSpecialHardCodedAddr: if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr) return false; @@ -5582,6 +5701,8 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { return true; case ConstPtrSpecialFunction: return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry; + case ConstPtrSpecialNull: + return true; } zig_unreachable(); } @@ -5750,7 +5871,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v } } -void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { +static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { assert(type_entry->id == ZigTypeIdPointer); if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { @@ -5763,6 +5884,9 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy zig_unreachable(); case ConstPtrSpecialRef: case ConstPtrSpecialBaseStruct: + case ConstPtrSpecialBaseErrorUnionCode: + case ConstPtrSpecialBaseErrorUnionPayload: + case ConstPtrSpecialBaseOptionalPayload: buf_appendf(buf, "*"); // TODO we need a source node for const_ptr_pointee because it can generate compile errors render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr)); @@ -5790,10 +5914,21 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name)); return; } + case ConstPtrSpecialNull: + buf_append_str(buf, "null"); + return; } zig_unreachable(); } +static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { + if (const_val->data.x_err_set == nullptr) { + buf_append_str(buf, "null"); + } else { + buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name)); + } +} + void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { switch (const_val->special) { case ConstValSpecialRuntime: @@ -5921,6 +6056,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { { if (get_codegen_ptr_type(const_val->type) != nullptr) return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type); + if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet) + return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type); if (const_val->data.x_optional) { render_const_value(g, buf, const_val->data.x_optional); } else { @@ -5958,11 +6095,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { case ZigTypeIdErrorUnion: { buf_appendf(buf, "%s(", buf_ptr(&type_entry->name)); - if (const_val->data.x_err_union.err == nullptr) { + ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; + if (err_set == nullptr) { render_const_value(g, buf, const_val->data.x_err_union.payload); } else { buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name), - buf_ptr(&const_val->data.x_err_union.err->name)); + buf_ptr(&err_set->name)); } buf_appendf(buf, ")"); return; @@ -5977,10 +6115,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { return; } case ZigTypeIdErrorSet: - { - buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name)); - return; - } + return render_const_val_err_set(g, buf, const_val, type_entry); case ZigTypeIdArgTuple: { buf_appendf(buf, "(args value)"); @@ -6172,6 +6307,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { // Canonicalize the array value as ConstArraySpecialNone void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { assert(const_val->type->id == ZigTypeIdArray); + if (const_val->special == ConstValSpecialUndef) { + const_val->special = ConstValSpecialStatic; + const_val->data.x_array.special = ConstArraySpecialUndef; + } switch (const_val->data.x_array.special) { case ConstArraySpecialNone: return; @@ -6215,17 +6354,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { } ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) { - assert(value->type); - ZigType *type_entry = value->type; - if (type_entry->id == ZigTypeIdArray) { - expand_undef_array(g, value); - return &value->data.x_array.data.s_none.parent; - } else if (type_entry->id == ZigTypeIdStruct) { - return &value->data.x_struct.parent; - } else if (type_entry->id == ZigTypeIdUnion) { - return &value->data.x_union.parent; - } - return nullptr; + return &value->parent; } static const ZigTypeId all_type_ids[] = { @@ -6453,7 +6582,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { resolve_top_level_decl(codegen, tld, false, nullptr); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; - ConstExprValue *var_value = tld_var->var->value; + ConstExprValue *var_value = tld_var->var->const_value; assert(var_value != nullptr); return var_value; } diff --git a/src/analyze.hpp b/src/analyze.hpp index efbc065a63..1bac15ebcc 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -81,7 +81,7 @@ ZigFn *scope_fn_entry(Scope *scope); ImportTableEntry *get_scope_import(Scope *scope); void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope); ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, - bool is_const, ConstExprValue *init_value, Tld *src_tld); + bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type); ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node); ZigFn *create_fn(CodeGen *g, AstNode *proto_node); ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value); @@ -222,6 +222,13 @@ enum ReqCompTime { }; ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); +enum OnePossibleValue { + OnePossibleValueInvalid, + OnePossibleValueNo, + OnePossibleValueYes, +}; +OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry); + Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, ConstExprValue *const_val, ZigType *wanted_type); diff --git a/src/ast_render.cpp b/src/ast_render.cpp index f7eb646e16..994ba5f5b1 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -233,8 +233,8 @@ static const char *node_type_str(NodeType node_type) { return "ErrorType"; case NodeTypeIfErrorExpr: return "IfErrorExpr"; - case NodeTypeTestExpr: - return "TestExpr"; + case NodeTypeIfOptional: + return "IfOptional"; case NodeTypeErrorSetDecl: return "ErrorSetDecl"; case NodeTypeCancel: @@ -387,7 +387,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) { if (node->data.if_err_expr.else_node) return statement_terminates_without_semicolon(node->data.if_err_expr.else_node); return node->data.if_err_expr.then_node->type == NodeTypeBlock; - case NodeTypeTestExpr: + case NodeTypeIfOptional: if (node->data.test_expr.else_node) return statement_terminates_without_semicolon(node->data.test_expr.else_node); return node->data.test_expr.then_node->type == NodeTypeBlock; @@ -974,7 +974,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { } break; } - case NodeTypeTestExpr: + case NodeTypeIfOptional: { fprintf(ar->f, "if ("); render_node_grouped(ar, node->data.test_expr.target_node); diff --git a/src/codegen.cpp b/src/codegen.cpp index 47f2aa103f..2f360735dd 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -313,6 +313,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char * static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name); static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name); static void generate_error_name_table(CodeGen *g); +static bool value_is_all_undef(ConstExprValue *const_val); +static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr); static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) { unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name)); @@ -461,6 +463,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag } } +static bool cc_want_sret_attr(CallingConvention cc) { + switch (cc) { + case CallingConventionNaked: + zig_unreachable(); + case CallingConventionC: + case CallingConventionCold: + case CallingConventionStdcall: + return true; + case CallingConventionAsync: + case CallingConventionUnspecified: + return false; + } + zig_unreachable(); +} + static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { if (fn_table_entry->llvm_value) return fn_table_entry->llvm_value; @@ -598,9 +615,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { } else if (type_is_codegen_pointer(return_type)) { addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) { - addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); - if (cc == CallingConventionC) { + addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); + if (cc_want_sret_attr(cc)) { addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias"); } init_gen_i = 1; @@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { assert(variable); assert(variable->value_ref); - if (!handle_is_ptr(variable->value->type)) { + if (!handle_is_ptr(variable->var_type)) { clear_debug_source_node(g); - gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref, - variable->align_bytes, false); + gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), + variable->value_ref, variable->align_bytes, false); } if (variable->decl_node) { @@ -2961,7 +2978,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, } static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, - IrInstructionPtrCast *instruction) + IrInstructionPtrCastGen *instruction) { ZigType *wanted_type = instruction->base.value.type; if (!type_has_bits(wanted_type)) { @@ -3149,11 +3166,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI } static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, - IrInstructionDeclVar *decl_var_instruction) + IrInstructionDeclVarGen *decl_var_instruction) { ZigVar *var = decl_var_instruction->var; - if (!type_has_bits(var->value->type)) + if (!type_has_bits(var->var_type)) return nullptr; if (var->ref_count == 0 && g->build_mode != BuildModeDebug) @@ -3161,34 +3178,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrInstruction *init_value = decl_var_instruction->init_value; - bool have_init_expr = false; - - ConstExprValue *const_val = &init_value->value; - if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic) - have_init_expr = true; + bool have_init_expr = !value_is_all_undef(&init_value->value); if (have_init_expr) { - assert(var->value->type == init_value->value.type); - ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false, + ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false, PtrLenSingle, var->align_bytes, 0, 0); LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value); gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val); - } else { - bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base); - if (want_safe) { - ZigType *usize = g->builtin_types.entry_usize; - uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref); - assert(size_bytes > 0); - - assert(var->align_bytes > 0); - - // memset uninitialized memory to 0xa - LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); - LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); - LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, ""); - LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); - ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false); - } + } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) { + uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes; + gen_undef_init(g, align_bytes, var->var_type, var->value_ref); } gen_var_debug_decl(g, var); @@ -3225,21 +3224,75 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); } +static bool value_is_all_undef(ConstExprValue *const_val) { + switch (const_val->special) { + case ConstValSpecialRuntime: + return false; + case ConstValSpecialUndef: + return true; + case ConstValSpecialStatic: + if (const_val->type->id == ZigTypeIdStruct) { + for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) { + if (!value_is_all_undef(&const_val->data.x_struct.fields[i])) + return false; + } + return true; + } else if (const_val->type->id == ZigTypeIdArray) { + switch (const_val->data.x_array.special) { + case ConstArraySpecialUndef: + return true; + case ConstArraySpecialBuf: + return false; + case ConstArraySpecialNone: + for (size_t i = 0; i < const_val->type->data.array.len; i += 1) { + if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i])) + return false; + } + return true; + } + zig_unreachable(); + } else { + return false; + } + } + zig_unreachable(); +} + +static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) { + assert(type_has_bits(value_type)); + uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref); + assert(size_bytes > 0); + assert(ptr_align_bytes > 0); + // memset uninitialized memory to 0xaa + LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); + LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); + LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, ""); + ZigType *usize = g->builtin_types.entry_usize; + LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); + ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false); +} + static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { - LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); - LLVMValueRef value = ir_llvm_value(g, instruction->value); - - assert(instruction->ptr->value.type->id == ZigTypeIdPointer); ZigType *ptr_type = instruction->ptr->value.type; + assert(ptr_type->id == ZigTypeIdPointer); + if (!type_has_bits(ptr_type)) + return nullptr; - gen_assign_raw(g, ptr, ptr_type, value); - + bool have_init_expr = !value_is_all_undef(&instruction->value->value); + if (have_init_expr) { + LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); + LLVMValueRef value = ir_llvm_value(g, instruction->value); + gen_assign_raw(g, ptr, ptr_type, value); + } else if (ir_want_runtime_safety(g, &instruction->base)) { + gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type, + ir_llvm_value(g, instruction->ptr)); + } return nullptr; } static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) { ZigVar *var = instruction->var; - if (type_has_bits(var->value->type)) { + if (type_has_bits(var->var_type)) { assert(var->value_ref); return var->value_ref; } else { @@ -3553,7 +3606,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab LLVMPositionBuilderAtEnd(g->builder, ok_block); } - LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, ""); + LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, + union_type->data.unionation.gen_union_index, ""); LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); return bitcasted_union_field_ptr; } @@ -3715,8 +3769,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR if (child_type->zero_bits) { return maybe_handle; } else { - bool maybe_is_ptr = type_is_codegen_pointer(child_type); - if (maybe_is_ptr) { + bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet; + if (is_scalar) { return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), ""); } else { LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); @@ -3731,17 +3785,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value)); } -static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, - IrInstructionUnwrapOptional *instruction) +static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable, + IrInstructionOptionalUnwrapPtr *instruction) { - ZigType *ptr_type = instruction->value->value.type; + ZigType *ptr_type = instruction->base_ptr->value.type; assert(ptr_type->id == ZigTypeIdPointer); ZigType *maybe_type = ptr_type->data.pointer.child_type; assert(maybe_type->id == ZigTypeIdOptional); ZigType *child_type = maybe_type->data.maybe.child_type; - LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); - LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); + LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr); if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) { + LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk"); LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail"); @@ -3755,8 +3809,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, if (child_type->zero_bits) { return nullptr; } else { - bool maybe_is_ptr = type_is_codegen_pointer(child_type); - if (maybe_is_ptr) { + bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet; + if (is_scalar) { return maybe_ptr; } else { LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); @@ -4174,7 +4228,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed) zig_unreachable(); } -static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) { +static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) { LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value); @@ -4189,18 +4243,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn assert(maybe_type->id == ZigTypeIdOptional); ZigType *child_type = maybe_type->data.maybe.child_type; - if (type_is_codegen_pointer(child_type)) { + if (!handle_is_ptr(maybe_type)) { LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, ""); } assert(instruction->tmp_ptr != nullptr); - assert(type_has_bits(instruction->type)); + assert(type_has_bits(child_type)); LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, ""); - gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val); + gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val); LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, ""); @@ -4351,6 +4405,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst assert(array_type->data.structure.is_slice); assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); + assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind); size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index; assert(ptr_index != SIZE_MAX); @@ -4540,12 +4595,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); } -static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) { - ZigType *ptr_type = instruction->value->value.type; +static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, + IrInstructionUnwrapErrCode *instruction) +{ + ZigType *ptr_type = instruction->err_union->value.type; assert(ptr_type->id == ZigTypeIdPointer); ZigType *err_union_type = ptr_type->data.pointer.child_type; ZigType *payload_type = err_union_type->data.error_union.payload_type; - LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); + LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union); LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); if (type_has_bits(payload_type)) { @@ -4556,7 +4613,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab } } -static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) { +static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, + IrInstructionUnwrapErrPayload *instruction) +{ + bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && + g->errors_by_index.length > 1; + if (!want_safety && !type_has_bits(instruction->base.value.type)) + return nullptr; ZigType *ptr_type = instruction->value->value.type; assert(ptr_type->id == ZigTypeIdPointer); ZigType *err_union_type = ptr_type->data.pointer.child_type; @@ -4568,7 +4631,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu return err_union_handle; } - if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) { + if (want_safety) { LLVMValueRef err_val; if (type_has_bits(payload_type)) { LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); @@ -4607,7 +4670,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I } LLVMValueRef payload_val = ir_llvm_value(g, instruction->value); - if (type_is_codegen_pointer(child_type)) { + if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) { return payload_val; } @@ -5184,12 +5247,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdToBytes: case IrInstructionIdEnumToInt: case IrInstructionIdCheckRuntimeScope: + case IrInstructionIdDeclVarSrc: + case IrInstructionIdPtrCastSrc: + case IrInstructionIdCmpxchgSrc: zig_unreachable(); + case IrInstructionIdDeclVarGen: + return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction); case IrInstructionIdReturn: return ir_render_return(g, executable, (IrInstructionReturn *)instruction); - case IrInstructionIdDeclVar: - return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction); case IrInstructionIdBinOp: return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction); case IrInstructionIdCast: @@ -5220,8 +5286,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_asm(g, executable, (IrInstructionAsm *)instruction); case IrInstructionIdTestNonNull: return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction); - case IrInstructionIdUnwrapOptional: - return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction); + case IrInstructionIdOptionalUnwrapPtr: + return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction); case IrInstructionIdClz: return ir_render_clz(g, executable, (IrInstructionClz *)instruction); case IrInstructionIdCtz: @@ -5236,8 +5302,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_ref(g, executable, (IrInstructionRef *)instruction); case IrInstructionIdErrName: return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction); - case IrInstructionIdCmpxchg: - return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction); + case IrInstructionIdCmpxchgGen: + return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction); case IrInstructionIdFence: return ir_render_fence(g, executable, (IrInstructionFence *)instruction); case IrInstructionIdTruncate: @@ -5278,8 +5344,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction); case IrInstructionIdUnionInit: return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction); - case IrInstructionIdPtrCast: - return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction); + case IrInstructionIdPtrCastGen: + return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction); case IrInstructionIdBitCast: return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction); case IrInstructionIdWidenOrShorten: @@ -5377,6 +5443,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index); static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index); static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val); +static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val); +static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val); +static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val); static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) { switch (parent->id) { @@ -5387,6 +5456,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent case ConstParentIdStruct: return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val, parent->data.p_struct.field_index); + case ConstParentIdErrUnionCode: + return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val); + case ConstParentIdErrUnionPayload: + return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val); + case ConstParentIdOptionalPayload: + return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val); case ConstParentIdArray: return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val, parent->data.p_array.elem_index); @@ -5402,7 +5477,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) { expand_undef_array(g, array_const_val); - ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent; + ConstParent *parent = &array_const_val->parent; LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent); LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr))); @@ -5427,7 +5502,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar } static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) { - ConstParent *parent = &struct_const_val->data.x_struct.parent; + ConstParent *parent = &struct_const_val->parent; LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent); ZigType *u32 = g->builtin_types.entry_u32; @@ -5438,8 +5513,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s return LLVMConstInBoundsGEP(base_ptr, indices, 2); } +static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) { + ConstParent *parent = &err_union_const_val->parent; + LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent); + + ZigType *u32 = g->builtin_types.entry_u32; + LLVMValueRef indices[] = { + LLVMConstNull(u32->type_ref), + LLVMConstInt(u32->type_ref, err_union_err_index, false), + }; + return LLVMConstInBoundsGEP(base_ptr, indices, 2); +} + +static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) { + ConstParent *parent = &err_union_const_val->parent; + LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent); + + ZigType *u32 = g->builtin_types.entry_u32; + LLVMValueRef indices[] = { + LLVMConstNull(u32->type_ref), + LLVMConstInt(u32->type_ref, err_union_payload_index, false), + }; + return LLVMConstInBoundsGEP(base_ptr, indices, 2); +} + +static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) { + ConstParent *parent = &optional_const_val->parent; + LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent); + + ZigType *u32 = g->builtin_types.entry_u32; + LLVMValueRef indices[] = { + LLVMConstNull(u32->type_ref), + LLVMConstInt(u32->type_ref, maybe_child_index, false), + }; + return LLVMConstInBoundsGEP(base_ptr, indices, 2); +} + static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) { - ConstParent *parent = &union_const_val->data.x_union.parent; + ConstParent *parent = &union_const_val->parent; LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent); ZigType *u32 = g->builtin_types.entry_u32; @@ -5609,6 +5720,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con render_const_val_global(g, const_val, ""); return ptr_val; } + case ConstPtrSpecialBaseErrorUnionCode: + { + render_const_val_global(g, const_val, name); + ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val; + assert(err_union_const_val->type->id == ZigTypeIdErrorUnion); + if (err_union_const_val->type->zero_bits) { + // make this a null pointer + ZigType *usize = g->builtin_types.entry_usize; + const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), + const_val->type->type_ref); + render_const_val_global(g, const_val, ""); + return const_val->global_refs->llvm_value; + } + LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val); + LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); + const_val->global_refs->llvm_value = ptr_val; + render_const_val_global(g, const_val, ""); + return ptr_val; + } + case ConstPtrSpecialBaseErrorUnionPayload: + { + render_const_val_global(g, const_val, name); + ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val; + assert(err_union_const_val->type->id == ZigTypeIdErrorUnion); + if (err_union_const_val->type->zero_bits) { + // make this a null pointer + ZigType *usize = g->builtin_types.entry_usize; + const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), + const_val->type->type_ref); + render_const_val_global(g, const_val, ""); + return const_val->global_refs->llvm_value; + } + LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val); + LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); + const_val->global_refs->llvm_value = ptr_val; + render_const_val_global(g, const_val, ""); + return ptr_val; + } + case ConstPtrSpecialBaseOptionalPayload: + { + render_const_val_global(g, const_val, name); + ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val; + assert(optional_const_val->type->id == ZigTypeIdOptional); + if (optional_const_val->type->zero_bits) { + // make this a null pointer + ZigType *usize = g->builtin_types.entry_usize; + const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), + const_val->type->type_ref); + render_const_val_global(g, const_val, ""); + return const_val->global_refs->llvm_value; + } + LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val); + LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); + const_val->global_refs->llvm_value = ptr_val; + render_const_val_global(g, const_val, ""); + return ptr_val; + } case ConstPtrSpecialHardCodedAddr: { render_const_val_global(g, const_val, name); @@ -5621,10 +5789,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con } case ConstPtrSpecialFunction: return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref); + case ConstPtrSpecialNull: + return LLVMConstNull(const_val->type->type_ref); } zig_unreachable(); } +static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) { + uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value; + return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false); +} + static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) { Error err; @@ -5644,9 +5819,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c case ZigTypeIdInt: return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); case ZigTypeIdErrorSet: - assert(const_val->data.x_err_set != nullptr); - return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, - const_val->data.x_err_set->value, false); + return gen_const_val_err_set(g, const_val, name); case ZigTypeIdFloat: switch (type_entry->data.floating.bit_count) { case 16: @@ -5680,6 +5853,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false); } else if (type_is_codegen_pointer(child_type)) { return gen_const_val_ptr(g, const_val, name); + } else if (child_type->id == ZigTypeIdErrorSet) { + return gen_const_val_err_set(g, const_val, name); } else { LLVMValueRef child_val; LLVMValueRef maybe_val; @@ -5914,7 +6089,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c ZigType *err_set_type = type_entry->data.error_union.err_set_type; if (!type_has_bits(payload_type)) { assert(type_has_bits(err_set_type)); - uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0; + ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; + uint64_t value = (err_set == nullptr) ? 0 : err_set->value; return LLVMConstInt(g->err_tag_type->type_ref, value, false); } else if (!type_has_bits(err_set_type)) { assert(type_has_bits(payload_type)); @@ -5923,8 +6099,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c LLVMValueRef err_tag_value; LLVMValueRef err_payload_value; bool make_unnamed_struct; - if (const_val->data.x_err_union.err) { - err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false); + ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; + if (err_set != nullptr) { + err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false); err_payload_value = LLVMConstNull(payload_type->type_ref); make_unnamed_struct = false; } else { @@ -6130,10 +6307,13 @@ static void do_code_gen(CodeGen *g) { TldVar *tld_var = g->global_vars.at(i); ZigVar *var = tld_var->var; - if (var->value->type->id == ZigTypeIdComptimeFloat) { + if (var->var_type->id == ZigTypeIdComptimeFloat) { // Generate debug info for it but that's it. - ConstExprValue *const_val = var->value; + ConstExprValue *const_val = var->const_value; assert(const_val->special != ConstValSpecialRuntime); + if (const_val->type != var->var_type) { + zig_panic("TODO debug info for var with ptr casted value"); + } ZigType *var_type = g->builtin_types.entry_f128; ConstExprValue coerced_value; coerced_value.special = ConstValSpecialStatic; @@ -6144,10 +6324,13 @@ static void do_code_gen(CodeGen *g) { continue; } - if (var->value->type->id == ZigTypeIdComptimeInt) { + if (var->var_type->id == ZigTypeIdComptimeInt) { // Generate debug info for it but that's it. - ConstExprValue *const_val = var->value; + ConstExprValue *const_val = var->const_value; assert(const_val->special != ConstValSpecialRuntime); + if (const_val->type != var->var_type) { + zig_panic("TODO debug info for var with ptr casted value"); + } size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint); if (bits_needed < 8) { bits_needed = 8; @@ -6158,7 +6341,7 @@ static void do_code_gen(CodeGen *g) { continue; } - if (!type_has_bits(var->value->type)) + if (!type_has_bits(var->var_type)) continue; assert(var->decl_node); @@ -6167,9 +6350,9 @@ static void do_code_gen(CodeGen *g) { if (var->linkage == VarLinkageExternal) { LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name)); if (existing_llvm_var) { - global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0)); + global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0)); } else { - global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name)); + global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name)); // TODO debug info for the extern variable LLVMSetLinkage(global_value, LLVMExternalLinkage); @@ -6180,9 +6363,9 @@ static void do_code_gen(CodeGen *g) { } else { bool exported = (var->linkage == VarLinkageExport); const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported)); - render_const_val(g, var->value, mangled_name); - render_const_val_global(g, var->value, mangled_name); - global_value = var->value->global_refs->llvm_global; + render_const_val(g, var->const_value, mangled_name); + render_const_val_global(g, var->const_value, mangled_name); + global_value = var->const_value->global_refs->llvm_global; if (exported) { LLVMSetLinkage(global_value, LLVMExternalLinkage); @@ -6194,8 +6377,10 @@ static void do_code_gen(CodeGen *g) { LLVMSetAlignment(global_value, var->align_bytes); // TODO debug info for function pointers - if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) { - gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type); + // Here we use const_value->type because that's the type of the llvm global, + // which we const ptr cast upon use to whatever it needs to be. + if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) { + gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type); } LLVMSetGlobalConstant(global_value, var->gen_is_const); @@ -6281,8 +6466,8 @@ static void do_code_gen(CodeGen *g) { } else if (instruction->id == IrInstructionIdErrWrapCode) { IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction; slot = &err_wrap_code_instruction->tmp_ptr; - } else if (instruction->id == IrInstructionIdCmpxchg) { - IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction; + } else if (instruction->id == IrInstructionIdCmpxchgGen) { + IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction; slot = &cmpxchg_instruction->tmp_ptr; } else { zig_unreachable(); @@ -6304,12 +6489,12 @@ static void do_code_gen(CodeGen *g) { for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) { ZigVar *var = fn_table_entry->variable_list.at(var_i); - if (!type_has_bits(var->value->type)) { + if (!type_has_bits(var->var_type)) { continue; } if (ir_get_var_is_comptime(var)) continue; - switch (type_requires_comptime(g, var->value->type)) { + switch (type_requires_comptime(g, var->var_type)) { case ReqCompTimeInvalid: zig_unreachable(); case ReqCompTimeYes: @@ -6319,11 +6504,11 @@ static void do_code_gen(CodeGen *g) { } if (var->src_arg_index == SIZE_MAX) { - var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); + var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1), - var->value->type->di_type, !g->strip_debug_symbols, 0); + var->var_type->di_type, !g->strip_debug_symbols, 0); } else if (is_c_abi) { fn_walk_var.data.vars.var = var; @@ -6333,16 +6518,16 @@ static void do_code_gen(CodeGen *g) { ZigType *gen_type; FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; - if (handle_is_ptr(var->value->type)) { + if (handle_is_ptr(var->var_type)) { if (gen_info->is_byval) { - gen_type = var->value->type; + gen_type = var->var_type; } else { gen_type = gen_info->type; } var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index); } else { - gen_type = var->value->type; - var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); + gen_type = var->var_type; + var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); } if (var->decl_node) { var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), @@ -7458,9 +7643,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i]; this_val->special = ConstValSpecialStatic; this_val->type = struct_type; - this_val->data.x_struct.parent.id = ConstParentIdArray; - this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array; - this_val->data.x_struct.parent.data.p_array.elem_index = i; + this_val->parent.id = ConstParentIdArray; + this_val->parent.data.p_array.array_val = test_fn_array; + this_val->parent.data.p_array.elem_index = i; this_val->data.x_struct.fields = create_const_vals(2); ConstExprValue *name_field = &this_val->data.x_struct.fields[0]; diff --git a/src/ir.cpp b/src/ir.cpp index b184252a2e..06eb4a47f1 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -167,6 +167,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ ZigType *dest_type, IrInstruction *dest_type_src); static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); +static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { assert(get_src_ptr_type(const_val->type) != nullptr); @@ -178,15 +179,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c case ConstPtrSpecialRef: result = const_val->data.x_ptr.data.ref.pointee; break; - case ConstPtrSpecialBaseArray: - expand_undef_array(g, const_val->data.x_ptr.data.base_array.array_val); - result = &const_val->data.x_ptr.data.base_array.array_val->data.x_array.data.s_none.elements[ - const_val->data.x_ptr.data.base_array.elem_index]; + case ConstPtrSpecialBaseArray: { + ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val; + expand_undef_array(g, array_val); + result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index]; break; + } case ConstPtrSpecialBaseStruct: result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[ const_val->data.x_ptr.data.base_struct.field_index]; break; + case ConstPtrSpecialBaseErrorUnionCode: + result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set; + break; + case ConstPtrSpecialBaseErrorUnionPayload: + result = const_val->data.x_ptr.data.base_err_union_payload.err_union_val->data.x_err_union.payload; + break; + case ConstPtrSpecialBaseOptionalPayload: + result = const_val->data.x_ptr.data.base_optional_payload.optional_val->data.x_optional; + break; + case ConstPtrSpecialNull: + result = const_val; + break; case ConstPtrSpecialHardCodedAddr: zig_unreachable(); case ConstPtrSpecialDiscard: @@ -198,6 +212,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c return result; } +static bool is_opt_err_set(ZigType *ty) { + return ty->id == ZigTypeIdErrorSet || + (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet); +} + static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { if (a == b) return true; @@ -208,15 +227,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr) return true; - return false; -} + if (is_opt_err_set(a) && is_opt_err_set(b)) + return true; -ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { - ConstExprValue *result = const_ptr_pointee_unchecked(g, const_val); - if (const_val->type->id == ZigTypeIdPointer) { - assert(types_have_same_zig_comptime_repr(const_val->type->data.pointer.child_type, result->type)); - } - return result; + return false; } static bool ir_should_inline(IrExecutable *exec, Scope *scope) { @@ -305,6 +319,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) { return new_bb; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarSrc *) { + return IrInstructionIdDeclVarSrc; +} + +static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarGen *) { + return IrInstructionIdDeclVarGen; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) { return IrInstructionIdCondBr; } @@ -337,10 +359,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) { return IrInstructionIdBinOp; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) { - return IrInstructionIdDeclVar; -} - static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) { return IrInstructionIdExport; } @@ -449,8 +467,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) { return IrInstructionIdTestNonNull; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) { - return IrInstructionIdUnwrapOptional; +static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) { + return IrInstructionIdOptionalUnwrapPtr; } static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) { @@ -517,8 +535,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) { return IrInstructionIdEmbedFile; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) { - return IrInstructionIdCmpxchg; +static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) { + return IrInstructionIdCmpxchgSrc; +} + +static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) { + return IrInstructionIdCmpxchgGen; } static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) { @@ -649,8 +671,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) return IrInstructionIdTestComptime; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) { - return IrInstructionIdPtrCast; +static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) { + return IrInstructionIdPtrCastSrc; +} + +static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) { + return IrInstructionIdPtrCastGen; } static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) { @@ -915,7 +941,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so ir_ref_instruction(condition, irb->current_basic_block); ir_ref_bb(then_block); ir_ref_bb(else_block); - if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block); + if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); return &cond_br_instruction->base; } @@ -931,16 +957,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou return &return_instruction->base; } -static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node, - ZigType *type_entry) -{ - assert(type_entry); - IrInstructionConst *const_instruction = ir_create_instruction(irb, scope, source_node); - const_instruction->base.value.type = type_entry; - const_instruction->base.value.special = ConstValSpecialStatic; - return &const_instruction->base; -} - static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) { IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); const_instruction->base.value.type = irb->codegen->builtin_types.entry_void; @@ -1188,14 +1204,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc call_instruction->async_allocator = async_allocator; call_instruction->new_stack = new_stack; - if (fn_ref) - ir_ref_instruction(fn_ref, irb->current_basic_block); + if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block); for (size_t i = 0; i < arg_count; i += 1) ir_ref_instruction(args[i], irb->current_basic_block); - if (async_allocator) - ir_ref_instruction(async_allocator, irb->current_basic_block); - if (new_stack != nullptr) - ir_ref_instruction(new_stack, irb->current_basic_block); + if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block); + if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block); return &call_instruction->base; } @@ -1280,7 +1293,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, container_init_list_instruction->item_count = item_count; container_init_list_instruction->items = items; - ir_ref_instruction(container_type, irb->current_basic_block); + if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block); for (size_t i = 0; i < item_count; i += 1) { ir_ref_instruction(items[i], irb->current_basic_block); } @@ -1355,10 +1368,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node, +static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value) { - IrInstructionDeclVar *decl_var_instruction = ir_build_instruction(irb, scope, source_node); + IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction(irb, scope, source_node); decl_var_instruction->base.value.special = ConstValSpecialStatic; decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void; decl_var_instruction->var = var; @@ -1366,13 +1379,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s decl_var_instruction->align_value = align_value; decl_var_instruction->init_value = init_value; - if (var_type) ir_ref_instruction(var_type, irb->current_basic_block); - if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); + if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block); + if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); ir_ref_instruction(init_value, irb->current_basic_block); return &decl_var_instruction->base; } +static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction, + ZigVar *var, IrInstruction *init_value) +{ + IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction(&ira->new_irb, + source_instruction->scope, source_instruction->source_node); + decl_var_instruction->base.value.special = ConstValSpecialStatic; + decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void; + decl_var_instruction->var = var; + decl_var_instruction->init_value = init_value; + + ir_ref_instruction(init_value, ira->new_irb.current_basic_block); + + return &decl_var_instruction->base; +} + static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name, IrInstruction *target, IrInstruction *linkage) { @@ -1542,14 +1570,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } -static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value, - bool safety_check_on) +static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *base_ptr, bool safety_check_on) { - IrInstructionUnwrapOptional *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; + IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base_ptr = base_ptr; instruction->safety_check_on = safety_check_on; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(base_ptr, irb->current_basic_block); return &instruction->base; } @@ -1765,13 +1793,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value, - IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, +static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, IrInstruction *success_order_value, IrInstruction *failure_order_value, - bool is_weak, - ZigType *type, AtomicOrder success_order, AtomicOrder failure_order) + bool is_weak) { - IrInstructionCmpxchg *instruction = ir_build_instruction(irb, scope, source_node); + IrInstructionCmpxchgSrc *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; instruction->ptr = ptr; instruction->cmp_value = cmp_value; @@ -1779,16 +1806,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so instruction->success_order_value = success_order_value; instruction->failure_order_value = failure_order_value; instruction->is_weak = is_weak; - instruction->type = type; - instruction->success_order = success_order; - instruction->failure_order = failure_order; - if (type_value != nullptr) ir_ref_instruction(type_value, irb->current_basic_block); + ir_ref_instruction(type_value, irb->current_basic_block); ir_ref_instruction(ptr, irb->current_basic_block); ir_ref_instruction(cmp_value, irb->current_basic_block); ir_ref_instruction(new_value, irb->current_basic_block); - if (type_value != nullptr) ir_ref_instruction(success_order_value, irb->current_basic_block); - if (type_value != nullptr) ir_ref_instruction(failure_order_value, irb->current_basic_block); + ir_ref_instruction(success_order_value, irb->current_basic_block); + ir_ref_instruction(failure_order_value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, + IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, + AtomicOrder success_order, AtomicOrder failure_order, bool is_weak) +{ + IrInstructionCmpxchgGen *instruction = ir_build_instruction(&ira->new_irb, + source_instruction->scope, source_instruction->source_node); + instruction->ptr = ptr; + instruction->cmp_value = cmp_value; + instruction->new_value = new_value; + instruction->success_order = success_order; + instruction->failure_order = failure_order; + instruction->is_weak = is_weak; + + ir_ref_instruction(ptr, ira->new_irb.current_basic_block); + ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block); + ir_ref_instruction(new_value, ira->new_irb.current_basic_block); return &instruction->base; } @@ -2060,12 +2104,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s } static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *value) + IrInstruction *err_union) { IrInstructionUnwrapErrCode *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; + instruction->err_union = err_union; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_instruction(err_union, irb->current_basic_block); return &instruction->base; } @@ -2115,20 +2159,33 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo return &instruction->base; } -static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, +static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *ptr) { - IrInstructionPtrCast *instruction = ir_build_instruction( + IrInstructionPtrCastSrc *instruction = ir_build_instruction( irb, scope, source_node); instruction->dest_type = dest_type; instruction->ptr = ptr; - if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); + ir_ref_instruction(dest_type, irb->current_basic_block); ir_ref_instruction(ptr, irb->current_basic_block); return &instruction->base; } +static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction, + ZigType *ptr_type, IrInstruction *ptr) +{ + IrInstructionPtrCastGen *instruction = ir_build_instruction( + &ira->new_irb, source_instruction->scope, source_instruction->source_node); + instruction->base.value.type = ptr_type; + instruction->ptr = ptr; + + ir_ref_instruction(ptr, ira->new_irb.current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *value) { @@ -2807,10 +2864,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o Scope *defer_expr_scope = defer_node->data.defer.expr_scope; IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); if (defer_expr_value != irb->codegen->invalid_instruction) { - if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == ZigTypeIdUnreachable) { + if (defer_expr_value->value.type != nullptr && + defer_expr_value->value.type->id == ZigTypeIdUnreachable) + { is_noreturn = true; } else { - ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value)); + ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, + defer_expr_value)); } } } @@ -3065,7 +3125,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s variable_entry->mem_slot_index = SIZE_MAX; variable_entry->is_comptime = is_comptime; variable_entry->src_arg_index = SIZE_MAX; - variable_entry->value = create_const_vals(1); + variable_entry->const_value = create_const_vals(1); if (is_comptime != nullptr) { is_comptime->ref_count += 1; @@ -3080,20 +3140,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s ErrorMsg *msg = add_node_error(codegen, node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); - variable_entry->value->type = codegen->builtin_types.entry_invalid; + variable_entry->var_type = codegen->builtin_types.entry_invalid; } else { ZigType *type; if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) { add_node_error(codegen, node, buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); - variable_entry->value->type = codegen->builtin_types.entry_invalid; + variable_entry->var_type = codegen->builtin_types.entry_invalid; } else { Tld *tld = find_decl(codegen, parent_scope, name); if (tld != nullptr) { ErrorMsg *msg = add_node_error(codegen, node, buf_sprintf("redefinition of '%s'", buf_ptr(name))); add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); - variable_entry->value->type = codegen->builtin_types.entry_invalid; + variable_entry->var_type = codegen->builtin_types.entry_invalid; } } } @@ -3156,7 +3216,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode scope_block->incoming_blocks = &incoming_blocks; scope_block->incoming_values = &incoming_values; scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); - scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope)); + scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, + ir_should_inline(irb->exec, parent_scope)); } bool is_continuation_unreachable = false; @@ -3174,9 +3235,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode // defer starts a new scope child_scope = statement_node->data.defer.child_scope; assert(child_scope); - } else if (statement_value->id == IrInstructionIdDeclVar) { + } else if (statement_value->id == IrInstructionIdDeclVarSrc) { // variable declarations start a new scope - IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value; + IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value; child_scope = decl_var_instruction->var->child_scope; } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) { // this statement's value must be void @@ -3331,7 +3392,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); } -static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) { +static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); AstNode *op1_node = node->data.bin_op_expr.op1; @@ -3365,7 +3426,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, ok_block); - IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false); + IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false); IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); IrBasicBlock *after_ok_block = irb->current_basic_block; ir_build_br(irb, parent_scope, node, end_block, is_comptime); @@ -3483,7 +3544,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) case BinOpTypeMergeErrorSets: return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets); case BinOpTypeUnwrapOptional: - return ir_gen_maybe_ok_or(irb, scope, node); + return ir_gen_orelse(irb, scope, node); case BinOpTypeErrorUnion: return ir_gen_error_union(irb, scope, node); } @@ -3542,6 +3603,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, buf_ptr(variable_name))); return irb->codegen->invalid_instruction; } + assert(err == ErrorPrimitiveTypeNotFound); } else { IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type); if (lval == LValPtr) { @@ -3904,9 +3966,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo if (arg5_value == irb->codegen->invalid_instruction) return arg5_value; - IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value, - arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), - nullptr, AtomicOrderUnordered, AtomicOrderUnordered); + IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, + arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak)); return ir_lval_wrap(irb, scope, cmpxchg, lval); } case BuiltinFnIdFence: @@ -4346,7 +4407,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo if (arg1_value == irb->codegen->invalid_instruction) return arg1_value; - IrInstruction *ptr_cast = ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value); + IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, ptr_cast, lval); } case BuiltinFnIdBitCast: @@ -4784,7 +4845,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node } } - IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr); + IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, + is_async, async_allocator, nullptr); return ir_lval_wrap(irb, scope, fn_call, lval); } @@ -4793,7 +4855,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); if (condition == irb->codegen->invalid_instruction) - return condition; + return irb->codegen->invalid_instruction; IrInstruction *is_comptime; if (ir_should_inline(irb->exec, scope)) { @@ -4816,7 +4878,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope); if (then_expr_result == irb->codegen->invalid_instruction) - return then_expr_result; + return irb->codegen->invalid_instruction; IrBasicBlock *after_then_block = irb->current_basic_block; if (!instr_is_unreachable(then_expr_result)) ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); @@ -4826,7 +4888,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode if (else_node) { else_expr_result = ir_gen_node(irb, else_node, subexpr_scope); if (else_expr_result == irb->codegen->invalid_instruction) - return else_expr_result; + return irb->codegen->invalid_instruction; } else { else_expr_result = ir_build_const_void(irb, scope, node); } @@ -4927,7 +4989,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode ptr_len, align_value, bit_offset_start, host_int_bytes); } -static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node, +static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node, LVal lval) { IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr); @@ -5053,11 +5115,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime); ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol, is_const, is_const, is_shadowable, is_comptime); - // we detect IrInstructionIdDeclVar in gen_block to make sure the next node + // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node // is inside var->child_scope if (!is_extern && !variable_declaration->expr) { - var->value->type = irb->codegen->builtin_types.entry_invalid; + var->var_type = irb->codegen->builtin_types.entry_invalid; add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized")); return irb->codegen->invalid_instruction; } @@ -5084,7 +5146,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod if (init_value == irb->codegen->invalid_instruction) return init_value; - return ir_build_var_decl(irb, scope, node, var, type_instruction, align_value, init_value); + return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value); } static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) { @@ -5140,7 +5202,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n err_val_ptr, false); IrInstruction *var_value = node->data.while_expr.var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value); - ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value); + ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value); } ZigList incoming_values = {0}; @@ -5180,7 +5242,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n true, false, false, is_comptime); Scope *err_scope = err_var->child_scope; IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); - ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value); + ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value); IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope); if (else_result == irb->codegen->invalid_instruction) @@ -5220,10 +5282,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n } ir_set_cursor_at_end_and_append_block(irb, body_block); - IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false); + IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false); IrInstruction *var_value = node->data.while_expr.var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value); - ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value); + ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value); ZigList incoming_values = {0}; ZigList incoming_blocks = {0}; @@ -5380,7 +5442,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo Scope *child_scope = elem_var->child_scope; IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); - ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value); + ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value); IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var); AstNode *index_var_source_node; @@ -5398,7 +5460,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize); IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); - ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero); + ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero); IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var); @@ -5622,8 +5684,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile); } -static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeTestExpr); +static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) { + assert(node->type == NodeTypeIfOptional); Buf *var_symbol = node->data.test_expr.var_symbol; AstNode *expr_node = node->data.test_expr.target_node; @@ -5661,9 +5723,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no ZigVar *var = ir_create_var(irb, node, subexpr_scope, var_symbol, is_const, is_const, is_shadowable, is_comptime); - IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, subexpr_scope, node, maybe_val_ptr, false); + IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false); IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); - ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); + ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value); var_scope = var->child_scope; } else { var_scope = subexpr_scope; @@ -5738,7 +5800,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false); IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); - ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); + ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value); var_scope = var->child_scope; } else { var_scope = subexpr_scope; @@ -5763,7 +5825,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * err_symbol, is_const, is_const, is_shadowable, is_comptime); IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr); - ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); + ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value); err_var_scope = var->child_scope; } else { err_var_scope = subexpr_scope; @@ -5818,7 +5880,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); } IrInstruction *var_type = nullptr; // infer the type - ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, nullptr, var_value); + ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value); } else { child_scope = scope; } @@ -6228,7 +6290,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true); } -static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) { +static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeUnwrapErrorExpr); AstNode *op1_node = node->data.unwrap_err_expr.op1; @@ -6242,7 +6304,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); return irb->codegen->invalid_instruction; } - return ir_gen_err_assert_ok(irb, parent_scope, node, op1_node, LValNone); + return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone); } @@ -6276,7 +6338,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN is_const, is_const, is_shadowable, is_comptime); err_scope = var->child_scope; IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); - ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val); + ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val); } else { err_scope = parent_scope; } @@ -6312,7 +6374,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope; if (need_comma) buf_append_char(name, ','); - render_const_value(codegen, name, var_scope->var->value); + // TODO: const ptr reinterpret here to make the var type agree with the value? + render_const_value(codegen, name, var_scope->var->const_value); return true; } @@ -6562,7 +6625,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010 // TODO relies on Zig not re-ordering fields - IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst); + IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst); IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, @@ -6640,7 +6703,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void)); // TODO relies on Zig not re-ordering fields - IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst); + IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst); IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, @@ -6756,7 +6819,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst); IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type); ir_build_await_bookkeeping(irb, scope, node, promise_result_type); - ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value); + ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value); IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var); ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr); IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle); @@ -7050,7 +7113,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop if (maybe_ptr == irb->codegen->invalid_instruction) return irb->codegen->invalid_instruction; - IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true); + IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true); if (lval == LValPtr) return unwrapped_ptr; @@ -7074,8 +7137,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval); case NodeTypeIfErrorExpr: return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval); - case NodeTypeTestExpr: - return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval); + case NodeTypeIfOptional: + return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval); case NodeTypeSwitchExpr: return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval); case NodeTypeCompTime: @@ -7093,7 +7156,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop case NodeTypeSliceExpr: return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval); case NodeTypeUnwrapErrorExpr: - return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval); + return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval); case NodeTypeContainerDecl: return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); case NodeTypeFnProto: @@ -7152,6 +7215,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec ir_ref_bb(irb->current_basic_block); ZigFn *fn_entry = exec_fn_entry(irb->exec); + bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; IrInstruction *coro_id; IrInstruction *u8_ptr_type; @@ -7172,27 +7236,27 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type); IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type); // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa - ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef); + ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef); coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var); ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false); IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node); IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node, get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise)); - ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value); + ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value); irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var); u8_ptr_type = ir_build_const_type(irb, coro_scope, node, get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); - IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr); + IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr); coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr); coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false); IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node); - ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size); + ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size); IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node, ImplicitAllocatorIdArg); irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false); - ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr); + ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr); Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name); IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr); @@ -7208,7 +7272,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec ir_build_return(irb, coro_scope, node, undef); ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); - IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr); + IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr); irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr); Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); @@ -7286,8 +7350,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, false, false, PtrLenUnknown, 0, 0, 0)); IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); - IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr); - IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, + IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr); + IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, irb->exec->coro_result_field_ptr); IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node, fn_entry->type_entry->data.fn.fn_type_id.return_type); @@ -7303,7 +7367,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec // Before we destroy the coroutine frame, we need to load the target promise into // a register or local variable which does not get spilled into the frame, // otherwise llvm tries to access memory inside the destroyed frame. - IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node, + IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, irb->exec->await_handle_var_ptr, false); IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr); ir_build_br(irb, scope, node, check_free_block, const_bool_false); @@ -7338,7 +7402,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node, get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, false, false, PtrLenUnknown, 0, 0, 0)); - IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe); + IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe); IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var); IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr); @@ -7435,7 +7499,7 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal return val; } -static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) { +static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) { IrBasicBlock *bb = exec->basic_block_list.at(0); for (size_t i = 0; i < bb->instruction_list.length; i += 1) { IrInstruction *instruction = bb->instruction_list.at(i); @@ -7445,16 +7509,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) if (value->value.special == ConstValSpecialRuntime) { exec_add_error_node(codegen, exec, value->source_node, buf_sprintf("unable to evaluate constant expression")); - return codegen->invalid_instruction; + return &codegen->invalid_instruction->value; } - return value; + return &value->value; } else if (ir_has_side_effects(instruction)) { exec_add_error_node(codegen, exec, instruction->source_node, buf_sprintf("unable to evaluate constant expression")); - return codegen->invalid_instruction; + return &codegen->invalid_instruction->value; } } - return codegen->invalid_instruction; + return &codegen->invalid_instruction->value; } static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) { @@ -8768,13 +8832,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT size_t errors_count = 0; ZigType *err_set_type = nullptr; if (prev_inst->value.type->id == ZigTypeIdErrorSet) { + if (!resolve_inferred_error_set(ira->codegen, prev_inst->value.type, prev_inst->source_node)) { + return ira->codegen->builtin_types.entry_invalid; + } if (type_is_global_error_set(prev_inst->value.type)) { err_set_type = ira->codegen->builtin_types.entry_global_error_set; } else { err_set_type = prev_inst->value.type; - if (!resolve_inferred_error_set(ira->codegen, err_set_type, prev_inst->source_node)) { - return ira->codegen->builtin_types.entry_invalid; - } update_errors_helper(ira->codegen, &errors, &errors_count); for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { @@ -8933,6 +8997,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT if (prev_type->id == ZigTypeIdArray) { convert_to_const_slice = true; } + if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) { + return ira->codegen->builtin_types.entry_invalid; + } if (type_is_global_error_set(cur_type)) { err_set_type = ira->codegen->builtin_types.entry_global_error_set; continue; @@ -8940,9 +9007,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) { continue; } - if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) { - return ira->codegen->builtin_types.entry_invalid; - } update_errors_helper(ira->codegen, &errors, &errors_count); @@ -9432,14 +9496,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ } return true; } + +static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) { + IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, + old_instruction->scope, old_instruction->source_node); + IrInstruction *new_instruction = &const_instruction->base; + new_instruction->value.type = ty; + new_instruction->value.special = ConstValSpecialStatic; + return new_instruction; +} + static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type, CastOp cast_op, bool need_alloca) { if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && cast_op != CastOpResizeSlice) { - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type, &result->value, wanted_type)) { @@ -9476,9 +9549,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, if (pointee == nullptr) return ira->codegen->invalid_instruction; if (pointee->special != ConstValSpecialRuntime) { - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); - result->value.type = wanted_type; + IrInstruction *result = ir_const(ira, source_instr, wanted_type); result->value.data.x_ptr.special = ConstPtrSpecialBaseArray; result->value.data.x_ptr.mut = value->value.data.x_ptr.mut; result->value.data.x_ptr.data.base_array.array_val = pointee; @@ -9517,8 +9588,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc assert(is_slice(wanted_type)); bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const); result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = value->value.data.x_ptr.mut; @@ -9653,15 +9723,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction) return instruction; } -static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) { - IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, - old_instruction->scope, old_instruction->source_node); - IrInstruction *new_instruction = &const_instruction->base; - new_instruction->value.type = ty; - new_instruction->value.special = ConstValSpecialStatic; - return new_instruction; -} - static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) { IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type); result->value.data.x_type = ty; @@ -9719,13 +9780,13 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un zig_unreachable(); } -IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, +ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, IrExecutable *parent_exec) { if (expected_type != nullptr && type_is_invalid(expected_type)) - return codegen->invalid_instruction; + return &codegen->invalid_instruction->value; IrExecutable *ir_executable = allocate(1); ir_executable->source_node = source_node; @@ -9738,13 +9799,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node ir_gen(codegen, node, scope, ir_executable); if (ir_executable->invalid) - return codegen->invalid_instruction; + return &codegen->invalid_instruction->value; if (codegen->verbose_ir) { fprintf(stderr, "\nSource: "); ast_render(codegen, stderr, node, 4); fprintf(stderr, "\n{ // (IR)\n"); - ir_print(codegen, stderr, ir_executable, 4); + ir_print(codegen, stderr, ir_executable, 2); fprintf(stderr, "}\n"); } IrExecutable *analyzed_executable = allocate(1); @@ -9760,11 +9821,11 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node analyzed_executable->begin_scope = scope; ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node); if (type_is_invalid(result_type)) - return codegen->invalid_instruction; + return &codegen->invalid_instruction->value; if (codegen->verbose_ir) { fprintf(stderr, "{ // (analyzed)\n"); - ir_print(codegen, stderr, analyzed_executable, 4); + ir_print(codegen, stderr, analyzed_executable, 2); fprintf(stderr, "}\n"); } @@ -9838,7 +9899,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { return const_val->data.x_ptr.data.fn.fn_entry; } -static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) { +static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, + ZigType *wanted_type) +{ assert(wanted_type->id == ZigTypeIdOptional); if (instr_is_comptime(value)) { @@ -9854,7 +9917,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value.special = ConstValSpecialStatic; - if (get_codegen_ptr_type(wanted_type) != nullptr) { + if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) { copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst); } else { const_instruction->base.value.data.x_optional = val; @@ -9885,11 +9948,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction if (!val) return ira->codegen->invalid_instruction; + ConstExprValue *err_set_val = create_const_vals(1); + err_set_val->type = wanted_type->data.error_union.err_set_type; + err_set_val->special = ConstValSpecialStatic; + err_set_val->data.x_err_set = nullptr; + IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value.type = wanted_type; const_instruction->base.value.special = ConstValSpecialStatic; - const_instruction->base.value.data.x_err_union.err = nullptr; + const_instruction->base.value.data.x_err_union.error_set = err_set_val; const_instruction->base.value.data.x_err_union.payload = val; return &const_instruction->base; } @@ -9954,11 +10022,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so if (!val) return ira->codegen->invalid_instruction; + ConstExprValue *err_set_val = create_const_vals(1); + err_set_val->special = ConstValSpecialStatic; + err_set_val->type = wanted_type->data.error_union.err_set_type; + err_set_val->data.x_err_set = val->data.x_err_set; + IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value.type = wanted_type; const_instruction->base.value.special = ConstValSpecialStatic; - const_instruction->base.value.data.x_err_union.err = val->data.x_err_set; + const_instruction->base.value.data.x_err_union.error_set = err_set_val; const_instruction->base.value.data.x_err_union.payload = nullptr; return &const_instruction->base; } @@ -9980,8 +10053,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value.special = ConstValSpecialStatic; if (get_codegen_ptr_type(wanted_type) != nullptr) { - const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; - const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0; + const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull; + } else if (is_opt_err_set(wanted_type)) { + const_instruction->base.value.data.x_err_set = nullptr; } else { const_instruction->base.value.data.x_optional = nullptr; } @@ -10014,7 +10088,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi source_instruction->source_node, value, is_const, is_volatile); new_instruction->value.type = ptr_type; new_instruction->value.data.rh_ptr = RuntimeHintPtrStack; - if (type_has_bits(ptr_type)) { + if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) { ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); assert(fn_entry); fn_entry->alloca_list.append(new_instruction); @@ -10040,20 +10114,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s ZigType *array_type = array->value.type; assert(array_type->id == ZigTypeIdArray); - if (instr_is_comptime(array)) { - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + if (instr_is_comptime(array) || array_type->data.array.len == 0) { + IrInstruction *result = ir_const(ira, source_instr, wanted_type); init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true); result->value.type = wanted_type; return result; } - IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, ira->codegen->builtin_types.entry_usize); + IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize); init_const_usize(ira->codegen, &start->value, 0); - IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, ira->codegen->builtin_types.entry_usize); + IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize); init_const_usize(ira->codegen, &end->value, array_type->data.array.len); if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); @@ -10092,8 +10163,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) return ira->codegen->invalid_instruction; - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag); return result; } @@ -10103,8 +10173,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour actual_type->data.enumeration.src_field_count == 1) { assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int); - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); init_const_bigint(&result->value, wanted_type, &actual_type->data.enumeration.fields[0].value); return result; @@ -10127,8 +10196,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) return ira->codegen->invalid_instruction; - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); result->value.special = ConstValSpecialStatic; result->value.type = wanted_type; bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag); @@ -10139,8 +10207,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && wanted_type->data.enumeration.src_field_count == 1) { - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); result->value.special = ConstValSpecialStatic; result->value.type = wanted_type; TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field; @@ -10157,8 +10224,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, ZigType *wanted_type) { - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); init_const_undefined(ira->codegen, &result->value); return result; } @@ -10190,8 +10256,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so buf_sprintf("field '%s' declared here", buf_ptr(union_field->name))); return ira->codegen->invalid_instruction; } - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); result->value.special = ConstValSpecialStatic; result->value.type = wanted_type; bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag); @@ -10246,8 +10311,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction return ira->codegen->invalid_instruction; } } - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); result->value.type = wanted_type; if (wanted_type->id == ZigTypeIdInt) { bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint); @@ -10301,8 +10365,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour return ira->codegen->invalid_instruction; } - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint); return result; } @@ -10320,8 +10383,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction if (!val) return ira->codegen->invalid_instruction; - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); if (wanted_type->id == ZigTypeIdComptimeFloat) { float_init_float(&result->value, val); } else if (wanted_type->id == ZigTypeIdComptimeInt) { @@ -10344,8 +10406,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc if (!val) return ira->codegen->invalid_instruction; - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) { return ira->codegen->invalid_instruction; @@ -10409,12 +10470,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc if (!val) return ira->codegen->invalid_instruction; - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); + IrInstruction *result = ir_const(ira, source_instr, wanted_type); ErrorTableEntry *err; if (err_type->id == ZigTypeIdErrorUnion) { - err = val->data.x_err_union.err; + err = val->data.x_err_union.error_set->data.x_err_set; } else if (err_type->id == ZigTypeIdErrorSet) { err = val->data.x_err_set; } else { @@ -10449,15 +10509,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc return ira->codegen->invalid_instruction; } if (err_set_type->data.error_set.err_count == 0) { - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); - result->value.type = wanted_type; + IrInstruction *result = ir_const(ira, source_instr, wanted_type); bigint_init_unsigned(&result->value.data.x_bigint, 0); return result; } else if (err_set_type->data.error_set.err_count == 1) { - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, - source_instr->source_node, wanted_type); - result->value.type = wanted_type; + IrInstruction *result = ir_const(ira, source_instr, wanted_type); ErrorTableEntry *err = err_set_type->data.error_set.errors[0]; bigint_init_unsigned(&result->value.data.x_bigint, err->value); return result; @@ -10504,8 +10560,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou array_val->type = array_type; array_val->data.x_array.special = ConstArraySpecialNone; array_val->data.x_array.data.s_none.elements = pointee; - array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar; - array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee; + array_val->parent.id = ConstParentIdScalar; + array_val->parent.data.p_scalar.scalar_val = pointee; IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, source_instr->scope, source_instr->source_node); @@ -10653,12 +10709,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk) { - return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); + return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type); } else if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdComptimeFloat) { if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { - return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); + return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type); } else { return ira->codegen->invalid_instruction; } @@ -10682,7 +10738,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst wanted_child_type); if (type_is_invalid(cast1->value.type)) return ira->codegen->invalid_instruction; - return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type); + return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type); } } } @@ -10735,6 +10791,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat)) { + if (value->value.special == ConstValSpecialUndef) { + IrInstruction *result = ir_const(ira, source_instr, wanted_type); + result->value.special = ConstValSpecialUndef; + return result; + } if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) { if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) { IrInstruction *result = ir_const(ira, source_instr, wanted_type); @@ -10788,6 +10849,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst // cast from [N]T to []const T + // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) { ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; assert(ptr_type->id == ZigTypeIdPointer); @@ -10800,6 +10862,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } // cast from [N]T to ?[]const T + // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this if (wanted_type->id == ZigTypeIdOptional && is_slice(wanted_type->data.maybe.child_type) && actual_type->id == ZigTypeIdArray) @@ -10894,7 +10957,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } } - // cast from error set to error union type + // cast from E to E!T if (wanted_type->id == ZigTypeIdErrorUnion && actual_type->id == ZigTypeIdErrorSet) { @@ -11046,8 +11109,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc ZigType *child_type = type_entry->data.pointer.child_type; // dereferencing a *u0 is comptime known to be 0 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) { - IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, - source_instruction->source_node, child_type); + IrInstruction *result = ir_const(ira, source_instruction, child_type); init_const_unsigned_negative(&result->value, child_type, 0, false); return result; } @@ -11061,8 +11123,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc { ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); if (pointee->special != ConstValSpecialRuntime) { - IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, - source_instruction->source_node, child_type); + IrInstruction *result = ir_const(ira, source_instruction, child_type); if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value, &ptr->value))) @@ -11074,7 +11135,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc } } } - // TODO if the instruction is a const ref instruction we can skip it + // if the instruction is a const ref instruction we can skip it + if (ptr->id == IrInstructionIdRef) { + IrInstructionRef *ref_inst = reinterpret_cast(ptr); + return ref_inst->value; + } IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, source_instruction->source_node, ptr); load_ptr_instruction->value.type = child_type; @@ -11321,8 +11386,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) { IrInstruction *result = ir_const(ira, &instruction->base, nullptr); - // TODO determine if we need to use copy_const_val here - result->value = instruction->base.value; + copy_const_val(&result->value, &instruction->base.value, true); return result; } @@ -11397,6 +11461,8 @@ static bool optional_value_is_null(ConstExprValue *val) { if (get_codegen_ptr_type(val->type) != nullptr) { return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && val->data.x_ptr.data.hard_coded_addr.addr == 0; + } else if (is_opt_err_set(val->type)) { + return val->data.x_err_set == nullptr; } else { return val->data.x_optional == nullptr; } @@ -11596,19 +11662,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * if (casted_op2 == ira->codegen->invalid_instruction) return ira->codegen->invalid_instruction; - bool requires_comptime; - switch (type_requires_comptime(ira->codegen, resolved_type)) { - case ReqCompTimeYes: - requires_comptime = true; - break; - case ReqCompTimeNo: - requires_comptime = false; - break; - case ReqCompTimeInvalid: + bool one_possible_value; + switch (type_has_one_possible_value(ira->codegen, resolved_type)) { + case OnePossibleValueInvalid: return ira->codegen->invalid_instruction; + case OnePossibleValueYes: + one_possible_value = true; + break; + case OnePossibleValueNo: + one_possible_value = false; + break; } - bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type); if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); if (op1_val == nullptr) @@ -12497,13 +12562,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio zig_unreachable(); } -static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) { +static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, + IrInstructionDeclVarSrc *decl_var_instruction) +{ Error err; ZigVar *var = decl_var_instruction->var; IrInstruction *init_value = decl_var_instruction->init_value->child; if (type_is_invalid(init_value->value.type)) { - var->value->type = ira->codegen->builtin_types.entry_invalid; + var->var_type = ira->codegen->builtin_types.entry_invalid; return ira->codegen->invalid_instruction; } @@ -12514,7 +12581,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct ZigType *proposed_type = ir_resolve_type(ira, var_type); explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type); if (type_is_invalid(explicit_type)) { - var->value->type = ira->codegen->builtin_types.entry_invalid; + var->var_type = ira->codegen->builtin_types.entry_invalid; return ira->codegen->invalid_instruction; } } @@ -12539,7 +12606,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct case ReqCompTimeInvalid: result_type = ira->codegen->builtin_types.entry_invalid; break; - case ReqCompTimeYes: { + case ReqCompTimeYes: var_class_requires_const = true; if (!var->gen_is_const && !is_comptime_var) { ir_add_error_node(ira, source_node, @@ -12548,7 +12615,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct result_type = ira->codegen->builtin_types.entry_invalid; } break; - } case ReqCompTimeNo: if (casted_init_value->value.special == ConstValSpecialStatic && casted_init_value->value.type->id == ZigTypeIdFn && @@ -12567,7 +12633,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct break; } - if (var->value->type != nullptr && !is_comptime_var) { + if (var->var_type != nullptr && !is_comptime_var) { // This is at least the second time we've seen this variable declaration during analysis. // This means that this is actually a different variable due to, e.g. an inline while loop. // We make a new variable so that it can hold a different type, and so the debug info can @@ -12589,8 +12655,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct // This must be done after possibly creating a new variable above var->ref_count = 0; - var->value->type = result_type; - assert(var->value->type); + var->var_type = result_type; + assert(var->var_type); if (type_is_invalid(result_type)) { return ir_const_void(ira, &decl_var_instruction->base); @@ -12598,13 +12664,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct if (decl_var_instruction->align_value == nullptr) { if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) { - var->value->type = ira->codegen->builtin_types.entry_invalid; + var->var_type = ira->codegen->builtin_types.entry_invalid; return ir_const_void(ira, &decl_var_instruction->base); } var->align_bytes = get_abi_alignment(ira->codegen, result_type); } else { if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) { - var->value->type = ira->codegen->builtin_types.entry_invalid; + var->var_type = ira->codegen->builtin_types.entry_invalid; } } @@ -12621,7 +12687,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct } else if (is_comptime_var) { ir_add_error(ira, &decl_var_instruction->base, buf_sprintf("cannot store runtime value in compile time variable")); - var->value->type = ira->codegen->builtin_types.entry_invalid; + var->var_type = ira->codegen->builtin_types.entry_invalid; return ira->codegen->invalid_instruction; } @@ -12629,11 +12695,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct if (fn_entry) fn_entry->variable_list.append(var); - IrInstruction *result = ir_build_var_decl(&ira->new_irb, - decl_var_instruction->base.scope, decl_var_instruction->base.source_node, - var, var_type, nullptr, casted_init_value); - result->value.type = ira->codegen->builtin_types.entry_void; - return result; + return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value); } static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { @@ -12963,7 +13025,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node Buf *param_name = param_decl_node->data.param_decl.name; ZigVar *var = add_variable(ira->codegen, param_decl_node, - *exec_scope, param_name, true, arg_val, nullptr); + *exec_scope, param_name, true, arg_val, nullptr, arg_val->type); *exec_scope = var->child_scope; *next_proto_i += 1; @@ -13021,7 +13083,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod if (!param_name) return false; if (!is_var_args) { ZigVar *var = add_variable(ira->codegen, param_decl_node, - *child_scope, param_name, true, arg_val, nullptr); + *child_scope, param_name, true, arg_val, nullptr, arg_val->type); *child_scope = var->child_scope; var->shadowable = !comptime_arg; @@ -13075,9 +13137,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) { return fn_entry->variable_list.at(next_var_i); } -static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, - ZigVar *var) -{ +static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) { while (var->next_var != nullptr) { var = var->next_var; } @@ -13086,14 +13146,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, assert(ira->codegen->errors.length != 0); return ira->codegen->invalid_instruction; } - if (var->value->type == nullptr || type_is_invalid(var->value->type)) + if (var->var_type == nullptr || type_is_invalid(var->var_type)) return ira->codegen->invalid_instruction; bool comptime_var_mem = ir_get_var_is_comptime(var); ConstExprValue *mem_slot = nullptr; - if (var->value->special == ConstValSpecialStatic) { - mem_slot = var->value; + if (var->const_value->special == ConstValSpecialStatic) { + mem_slot = var->const_value; } else { if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) { // find the relevant exec_context @@ -13122,7 +13182,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, assert(!comptime_var_mem); ptr_mut = ConstPtrMutRuntimeVar; } - return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type, + return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type, ptr_mut, is_const, is_volatile, var->align_bytes); } } @@ -13133,7 +13193,7 @@ no_mem_slot: IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb, instruction->scope, instruction->source_node, var); - var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type, + var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type, var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0); bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); @@ -13142,6 +13202,96 @@ no_mem_slot: return var_ptr_instruction; } +static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *ptr, IrInstruction *uncasted_value) +{ + if (ptr->value.type->id != ZigTypeIdPointer) { + ir_add_error(ira, ptr, + buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name))); + return ira->codegen->invalid_instruction; + } + + if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) { + return ir_const_void(ira, source_instr); + } + + if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) { + ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); + return ira->codegen->invalid_instruction; + } + + ZigType *child_type = ptr->value.type->data.pointer.child_type; + IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type); + if (value == ira->codegen->invalid_instruction) + return ira->codegen->invalid_instruction; + + if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { + if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) { + ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); + return ira->codegen->invalid_instruction; + } + if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) { + if (instr_is_comptime(value)) { + ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node); + if (dest_val == nullptr) + return ira->codegen->invalid_instruction; + if (dest_val->special != ConstValSpecialRuntime) { + // TODO this allows a value stored to have the original value modified and then + // have that affect what should be a copy. We need some kind of advanced copy-on-write + // system to make these two tests pass at the same time: + // * "string literal used as comptime slice is memoized" + // * "comptime modification of const struct field" - except modified to avoid + // ConstPtrMutComptimeVar, thus defeating the logic below. + bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar; + copy_const_val(dest_val, &value->value, same_global_refs); + if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) { + switch (type_has_one_possible_value(ira->codegen, child_type)) { + case OnePossibleValueInvalid: + return ira->codegen->invalid_instruction; + case OnePossibleValueNo: + ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr; + break; + case OnePossibleValueYes: + break; + } + } + return ir_const_void(ira, source_instr); + } + } + ir_add_error(ira, source_instr, + buf_sprintf("cannot store runtime value in compile time variable")); + ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); + dest_val->type = ira->codegen->builtin_types.entry_invalid; + + return ira->codegen->invalid_instruction; + } + } + + switch (type_requires_comptime(ira->codegen, child_type)) { + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + case ReqCompTimeYes: + switch (type_has_one_possible_value(ira->codegen, ptr->value.type)) { + case OnePossibleValueInvalid: + return ira->codegen->invalid_instruction; + case OnePossibleValueNo: + ir_add_error(ira, source_instr, + buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name))); + return ira->codegen->invalid_instruction; + case OnePossibleValueYes: + return ir_const_void(ira, source_instr); + } + zig_unreachable(); + case ReqCompTimeNo: + break; + } + + IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, + ptr, value); + result->value.type = ira->codegen->builtin_types.entry_void; + return result; +} + static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref, IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline) @@ -13286,7 +13436,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call } bool cacheable = fn_eval_cacheable(exec_scope, return_type); - IrInstruction *result = nullptr; + ConstExprValue *result = nullptr; if (cacheable) { auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); if (entry) @@ -13302,18 +13452,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call if (inferred_err_set_type != nullptr) { inferred_err_set_type->data.error_set.infer_fn = nullptr; - if (result->value.type->id == ZigTypeIdErrorUnion) { - if (result->value.data.x_err_union.err != nullptr) { + if (result->type->id == ZigTypeIdErrorUnion) { + ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set; + if (err != nullptr) { inferred_err_set_type->data.error_set.err_count = 1; inferred_err_set_type->data.error_set.errors = allocate(1); - inferred_err_set_type->data.error_set.errors[0] = result->value.data.x_err_union.err; + inferred_err_set_type->data.error_set.errors[0] = err; } - ZigType *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type; + ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type; inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count; inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors; - } else if (result->value.type->id == ZigTypeIdErrorSet) { - inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count; - inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors; + } else if (result->type->id == ZigTypeIdErrorSet) { + inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count; + inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors; } } @@ -13321,13 +13472,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call ira->codegen->memoized_fn_eval_table.put(exec_scope, result); } - if (type_is_invalid(result->value.type)) + if (type_is_invalid(result->type)) return ira->codegen->invalid_instruction; } - IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type); - // TODO should we use copy_const_val? - new_instruction->value = result->value; + IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type); + copy_const_val(&new_instruction->value, result, true); new_instruction->value.type = return_type; return ir_finish_anal(ira, new_instruction); } @@ -13486,18 +13636,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen, first_var_arg, inst_fn_type_id.param_count); ZigVar *var = add_variable(ira->codegen, param_decl_node, - impl_fn->child_scope, param_name, true, var_args_val, nullptr); + impl_fn->child_scope, param_name, true, var_args_val, nullptr, var_args_val->type); impl_fn->child_scope = var->child_scope; } if (fn_proto_node->data.fn_proto.align_expr != nullptr) { - IrInstruction *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, + ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec); + IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, + impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); + const_instruction->base.value = *align_result; uint32_t align_bytes = 0; - ir_resolve_align(ira, align_result, &align_bytes); + ir_resolve_align(ira, &const_instruction->base, &align_bytes); impl_fn->align_bytes = align_bytes; inst_fn_type_id.alignment = align_bytes; } @@ -13575,12 +13728,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call ira->codegen->fn_defs.append(impl_fn); } - ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; - if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) { + FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id; + if (fn_type_can_fail(impl_fn_type_id)) { parent_fn_entry->calls_or_awaits_errorable_fn = true; } - size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count; + size_t impl_param_count = impl_fn_type_id->param_count; if (call_instruction->is_async) { IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, fn_ref, casted_args, impl_param_count, async_allocator_inst); @@ -13593,9 +13746,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call call_instruction->base.scope, call_instruction->base.source_node, impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline, call_instruction->is_async, nullptr, casted_new_stack); - new_call_instruction->value.type = return_type; + new_call_instruction->value.type = impl_fn_type_id->return_type; - ir_add_alloca(ira, new_call_instruction, return_type); + ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type); return ir_finish_anal(ira, new_call_instruction); } @@ -13790,6 +13943,13 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source switch (ptr_val->data.x_ptr.special) { case ConstPtrSpecialInvalid: zig_unreachable(); + case ConstPtrSpecialNull: + if (dst_size == 0) + return ErrorNone; + opt_ir_add_error_node(ira, codegen, source_node, + buf_sprintf("attempt to read %zu bytes from null pointer", + dst_size)); + return ErrorSemanticAnalyzeFail; case ConstPtrSpecialRef: { opt_ir_add_error_node(ira, codegen, source_node, buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", @@ -13822,6 +13982,9 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source return ErrorNone; } case ConstPtrSpecialBaseStruct: + case ConstPtrSpecialBaseErrorUnionCode: + case ConstPtrSpecialBaseErrorUnionPayload: + case ConstPtrSpecialBaseOptionalPayload: case ConstPtrSpecialDiscard: case ConstPtrSpecialHardCodedAddr: case ConstPtrSpecialFunction: @@ -14017,9 +14180,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime)) return ir_unreach_error(ira); - if (is_comptime || instr_is_comptime(condition)) { + ZigType *bool_type = ira->codegen->builtin_types.entry_bool; + IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type); + if (type_is_invalid(casted_condition->value.type)) + return ir_unreach_error(ira); + + if (is_comptime || instr_is_comptime(casted_condition)) { bool cond_is_true; - if (!ir_resolve_bool(ira, condition, &cond_is_true)) + if (!ir_resolve_bool(ira, casted_condition, &cond_is_true)) return ir_unreach_error(ira); IrBasicBlock *old_dest_block = cond_is_true ? @@ -14038,11 +14206,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi return ir_finish_anal(ira, result); } - ZigType *bool_type = ira->codegen->builtin_types.entry_bool; - IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type); - if (casted_condition == ira->codegen->invalid_instruction) - return ir_unreach_error(ira); - assert(cond_br_instruction->then_block != cond_br_instruction->else_block); IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base); if (new_then_block == nullptr) @@ -14081,8 +14244,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh if (value->value.special != ConstValSpecialRuntime) { IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr); - // TODO use copy_const_val? - result->value = value->value; + copy_const_val(&result->value, &value->value, true); return result; } else { return value; @@ -14131,14 +14293,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh if (type_is_invalid(resolved_type)) return ira->codegen->invalid_instruction; - if (resolved_type->id == ZigTypeIdComptimeFloat || - resolved_type->id == ZigTypeIdComptimeInt || - resolved_type->id == ZigTypeIdNull || - resolved_type->id == ZigTypeIdUndefined) - { - ir_add_error_node(ira, phi_instruction->base.source_node, - buf_sprintf("unable to infer expression type")); + switch (type_has_one_possible_value(ira->codegen, resolved_type)) { + case OnePossibleValueInvalid: return ira->codegen->invalid_instruction; + case OnePossibleValueYes: + return ir_const(ira, &phi_instruction->base, resolved_type); + case OnePossibleValueNo: + break; + } + + switch (type_requires_comptime(ira->codegen, resolved_type)) { + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + case ReqCompTimeYes: + ir_add_error_node(ira, phi_instruction->base.source_node, + buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name))); + return ira->codegen->invalid_instruction; + case ReqCompTimeNo: + break; } bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer); @@ -14428,10 +14600,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } case ConstPtrSpecialBaseStruct: zig_panic("TODO elem ptr on a const inner struct"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO elem ptr on a const inner error union code"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO elem ptr on a const inner error union payload"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO elem ptr on a const inner optional payload"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); case ConstPtrSpecialFunction: zig_panic("TODO element ptr of a function casted to a ptr"); + case ConstPtrSpecialNull: + zig_panic("TODO elem ptr on a null pointer"); } if (new_index >= mem_size) { ir_add_error_node(ira, elem_ptr_instruction->base.source_node, @@ -14481,10 +14661,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } case ConstPtrSpecialBaseStruct: zig_panic("TODO elem ptr on a slice backed by const inner struct"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO elem ptr on a slice backed by const inner error union code"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO elem ptr on a slice backed by const inner error union payload"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO elem ptr on a slice backed by const optional payload"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); case ConstPtrSpecialFunction: zig_panic("TODO elem ptr on a slice that was ptrcast from a function"); + case ConstPtrSpecialNull: + zig_panic("TODO elem ptr on a slice has a null pointer"); } return result; } else if (array_type->id == ZigTypeIdArray) { @@ -15171,74 +15359,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc } } -static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { - IrInstruction *ptr = load_ptr_instruction->ptr->child; - if (type_is_invalid(ptr->value.type)) - return ira->codegen->invalid_instruction; - return ir_get_deref(ira, &load_ptr_instruction->base, ptr); -} - -static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) { - IrInstruction *ptr = store_ptr_instruction->ptr->child; +static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) { + IrInstruction *ptr = instruction->ptr->child; if (type_is_invalid(ptr->value.type)) return ira->codegen->invalid_instruction; - IrInstruction *value = store_ptr_instruction->value->child; + IrInstruction *value = instruction->value->child; if (type_is_invalid(value->value.type)) return ira->codegen->invalid_instruction; - if (ptr->value.type->id != ZigTypeIdPointer) { - ir_add_error(ira, ptr, - buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name))); + return ir_analyze_store_ptr(ira, &instruction->base, ptr, value); +} + +static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) { + IrInstruction *ptr = instruction->ptr->child; + if (type_is_invalid(ptr->value.type)) return ira->codegen->invalid_instruction; - } - - if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) { - return ir_const_void(ira, &store_ptr_instruction->base); - } - - if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) { - ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant")); - return ira->codegen->invalid_instruction; - } - - ZigType *child_type = ptr->value.type->data.pointer.child_type; - IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type); - if (casted_value == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; - - if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { - if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) { - ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant")); - return ira->codegen->invalid_instruction; - } - if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) { - if (instr_is_comptime(casted_value)) { - ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, store_ptr_instruction->base.source_node); - if (dest_val == nullptr) - return ira->codegen->invalid_instruction; - if (dest_val->special != ConstValSpecialRuntime) { - *dest_val = casted_value->value; - if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) { - ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base; - } - return ir_const_void(ira, &store_ptr_instruction->base); - } - } - ir_add_error(ira, &store_ptr_instruction->base, - buf_sprintf("cannot store runtime value in compile time variable")); - ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); - dest_val->type = ira->codegen->builtin_types.entry_invalid; - - return ira->codegen->invalid_instruction; - } - } - - IrInstruction *result = ir_build_store_ptr(&ira->new_irb, - store_ptr_instruction->base.scope, store_ptr_instruction->base.source_node, - ptr, casted_value); - result->value.type = ira->codegen->builtin_types.entry_void; - return result; + return ir_get_deref(ira, &instruction->base, ptr); } static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) { @@ -15709,11 +15846,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, zig_unreachable(); } -static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) { - IrInstruction *value = instruction->value->child; - if (type_is_invalid(value->value.type)) - return ira->codegen->invalid_instruction; - +static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) { ZigType *type_entry = value->value.type; if (type_entry->id == ZigTypeIdOptional) { @@ -15722,60 +15855,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns if (!maybe_val) return ira->codegen->invalid_instruction; - return ir_const_bool(ira, &instruction->base, !optional_value_is_null(maybe_val)); + return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val)); } IrInstruction *result = ir_build_test_nonnull(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, value); + source_inst->scope, source_inst->source_node, value); result->value.type = ira->codegen->builtin_types.entry_bool; return result; } else if (type_entry->id == ZigTypeIdNull) { - return ir_const_bool(ira, &instruction->base, false); + return ir_const_bool(ira, source_inst, false); } else { - return ir_const_bool(ira, &instruction->base, true); + return ir_const_bool(ira, source_inst, true); } } -static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, - IrInstructionUnwrapOptional *unwrap_maybe_instruction) -{ - IrInstruction *value = unwrap_maybe_instruction->value->child; +static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) { + IrInstruction *value = instruction->value->child; if (type_is_invalid(value->value.type)) return ira->codegen->invalid_instruction; - ZigType *ptr_type = value->value.type; + return ir_analyze_test_non_null(ira, &instruction->base, value); +} + +static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *base_ptr, bool safety_check_on) +{ + ZigType *ptr_type = base_ptr->value.type; assert(ptr_type->id == ZigTypeIdPointer); ZigType *type_entry = ptr_type->data.pointer.child_type; - if (type_is_invalid(type_entry)) { + if (type_is_invalid(type_entry)) return ira->codegen->invalid_instruction; - } else if (type_entry->id != ZigTypeIdOptional) { - ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node, + + if (type_entry->id != ZigTypeIdOptional) { + ir_add_error_node(ira, base_ptr->source_node, buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name))); return ira->codegen->invalid_instruction; } + ZigType *child_type = type_entry->data.maybe.child_type; ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0); - if (instr_is_comptime(value)) { - ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); + if (instr_is_comptime(base_ptr)) { + ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad); if (!val) return ira->codegen->invalid_instruction; - ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, unwrap_maybe_instruction->base.source_node); + ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node); if (maybe_val == nullptr) return ira->codegen->invalid_instruction; if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { if (optional_value_is_null(maybe_val)) { - ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null")); + ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null")); return ira->codegen->invalid_instruction; } - IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type); + IrInstruction *result = ir_const(ira, source_instr, result_type); ConstExprValue *out_val = &result->value; out_val->data.x_ptr.special = ConstPtrSpecialRef; out_val->data.x_ptr.mut = val->data.x_ptr.mut; - if (type_is_codegen_pointer(child_type)) { + if (types_have_same_zig_comptime_repr(type_entry, child_type)) { out_val->data.x_ptr.data.ref.pointee = maybe_val; } else { out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional; @@ -15784,13 +15923,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, } } - IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb, - unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node, - value, unwrap_maybe_instruction->safety_check_on); + IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope, + source_instr->source_node, base_ptr, safety_check_on); result->value.type = result_type; return result; } +static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, + IrInstructionOptionalUnwrapPtr *instruction) +{ + IrInstruction *base_ptr = instruction->base_ptr->child; + if (type_is_invalid(base_ptr->value.type)) + return ira->codegen->invalid_instruction; + + return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on); +} + static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) { IrInstruction *value = ctz_instruction->value->child; if (type_is_invalid(value->value.type)) { @@ -16091,9 +16239,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, return result; } - IrInstruction *result = ir_build_load_ptr(&ira->new_irb, - switch_target_instruction->base.scope, switch_target_instruction->base.source_node, - target_value_ptr); + IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr); result->value.type = target_type; return result; } @@ -16123,8 +16269,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, return result; } - IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, - switch_target_instruction->base.source_node, target_value_ptr); + IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr); union_value->value.type = target_type; IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope, @@ -16148,8 +16293,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, return result; } - IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, - switch_target_instruction->base.source_node, target_value_ptr); + IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr); enum_value->value.type = target_type; return enum_value; } @@ -16306,7 +16450,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI Error err; assert(container_type->id == ZigTypeIdUnion); - if ((err = ensure_complete_type(ira->codegen, container_type))) + if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) return ira->codegen->invalid_instruction; if (instr_field_count != 1) { @@ -16350,12 +16494,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI ConstExprValue *out_val = &result->value; out_val->data.x_union.payload = field_val; out_val->data.x_union.tag = type_field->enum_field->value; - - ConstParent *parent = get_const_val_parent(ira->codegen, field_val); - if (parent != nullptr) { - parent->id = ConstParentIdUnion; - parent->data.p_union.union_val = out_val; - } + out_val->parent.id = ConstParentIdUnion; + out_val->parent.data.p_union.union_val = out_val; return result; } @@ -16382,7 +16522,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc return ira->codegen->invalid_instruction; } - if ((err = ensure_complete_type(ira->codegen, container_type))) + if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) return ira->codegen->invalid_instruction; size_t actual_field_count = container_type->data.structure.src_field_count; @@ -16461,9 +16601,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc if (const_val.special == ConstValSpecialStatic) { IrInstruction *result = ir_const(ira, instruction, nullptr); ConstExprValue *out_val = &result->value; - // TODO copy_const_val? - *out_val = const_val; - result->value.type = container_type; + copy_const_val(out_val, &const_val, true); + out_val->type = container_type; for (size_t i = 0; i < instr_field_count; i += 1) { ConstExprValue *field_val = &out_val->data.x_struct.fields[i]; @@ -16495,127 +16634,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) { - IrInstruction *container_type_value = instruction->container_type->child; - if (type_is_invalid(container_type_value->value.type)) + ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); + if (type_is_invalid(container_type)) return ira->codegen->invalid_instruction; size_t elem_count = instruction->item_count; - if (container_type_value->value.type->id == ZigTypeIdMetaType) { - ZigType *container_type = ir_resolve_type(ira, container_type_value); - if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; - if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) { - return ir_analyze_container_init_fields(ira, &instruction->base, container_type, - 0, nullptr); - } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) { - // array is same as slice init but we make a compile error if the length is wrong - ZigType *child_type; - if (container_type->id == ZigTypeIdArray) { - child_type = container_type->data.array.child_type; - if (container_type->data.array.len != elem_count) { - ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); + if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) { + return ir_analyze_container_init_fields(ira, &instruction->base, container_type, + 0, nullptr); + } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) { + // array is same as slice init but we make a compile error if the length is wrong + ZigType *child_type; + if (container_type->id == ZigTypeIdArray) { + child_type = container_type->data.array.child_type; + if (container_type->data.array.len != elem_count) { + ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); - ir_add_error(ira, &instruction->base, - buf_sprintf("expected %s literal, found %s literal", - buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); - return ira->codegen->invalid_instruction; - } - } else { - ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry; - assert(pointer_type->id == ZigTypeIdPointer); - child_type = pointer_type->data.pointer.child_type; + ir_add_error(ira, &instruction->base, + buf_sprintf("expected %s literal, found %s literal", + buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); + return ira->codegen->invalid_instruction; } + } else { + ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry; + assert(pointer_type->id == ZigTypeIdPointer); + child_type = pointer_type->data.pointer.child_type; + } - ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); + ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); - ConstExprValue const_val = {}; - const_val.special = ConstValSpecialStatic; - const_val.type = fixed_size_array_type; - const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count); + ConstExprValue const_val = {}; + const_val.special = ConstValSpecialStatic; + const_val.type = fixed_size_array_type; + const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count); - bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope); + bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope); - IrInstruction **new_items = allocate(elem_count); + IrInstruction **new_items = allocate(elem_count); - IrInstruction *first_non_const_instruction = nullptr; + IrInstruction *first_non_const_instruction = nullptr; - for (size_t i = 0; i < elem_count; i += 1) { - IrInstruction *arg_value = instruction->items[i]->child; - if (type_is_invalid(arg_value->value.type)) - return ira->codegen->invalid_instruction; + for (size_t i = 0; i < elem_count; i += 1) { + IrInstruction *arg_value = instruction->items[i]->child; + if (type_is_invalid(arg_value->value.type)) + return ira->codegen->invalid_instruction; - IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type); - if (casted_arg == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type); + if (casted_arg == ira->codegen->invalid_instruction) + return ira->codegen->invalid_instruction; - new_items[i] = casted_arg; - - if (const_val.special == ConstValSpecialStatic) { - if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) { - ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad); - if (!elem_val) - return ira->codegen->invalid_instruction; - - copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true); - } else { - first_non_const_instruction = casted_arg; - const_val.special = ConstValSpecialRuntime; - } - } - } + new_items[i] = casted_arg; if (const_val.special == ConstValSpecialStatic) { - IrInstruction *result = ir_const(ira, &instruction->base, nullptr); - ConstExprValue *out_val = &result->value; - // TODO copy_const_val? - *out_val = const_val; - result->value.type = fixed_size_array_type; - for (size_t i = 0; i < elem_count; i += 1) { - ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i]; - ConstParent *parent = get_const_val_parent(ira->codegen, elem_val); - if (parent != nullptr) { - parent->id = ConstParentIdArray; - parent->data.p_array.array_val = out_val; - parent->data.p_array.elem_index = i; - } + if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) { + ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad); + if (!elem_val) + return ira->codegen->invalid_instruction; + + copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true); + } else { + first_non_const_instruction = casted_arg; + const_val.special = ConstValSpecialRuntime; } - return result; } + } - if (is_comptime) { - ir_add_error_node(ira, first_non_const_instruction->source_node, - buf_sprintf("unable to evaluate constant expression")); - return ira->codegen->invalid_instruction; + if (const_val.special == ConstValSpecialStatic) { + IrInstruction *result = ir_const(ira, &instruction->base, nullptr); + ConstExprValue *out_val = &result->value; + copy_const_val(out_val, &const_val, true); + result->value.type = fixed_size_array_type; + for (size_t i = 0; i < elem_count; i += 1) { + ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i]; + ConstParent *parent = get_const_val_parent(ira->codegen, elem_val); + if (parent != nullptr) { + parent->id = ConstParentIdArray; + parent->data.p_array.array_val = out_val; + parent->data.p_array.elem_index = i; + } } + return result; + } - IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, - container_type_value, elem_count, new_items); - new_instruction->value.type = fixed_size_array_type; - ir_add_alloca(ira, new_instruction, fixed_size_array_type); - return new_instruction; - } else if (container_type->id == ZigTypeIdVoid) { - if (elem_count != 0) { - ir_add_error_node(ira, instruction->base.source_node, - buf_sprintf("void expression expects no arguments")); - return ira->codegen->invalid_instruction; - } - return ir_const_void(ira, &instruction->base); - } else { - ir_add_error_node(ira, instruction->base.source_node, - buf_sprintf("type '%s' does not support array initialization", - buf_ptr(&container_type->name))); + if (is_comptime) { + ir_add_error_node(ira, first_non_const_instruction->source_node, + buf_sprintf("unable to evaluate constant expression")); return ira->codegen->invalid_instruction; } + + IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb, + instruction->base.scope, instruction->base.source_node, + nullptr, elem_count, new_items); + new_instruction->value.type = fixed_size_array_type; + ir_add_alloca(ira, new_instruction, fixed_size_array_type); + return new_instruction; + } else if (container_type->id == ZigTypeIdVoid) { + if (elem_count != 0) { + ir_add_error_node(ira, instruction->base.source_node, + buf_sprintf("void expression expects no arguments")); + return ira->codegen->invalid_instruction; + } + return ir_const_void(ira, &instruction->base); } else { - ir_add_error(ira, container_type_value, - buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name))); + ir_add_error_node(ira, instruction->base.source_node, + buf_sprintf("type '%s' does not support array initialization", + buf_ptr(&container_type->name))); return ira->codegen->invalid_instruction; } } -static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) { +static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, + IrInstructionContainerInitFields *instruction) +{ IrInstruction *container_type_value = instruction->container_type->child; ZigType *container_type = ir_resolve_type(ira, container_type_value); if (type_is_invalid(container_type)) @@ -16675,7 +16806,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct if (type_is_invalid(value->value.type)) return ira->codegen->invalid_instruction; - IrInstruction *casted_value = ir_implicit_cast(ira, value, value->value.type); + IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set); if (type_is_invalid(casted_value->value.type)) return ira->codegen->invalid_instruction; @@ -16936,10 +17067,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig ZigVar *var = tld->var; - if ((err = ensure_complete_type(ira->codegen, var->value->type))) + if ((err = ensure_complete_type(ira->codegen, var->const_value->type))) return ira->codegen->builtin_types.entry_invalid; - assert(var->value->type->id == ZigTypeIdMetaType); - return var->value->data.x_type; + + assert(var->const_value->type->id == ZigTypeIdMetaType); + return var->const_value->data.x_type; } static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) { @@ -16994,7 +17126,6 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco definition_array->special = ConstValSpecialStatic; definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count); definition_array->data.x_array.special = ConstArraySpecialNone; - definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count); init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false); @@ -17025,33 +17156,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub; inner_fields[2].special = ConstValSpecialStatic; inner_fields[2].type = type_info_definition_data_type; - inner_fields[2].data.x_union.parent.id = ConstParentIdStruct; - inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val; - inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1; + inner_fields[2].parent.id = ConstParentIdStruct; + inner_fields[2].parent.data.p_struct.struct_val = definition_val; + inner_fields[2].parent.data.p_struct.field_index = 1; switch (curr_entry->value->id) { case TldIdVar: { ZigVar *var = ((TldVar *)curr_entry->value)->var; - if ((err = ensure_complete_type(ira->codegen, var->value->type))) + if ((err = ensure_complete_type(ira->codegen, var->const_value->type))) return ErrorSemanticAnalyzeFail; - if (var->value->type->id == ZigTypeIdMetaType) - { + if (var->const_value->type->id == ZigTypeIdMetaType) { // We have a variable of type 'type', so it's actually a type definition. // 0: Data.Type: type bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); - inner_fields[2].data.x_union.payload = var->value; - } - else - { + inner_fields[2].data.x_union.payload = var->const_value; + } else { // We have a variable of another type, so we store the type of the variable. // 1: Data.Var: type bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1); ConstExprValue *payload = create_const_vals(1); payload->type = ira->codegen->builtin_types.entry_type; - payload->data.x_type = var->value->type; + payload->data.x_type = var->const_value->type; inner_fields[2].data.x_union.payload = payload; } @@ -17071,8 +17199,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco ConstExprValue *fn_def_val = create_const_vals(1); fn_def_val->special = ConstValSpecialStatic; fn_def_val->type = type_info_fn_def_type; - fn_def_val->data.x_struct.parent.id = ConstParentIdUnion; - fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2]; + fn_def_val->parent.id = ConstParentIdUnion; + fn_def_val->parent.data.p_union.union_val = &inner_fields[2]; ConstExprValue *fn_def_fields = create_const_vals(9); fn_def_val->data.x_struct.fields = fn_def_fields; @@ -17136,20 +17264,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco fn_arg_name_array->type = get_array_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr), fn_arg_count); fn_arg_name_array->data.x_array.special = ConstArraySpecialNone; - fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false); - for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) - { + for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index); ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index]; ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name); init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true); - fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray; - fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array; - fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index; + fn_arg_name_val->parent.id = ConstParentIdArray; + fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array; + fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index; } inner_fields[2].data.x_union.payload = fn_def_val; @@ -17442,7 +17568,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE enum_field_array->special = ConstValSpecialStatic; enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count); enum_field_array->data.x_array.special = ConstArraySpecialNone; - enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count); init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false); @@ -17452,9 +17577,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index]; ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index]; make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type); - enum_field_val->data.x_struct.parent.id = ConstParentIdArray; - enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array; - enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index; + enum_field_val->parent.id = ConstParentIdArray; + enum_field_val->parent.data.p_array.array_val = enum_field_array; + enum_field_val->parent.data.p_array.elem_index = enum_field_index; } // defs: []TypeInfo.Definition ensure_field_index(result->type, "defs", 3); @@ -17481,7 +17606,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE error_array->special = ConstValSpecialStatic; error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count); error_array->data.x_array.special = ConstArraySpecialNone; - error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; error_array->data.x_array.data.s_none.elements = create_const_vals(error_count); init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false); @@ -17505,9 +17629,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value); error_val->data.x_struct.fields = inner_fields; - error_val->data.x_struct.parent.id = ConstParentIdArray; - error_val->data.x_struct.parent.data.p_array.array_val = error_array; - error_val->data.x_struct.parent.data.p_array.elem_index = error_index; + error_val->parent.id = ConstParentIdArray; + error_val->parent.data.p_array.array_val = error_array; + error_val->parent.data.p_array.elem_index = error_index; } break; @@ -17576,7 +17700,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE union_field_array->special = ConstValSpecialStatic; union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count); union_field_array->data.x_array.special = ConstArraySpecialNone; - union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count); init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false); @@ -17609,9 +17732,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true); union_field_val->data.x_struct.fields = inner_fields; - union_field_val->data.x_struct.parent.id = ConstParentIdArray; - union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array; - union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index; + union_field_val->parent.id = ConstParentIdArray; + union_field_val->parent.data.p_array.array_val = union_field_array; + union_field_val->parent.data.p_array.elem_index = union_field_index; } // defs: []TypeInfo.Definition ensure_field_index(result->type, "defs", 3); @@ -17651,7 +17774,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE struct_field_array->special = ConstValSpecialStatic; struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count); struct_field_array->data.x_array.special = ConstArraySpecialNone; - struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count); init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false); @@ -17685,9 +17807,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true); struct_field_val->data.x_struct.fields = inner_fields; - struct_field_val->data.x_struct.parent.id = ConstParentIdArray; - struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array; - struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index; + struct_field_val->parent.id = ConstParentIdArray; + struct_field_val->parent.data.p_array.array_val = struct_field_array; + struct_field_val->parent.data.p_array.elem_index = struct_field_index; } // defs: []TypeInfo.Definition ensure_field_index(result->type, "defs", 2); @@ -17757,7 +17879,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE fn_arg_array->special = ConstValSpecialStatic; fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count); fn_arg_array->data.x_array.special = ConstArraySpecialNone; - fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false); @@ -17794,9 +17915,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE } fn_arg_val->data.x_struct.fields = inner_fields; - fn_arg_val->data.x_struct.parent.id = ConstParentIdArray; - fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array; - fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index; + fn_arg_val->parent.id = ConstParentIdArray; + fn_arg_val->parent.data.p_array.array_val = fn_arg_array; + fn_arg_val->parent.data.p_array.elem_index = fn_arg_index; } break; @@ -17840,8 +17961,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, if (payload != nullptr) { assert(payload->type->id == ZigTypeIdStruct); - payload->data.x_struct.parent.id = ConstParentIdUnion; - payload->data.x_struct.parent.data.p_union.union_val = out_val; + payload->parent.id = ConstParentIdUnion; + payload->parent.data.p_union.union_val = out_val; } return result; @@ -17913,10 +18034,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct // Execute the C import block like an inline function ZigType *void_type = ira->codegen->builtin_types.entry_void; - IrInstruction *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, + ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, &cimport_scope->buf, block_node, nullptr, nullptr); - if (type_is_invalid(cimport_result->value.type)) + if (type_is_invalid(cimport_result->type)) return ira->codegen->invalid_instruction; find_libc_include_path(ira->codegen); @@ -18066,7 +18187,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru return result; } -static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) { +static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) { ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child); if (type_is_invalid(operand_type)) return ira->codegen->invalid_instruction; @@ -18138,9 +18259,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi zig_panic("TODO compile-time execution of cmpxchg"); } - IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node, - nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak, - operand_type, success_order, failure_order); + IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base, + casted_ptr, casted_cmp_value, casted_new_value, + success_order, failure_order, instruction->is_weak); result->value.type = get_optional_type(ira->codegen, operand_type); ir_add_alloca(ira, result, result->value.type); return result; @@ -18312,18 +18433,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type); } -static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { - Error err; - - if (ty->id == ZigTypeIdPointer) { - if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown))) - return err; - } - - *result_align = get_ptr_align(ira->codegen, ty); - return ErrorNone; -} - static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) { Error err; @@ -18442,6 +18551,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true); } +static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { + Error err; + + ZigType *ptr_type = get_src_ptr_type(ty); + assert(ptr_type != nullptr); + if (ptr_type->id == ZigTypeIdPointer) { + if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) + return err; + } + + *result_align = get_ptr_align(ira->codegen, ty); + return ErrorNone; +} + static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) { ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); if (type_is_invalid(dest_type)) @@ -18646,10 +18769,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio } case ConstPtrSpecialBaseStruct: zig_panic("TODO memset on const inner struct"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO memset on const inner error union code"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO memset on const inner error union payload"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO memset on const inner optional payload"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); case ConstPtrSpecialFunction: zig_panic("TODO memset on ptr cast from function"); + case ConstPtrSpecialNull: + zig_panic("TODO memset on null ptr"); } size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint); @@ -18761,10 +18892,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio } case ConstPtrSpecialBaseStruct: zig_panic("TODO memcpy on const inner struct"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO memcpy on const inner error union code"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO memcpy on const inner error union payload"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO memcpy on const inner optional payload"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); case ConstPtrSpecialFunction: zig_panic("TODO memcpy on ptr cast from function"); + case ConstPtrSpecialNull: + zig_panic("TODO memcpy on null ptr"); } if (dest_start + count > dest_end) { @@ -18797,10 +18936,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio } case ConstPtrSpecialBaseStruct: zig_panic("TODO memcpy on const inner struct"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO memcpy on const inner error union code"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO memcpy on const inner error union payload"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO memcpy on const inner optional payload"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); case ConstPtrSpecialFunction: zig_panic("TODO memcpy on ptr cast from function"); + case ConstPtrSpecialNull: + zig_panic("TODO memcpy on null ptr"); } if (src_start + count > src_end) { @@ -18828,9 +18975,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction if (type_is_invalid(ptr_ptr->value.type)) return ira->codegen->invalid_instruction; - ZigType *ptr_type = ptr_ptr->value.type; - assert(ptr_type->id == ZigTypeIdPointer); - ZigType *array_type = ptr_type->data.pointer.child_type; + ZigType *ptr_ptr_type = ptr_ptr->value.type; + assert(ptr_ptr_type->id == ZigTypeIdPointer); + ZigType *array_type = ptr_ptr_type->data.pointer.child_type; IrInstruction *start = instruction->start->child; if (type_is_invalid(start->value.type)) @@ -18859,10 +19006,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic && ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst; ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type, - ptr_type->data.pointer.is_const || is_comptime_const, - ptr_type->data.pointer.is_volatile, + ptr_ptr_type->data.pointer.is_const || is_comptime_const, + ptr_ptr_type->data.pointer.is_volatile, PtrLenUnknown, - ptr_type->data.pointer.explicit_alignment, 0, 0); + ptr_ptr_type->data.pointer.explicit_alignment, 0, 0); return_type = get_slice_type(ira->codegen, slice_ptr_type); } else if (array_type->id == ZigTypeIdPointer) { if (array_type->data.pointer.ptr_len == PtrLenSingle) { @@ -18960,6 +19107,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction break; case ConstPtrSpecialBaseStruct: zig_panic("TODO slice const inner struct"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO slice const inner error union code"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO slice const inner error union payload"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO slice const inner optional payload"); case ConstPtrSpecialHardCodedAddr: array_val = nullptr; abs_offset = 0; @@ -18967,6 +19120,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction break; case ConstPtrSpecialFunction: zig_panic("TODO slice of ptr cast from function"); + case ConstPtrSpecialNull: + zig_panic("TODO slice of null ptr"); } } else if (is_slice(array_type)) { ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node); @@ -18997,6 +19152,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction break; case ConstPtrSpecialBaseStruct: zig_panic("TODO slice const inner struct"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO slice const inner error union code"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO slice const inner error union payload"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO slice const inner optional payload"); case ConstPtrSpecialHardCodedAddr: array_val = nullptr; abs_offset = 0; @@ -19004,6 +19165,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction break; case ConstPtrSpecialFunction: zig_panic("TODO slice of slice cast from function"); + case ConstPtrSpecialNull: + zig_panic("TODO slice of null"); } } else { zig_unreachable(); @@ -19069,6 +19232,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction zig_unreachable(); case ConstPtrSpecialBaseStruct: zig_panic("TODO"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO"); case ConstPtrSpecialHardCodedAddr: init_const_ptr_hard_coded_addr(ira->codegen, ptr_val, parent_ptr->type->data.pointer.child_type, @@ -19077,6 +19246,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction break; case ConstPtrSpecialFunction: zig_panic("TODO"); + case ConstPtrSpecialNull: + zig_panic("TODO"); } ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; @@ -19432,7 +19603,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct return ira->codegen->invalid_instruction; if (err_union_val->special != ConstValSpecialRuntime) { - return ir_const_bool(ira, &instruction->base, (err_union_val->data.x_err_union.err != nullptr)); + ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; + return ir_const_bool(ira, &instruction->base, (err != nullptr)); } } @@ -19458,48 +19630,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct } } -static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, - IrInstructionUnwrapErrCode *instruction) -{ - IrInstruction *value = instruction->value->child; - if (type_is_invalid(value->value.type)) +static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) { + IrInstruction *base_ptr = instruction->err_union->child; + if (type_is_invalid(base_ptr->value.type)) return ira->codegen->invalid_instruction; - ZigType *ptr_type = value->value.type; + ZigType *ptr_type = base_ptr->value.type; // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing. assert(ptr_type->id == ZigTypeIdPointer); ZigType *type_entry = ptr_type->data.pointer.child_type; - if (type_is_invalid(type_entry)) { + if (type_is_invalid(type_entry)) return ira->codegen->invalid_instruction; - } else if (type_entry->id == ZigTypeIdErrorUnion) { - if (instr_is_comptime(value)) { - ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); - if (!ptr_val) - return ira->codegen->invalid_instruction; - ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); - if (err_union_val == nullptr) - return ira->codegen->invalid_instruction; - if (err_union_val->special != ConstValSpecialRuntime) { - ErrorTableEntry *err = err_union_val->data.x_err_union.err; - assert(err); - IrInstruction *result = ir_const(ira, &instruction->base, - type_entry->data.error_union.err_set_type); - result->value.data.x_err_set = err; - return result; - } - } - - IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, value); - result->value.type = type_entry->data.error_union.err_set_type; - return result; - } else { - ir_add_error(ira, value, + if (type_entry->id != ZigTypeIdErrorUnion) { + ir_add_error(ira, base_ptr, buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); return ira->codegen->invalid_instruction; } + + if (instr_is_comptime(base_ptr)) { + ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad); + if (!ptr_val) + return ira->codegen->invalid_instruction; + ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); + if (err_union_val == nullptr) + return ira->codegen->invalid_instruction; + if (err_union_val->special != ConstValSpecialRuntime) { + ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; + assert(err); + + IrInstruction *result = ir_const(ira, &instruction->base, + type_entry->data.error_union.err_set_type); + result->value.data.x_err_set = err; + return result; + } + } + + IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb, + instruction->base.scope, instruction->base.source_node, base_ptr); + result->value.type = type_entry->data.error_union.err_set_type; + return result; } static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, @@ -19515,48 +19686,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, assert(ptr_type->id == ZigTypeIdPointer); ZigType *type_entry = ptr_type->data.pointer.child_type; - if (type_is_invalid(type_entry)) { + if (type_is_invalid(type_entry)) return ira->codegen->invalid_instruction; - } else if (type_entry->id == ZigTypeIdErrorUnion) { - ZigType *payload_type = type_entry->data.error_union.payload_type; - if (type_is_invalid(payload_type)) { - return ira->codegen->invalid_instruction; - } - ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type, - ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, - PtrLenSingle, 0, 0, 0); - if (instr_is_comptime(value)) { - ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); - if (!ptr_val) - return ira->codegen->invalid_instruction; - ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); - if (err_union_val == nullptr) - return ira->codegen->invalid_instruction; - if (err_union_val->special != ConstValSpecialRuntime) { - ErrorTableEntry *err = err_union_val->data.x_err_union.err; - if (err != nullptr) { - ir_add_error(ira, &instruction->base, - buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name))); - return ira->codegen->invalid_instruction; - } - IrInstruction *result = ir_const(ira, &instruction->base, result_type); - result->value.data.x_ptr.special = ConstPtrSpecialRef; - result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload; - return result; - } - } - - IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on); - result->value.type = result_type; - return result; - } else { + if (type_entry->id != ZigTypeIdErrorUnion) { ir_add_error(ira, value, buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); return ira->codegen->invalid_instruction; } + ZigType *payload_type = type_entry->data.error_union.payload_type; + if (type_is_invalid(payload_type)) + return ira->codegen->invalid_instruction; + + ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type, + ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, + PtrLenSingle, 0, 0, 0); + if (instr_is_comptime(value)) { + ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); + if (!ptr_val) + return ira->codegen->invalid_instruction; + ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); + if (err_union_val == nullptr) + return ira->codegen->invalid_instruction; + if (err_union_val->special != ConstValSpecialRuntime) { + ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; + if (err != nullptr) { + ir_add_error(ira, &instruction->base, + buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name))); + return ira->codegen->invalid_instruction; + } + + IrInstruction *result = ir_const(ira, &instruction->base, result_type); + result->value.data.x_ptr.special = ConstPtrSpecialRef; + result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload; + return result; + } + } + + IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, + instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on); + result->value.type = result_type; + return result; } static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { @@ -19973,7 +20144,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 return ira->codegen->invalid_instruction; } - IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type); + IrInstruction *result = ir_const(ira, target, result_type); copy_const_val(&result->value, val, false); result->value.type = result_type; return result; @@ -20021,8 +20192,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ if (!val) return ira->codegen->invalid_instruction; - IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node, - dest_type); + IrInstruction *result = ir_const(ira, source_instr, dest_type); copy_const_val(&result->value, val, false); result->value.type = dest_type; return result; @@ -20045,9 +20215,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ return ira->codegen->invalid_instruction; } - IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope, - source_instr->source_node, nullptr, ptr); - casted_ptr->value.type = dest_type; + IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr); if (type_has_bits(dest_type) && !type_has_bits(src_type)) { ErrorMsg *msg = ir_add_error(ira, source_instr, @@ -20073,7 +20241,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ return result; } -static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) { +static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) { IrInstruction *dest_type_value = instruction->dest_type->child; ZigType *dest_type = ir_resolve_type(ira, dest_type_value); if (type_is_invalid(dest_type)) @@ -20211,15 +20379,29 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem))) return err; } - break; + return ErrorNone; case ConstArraySpecialUndef: zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type"); case ConstArraySpecialBuf: zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type"); } - - return ErrorNone; + zig_unreachable(); } + case ZigTypeIdEnum: + switch (val->type->data.enumeration.layout) { + case ContainerLayoutAuto: + zig_panic("TODO buf_read_value_bytes enum auto"); + case ContainerLayoutPacked: + zig_panic("TODO buf_read_value_bytes enum packed"); + case ContainerLayoutExtern: { + ZigType *tag_int_type = val->type->data.enumeration.tag_int_type; + assert(tag_int_type->id == ZigTypeIdInt); + bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count, + codegen->is_big_endian, tag_int_type->data.integral.is_signed); + return ErrorNone; + } + } + zig_unreachable(); case ZigTypeIdStruct: switch (val->type->data.structure.layout) { case ContainerLayoutAuto: { @@ -20258,8 +20440,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou zig_panic("TODO buf_read_value_bytes error union"); case ZigTypeIdErrorSet: zig_panic("TODO buf_read_value_bytes pure error type"); - case ZigTypeIdEnum: - zig_panic("TODO buf_read_value_bytes enum type"); case ZigTypeIdFn: zig_panic("TODO buf_read_value_bytes fn type"); case ZigTypeIdUnion: @@ -20426,8 +20606,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, case TldIdContainer: case TldIdCompTime: zig_unreachable(); - case TldIdVar: - { + case TldIdVar: { TldVar *tld_var = (TldVar *)tld; ZigVar *var = tld_var->var; @@ -20445,8 +20624,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, return ir_get_deref(ira, &instruction->base, var_ptr); } } - case TldIdFn: - { + case TldIdFn: { TldFn *tld_fn = (TldFn *)tld; ZigFn *fn_entry = tld_fn->fn_entry; assert(fn_entry->type_entry); @@ -20492,8 +20670,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru if (!val) return ira->codegen->invalid_instruction; if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { - IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, usize); + IrInstruction *result = ir_const(ira, &instruction->base, usize); bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr); result->value.type = usize; return result; @@ -21331,6 +21508,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio case IrInstructionIdErrWrapCode: case IrInstructionIdErrWrapPayload: case IrInstructionIdCast: + case IrInstructionIdDeclVarGen: + case IrInstructionIdPtrCastGen: + case IrInstructionIdCmpxchgGen: zig_unreachable(); case IrInstructionIdReturn: @@ -21341,8 +21521,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction); case IrInstructionIdBinOp: return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction); - case IrInstructionIdDeclVar: - return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction); + case IrInstructionIdDeclVarSrc: + return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction); case IrInstructionIdLoadPtr: return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); case IrInstructionIdStorePtr: @@ -21387,8 +21567,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction); case IrInstructionIdTestNonNull: return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction); - case IrInstructionIdUnwrapOptional: - return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction); + case IrInstructionIdOptionalUnwrapPtr: + return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction); case IrInstructionIdClz: return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction); case IrInstructionIdCtz: @@ -21429,8 +21609,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction); case IrInstructionIdEmbedFile: return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction); - case IrInstructionIdCmpxchg: - return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction); + case IrInstructionIdCmpxchgSrc: + return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction); case IrInstructionIdFence: return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction); case IrInstructionIdTruncate: @@ -21497,8 +21677,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction); case IrInstructionIdPanic: return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction); - case IrInstructionIdPtrCast: - return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction); + case IrInstructionIdPtrCastSrc: + return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction); case IrInstructionIdBitCast: return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction); case IrInstructionIdIntToPtr: @@ -21682,7 +21862,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdBr: case IrInstructionIdCondBr: case IrInstructionIdSwitchBr: - case IrInstructionIdDeclVar: + case IrInstructionIdDeclVarSrc: + case IrInstructionIdDeclVarGen: case IrInstructionIdStorePtr: case IrInstructionIdCall: case IrInstructionIdReturn: @@ -21697,7 +21878,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdCInclude: case IrInstructionIdCDefine: case IrInstructionIdCUndef: - case IrInstructionIdCmpxchg: case IrInstructionIdFence: case IrInstructionIdMemset: case IrInstructionIdMemcpy: @@ -21725,6 +21905,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdMergeErrRetTraces: case IrInstructionIdMarkErrRetTracePtr: case IrInstructionIdAtomicRmw: + case IrInstructionIdCmpxchgGen: + case IrInstructionIdCmpxchgSrc: return true; case IrInstructionIdPhi: @@ -21750,7 +21932,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdSliceType: case IrInstructionIdSizeOf: case IrInstructionIdTestNonNull: - case IrInstructionIdUnwrapOptional: + case IrInstructionIdOptionalUnwrapPtr: case IrInstructionIdClz: case IrInstructionIdCtz: case IrInstructionIdPopCount: @@ -21777,7 +21959,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdErrWrapPayload: case IrInstructionIdFnProto: case IrInstructionIdTestComptime: - case IrInstructionIdPtrCast: + case IrInstructionIdPtrCastSrc: + case IrInstructionIdPtrCastGen: case IrInstructionIdBitCast: case IrInstructionIdWidenOrShorten: case IrInstructionIdPtrToInt: diff --git a/src/ir.hpp b/src/ir.hpp index 7af1d7f52b..0a7c614812 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -13,7 +13,7 @@ bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable); bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); -IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, +ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, IrExecutable *parent_exec); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index b5099db86a..a3ec8e9d35 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction } } -static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) { +static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) { const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; const char *name = buf_ptr(&decl_var_instruction->var->name); if (decl_var_instruction->var_type) { @@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) { } static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) { - fprintf(irp->f, "*"); ir_print_other_instruction(irp, instruction->ptr); + fprintf(irp->f, ".*"); } static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { @@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { fprintf(irp->f, ")"); } -static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) { - fprintf(irp->f, "*"); +static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) { ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, " != null"); } -static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) { - fprintf(irp->f, "&??*"); - ir_print_other_instruction(irp, instruction->value); +static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) { + fprintf(irp->f, "&"); + ir_print_other_instruction(irp, instruction->base_ptr); + fprintf(irp->f, ".*.?"); if (!instruction->safety_check_on) { fprintf(irp->f, " // no safety"); } @@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio fprintf(irp->f, ")"); } -static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) { +static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) { fprintf(irp->f, "@cmpxchg("); ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ", "); @@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) { fprintf(irp->f, ")"); } +static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) { + fprintf(irp->f, "@cmpxchg("); + ir_print_other_instruction(irp, instruction->ptr); + fprintf(irp->f, ", "); + ir_print_other_instruction(irp, instruction->cmp_value); + fprintf(irp->f, ", "); + ir_print_other_instruction(irp, instruction->new_value); + fprintf(irp->f, ", TODO print atomic orders)"); +} + static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) { fprintf(irp->f, "@fence("); ir_print_other_instruction(irp, instruction->order_value); @@ -820,13 +830,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) { } static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) { - fprintf(irp->f, "@unwrapErrorCode("); - ir_print_other_instruction(irp, instruction->value); + fprintf(irp->f, "UnwrapErrorCode("); + ir_print_other_instruction(irp, instruction->err_union); fprintf(irp->f, ")"); } static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) { - fprintf(irp->f, "@unwrapErrorPayload("); + fprintf(irp->f, "ErrorUnionFieldPayload("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); if (!instruction->safety_check_on) { @@ -879,7 +889,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst fprintf(irp->f, ")"); } -static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { +static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) { fprintf(irp->f, "@ptrCast("); if (instruction->dest_type) { ir_print_other_instruction(irp, instruction->dest_type); @@ -889,6 +899,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { fprintf(irp->f, ")"); } +static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) { + fprintf(irp->f, "@ptrCast("); + ir_print_other_instruction(irp, instruction->ptr); + fprintf(irp->f, ")"); +} + static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { fprintf(irp->f, "@bitCast("); if (instruction->dest_type) { @@ -900,7 +916,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { } static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) { - fprintf(irp->f, "@widenOrShorten("); + fprintf(irp->f, "WidenOrShorten("); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } @@ -1323,6 +1339,20 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) { fprintf(irp->f, ")"); } +static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) { + ZigVar *var = decl_var_instruction->var; + const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; + const char *name = buf_ptr(&decl_var_instruction->var->name); + fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name), + var->align_bytes); + + ir_print_other_instruction(irp, decl_var_instruction->init_value); + if (decl_var_instruction->var->is_comptime != nullptr) { + fprintf(irp->f, " // comptime = "); + ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime); + } +} + static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) { fprintf(irp->f, "@bswap("); if (instruction->type != nullptr) { @@ -1361,8 +1391,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdBinOp: ir_print_bin_op(irp, (IrInstructionBinOp *)instruction); break; - case IrInstructionIdDeclVar: - ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction); + case IrInstructionIdDeclVarSrc: + ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction); break; case IrInstructionIdCast: ir_print_cast(irp, (IrInstructionCast *)instruction); @@ -1452,10 +1482,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { ir_print_size_of(irp, (IrInstructionSizeOf *)instruction); break; case IrInstructionIdTestNonNull: - ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction); + ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction); break; - case IrInstructionIdUnwrapOptional: - ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction); + case IrInstructionIdOptionalUnwrapPtr: + ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction); break; case IrInstructionIdCtz: ir_print_ctz(irp, (IrInstructionCtz *)instruction); @@ -1508,8 +1538,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdEmbedFile: ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction); break; - case IrInstructionIdCmpxchg: - ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction); + case IrInstructionIdCmpxchgSrc: + ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction); + break; + case IrInstructionIdCmpxchgGen: + ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction); break; case IrInstructionIdFence: ir_print_fence(irp, (IrInstructionFence *)instruction); @@ -1607,8 +1640,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdTestComptime: ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); break; - case IrInstructionIdPtrCast: - ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction); + case IrInstructionIdPtrCastSrc: + ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction); + break; + case IrInstructionIdPtrCastGen: + ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction); break; case IrInstructionIdBitCast: ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction); @@ -1775,6 +1811,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdCheckRuntimeScope: ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction); break; + case IrInstructionIdDeclVarGen: + ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction); + break; } fprintf(irp->f, "\n"); } diff --git a/src/parser.cpp b/src/parser.cpp index 077365995e..81bd469d1c 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse else_body = ast_expect(pc, body_parser); } - assert(res->type == NodeTypeTestExpr); + assert(res->type == NodeTypeIfOptional); if (err_payload != nullptr) { AstNodeTestExpr old = res->data.test_expr; res->type = NodeTypeIfErrorExpr; @@ -990,7 +990,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { if (requires_semi && else_body == nullptr) expect_token(pc, TokenIdSemicolon); - assert(res->type == NodeTypeTestExpr); + assert(res->type == NodeTypeIfOptional); if (err_payload != nullptr) { AstNodeTestExpr old = res->data.test_expr; res->type = NodeTypeIfErrorExpr; @@ -2204,7 +2204,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) { Optional opt_payload = ast_parse_ptr_payload(pc); PtrPayload payload; - AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first); + AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first); res->data.test_expr.target_node = condition; if (opt_payload.unwrap(&payload)) { res->data.test_expr.var_symbol = token_buf(payload.payload); @@ -2999,7 +2999,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont visit_field(&node->data.if_err_expr.then_node, visit, context); visit_field(&node->data.if_err_expr.else_node, visit, context); break; - case NodeTypeTestExpr: + case NodeTypeIfOptional: visit_field(&node->data.test_expr.target_node, visit, context); visit_field(&node->data.test_expr.then_node, visit, context); visit_field(&node->data.test_expr.else_node, visit, context); diff --git a/std/event/fs.zig b/std/event/fs.zig index 1b8e1aa5dc..7e77b3e6e2 100644 --- a/std/event/fs.zig +++ b/std/event/fs.zig @@ -1307,32 +1307,29 @@ pub fn Watch(comptime V: type) type { const test_tmp_dir = "std_event_fs_test"; -test "write a file, watch it, write it again" { - if (builtin.os == builtin.Os.windows) { - // TODO this test is disabled on windows until the coroutine rewrite is finished. - // https://github.com/ziglang/zig/issues/1363 - return error.SkipZigTest; - } - var da = std.heap.DirectAllocator.init(); - defer da.deinit(); - - const allocator = &da.allocator; - - // TODO move this into event loop too - try os.makePath(allocator, test_tmp_dir); - defer os.deleteTree(allocator, test_tmp_dir) catch {}; - - var loop: Loop = undefined; - try loop.initMultiThreaded(allocator); - defer loop.deinit(); - - var result: anyerror!void = error.ResultNeverWritten; - const handle = try async testFsWatchCantFail(&loop, &result); - defer cancel handle; - - loop.run(); - return result; -} +// TODO this test is disabled until the coroutine rewrite is finished. +//test "write a file, watch it, write it again" { +// return error.SkipZigTest; +// var da = std.heap.DirectAllocator.init(); +// defer da.deinit(); +// +// const allocator = &da.allocator; +// +// // TODO move this into event loop too +// try os.makePath(allocator, test_tmp_dir); +// defer os.deleteTree(allocator, test_tmp_dir) catch {}; +// +// var loop: Loop = undefined; +// try loop.initMultiThreaded(allocator); +// defer loop.deinit(); +// +// var result: anyerror!void = error.ResultNeverWritten; +// const handle = try async testFsWatchCantFail(&loop, &result); +// defer cancel handle; +// +// loop.run(); +// return result; +//} async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void { result.* = await (async testFsWatch(loop) catch unreachable); diff --git a/test/behavior.zig b/test/behavior.zig deleted file mode 100644 index 10cd08dad7..0000000000 --- a/test/behavior.zig +++ /dev/null @@ -1,82 +0,0 @@ -const builtin = @import("builtin"); - -comptime { - _ = @import("cases/align.zig"); - _ = @import("cases/alignof.zig"); - _ = @import("cases/array.zig"); - _ = @import("cases/asm.zig"); - _ = @import("cases/atomics.zig"); - _ = @import("cases/bitcast.zig"); - _ = @import("cases/bool.zig"); - _ = @import("cases/bswap.zig"); - _ = @import("cases/bitreverse.zig"); - _ = @import("cases/bugs/1076.zig"); - _ = @import("cases/bugs/1111.zig"); - _ = @import("cases/bugs/1277.zig"); - _ = @import("cases/bugs/1322.zig"); - _ = @import("cases/bugs/1381.zig"); - _ = @import("cases/bugs/1421.zig"); - _ = @import("cases/bugs/1442.zig"); - _ = @import("cases/bugs/1486.zig"); - _ = @import("cases/bugs/394.zig"); - _ = @import("cases/bugs/655.zig"); - _ = @import("cases/bugs/656.zig"); - _ = @import("cases/bugs/726.zig"); - _ = @import("cases/bugs/828.zig"); - _ = @import("cases/bugs/920.zig"); - _ = @import("cases/byval_arg_var.zig"); - _ = @import("cases/cancel.zig"); - _ = @import("cases/cast.zig"); - _ = @import("cases/const_slice_child.zig"); - _ = @import("cases/coroutine_await_struct.zig"); - _ = @import("cases/coroutines.zig"); - _ = @import("cases/defer.zig"); - _ = @import("cases/enum.zig"); - _ = @import("cases/enum_with_members.zig"); - _ = @import("cases/error.zig"); - _ = @import("cases/eval.zig"); - _ = @import("cases/field_parent_ptr.zig"); - _ = @import("cases/fn.zig"); - _ = @import("cases/fn_in_struct_in_comptime.zig"); - _ = @import("cases/for.zig"); - _ = @import("cases/generics.zig"); - _ = @import("cases/if.zig"); - _ = @import("cases/import.zig"); - _ = @import("cases/incomplete_struct_param_tld.zig"); - _ = @import("cases/inttoptr.zig"); - _ = @import("cases/ir_block_deps.zig"); - _ = @import("cases/math.zig"); - _ = @import("cases/merge_error_sets.zig"); - _ = @import("cases/misc.zig"); - _ = @import("cases/namespace_depends_on_compile_var/index.zig"); - _ = @import("cases/new_stack_call.zig"); - _ = @import("cases/null.zig"); - _ = @import("cases/optional.zig"); - _ = @import("cases/pointers.zig"); - _ = @import("cases/popcount.zig"); - _ = @import("cases/ptrcast.zig"); - _ = @import("cases/pub_enum/index.zig"); - _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); - _ = @import("cases/reflection.zig"); - _ = @import("cases/sizeof_and_typeof.zig"); - _ = @import("cases/slice.zig"); - _ = @import("cases/struct.zig"); - _ = @import("cases/struct_contains_null_ptr_itself.zig"); - _ = @import("cases/struct_contains_slice_of_itself.zig"); - _ = @import("cases/switch.zig"); - _ = @import("cases/switch_prong_err_enum.zig"); - _ = @import("cases/switch_prong_implicit_cast.zig"); - _ = @import("cases/syntax.zig"); - _ = @import("cases/this.zig"); - _ = @import("cases/truncate.zig"); - _ = @import("cases/try.zig"); - _ = @import("cases/type_info.zig"); - _ = @import("cases/undefined.zig"); - _ = @import("cases/underscore.zig"); - _ = @import("cases/union.zig"); - _ = @import("cases/var_args.zig"); - _ = @import("cases/void.zig"); - _ = @import("cases/while.zig"); - _ = @import("cases/widening.zig"); - _ = @import("cases/bit_shifting.zig"); -} diff --git a/test/cases/array.zig b/test/cases/array.zig deleted file mode 100644 index 7c63a649a8..0000000000 --- a/test/cases/array.zig +++ /dev/null @@ -1,173 +0,0 @@ -const assert = @import("std").debug.assert; -const mem = @import("std").mem; - -test "arrays" { - var array: [5]u32 = undefined; - - var i: u32 = 0; - while (i < 5) { - array[i] = i + 1; - i = array[i]; - } - - i = 0; - var accumulator = u32(0); - while (i < 5) { - accumulator += array[i]; - - i += 1; - } - - assert(accumulator == 15); - assert(getArrayLen(array) == 5); -} -fn getArrayLen(a: []const u32) usize { - return a.len; -} - -test "void arrays" { - var array: [4]void = undefined; - array[0] = void{}; - array[1] = array[2]; - assert(@sizeOf(@typeOf(array)) == 0); - assert(array.len == 4); -} - -test "array literal" { - const hex_mult = []u16{ - 4096, - 256, - 16, - 1, - }; - - assert(hex_mult.len == 4); - assert(hex_mult[1] == 256); -} - -test "array dot len const expr" { - assert(comptime x: { - break :x some_array.len == 4; - }); -} - -const ArrayDotLenConstExpr = struct { - y: [some_array.len]u8, -}; -const some_array = []u8{ - 0, - 1, - 2, - 3, -}; - -test "nested arrays" { - const array_of_strings = [][]const u8{ - "hello", - "this", - "is", - "my", - "thing", - }; - for (array_of_strings) |s, i| { - if (i == 0) assert(mem.eql(u8, s, "hello")); - if (i == 1) assert(mem.eql(u8, s, "this")); - if (i == 2) assert(mem.eql(u8, s, "is")); - if (i == 3) assert(mem.eql(u8, s, "my")); - if (i == 4) assert(mem.eql(u8, s, "thing")); - } -} - -var s_array: [8]Sub = undefined; -const Sub = struct { - b: u8, -}; -const Str = struct { - a: []Sub, -}; -test "set global var array via slice embedded in struct" { - var s = Str{ .a = s_array[0..] }; - - s.a[0].b = 1; - s.a[1].b = 2; - s.a[2].b = 3; - - assert(s_array[0].b == 1); - assert(s_array[1].b == 2); - assert(s_array[2].b == 3); -} - -test "array literal with specified size" { - var array = [2]u8{ - 1, - 2, - }; - assert(array[0] == 1); - assert(array[1] == 2); -} - -test "array child property" { - var x: [5]i32 = undefined; - assert(@typeOf(x).Child == i32); -} - -test "array len property" { - var x: [5]i32 = undefined; - assert(@typeOf(x).len == 5); -} - -test "array len field" { - var arr = [4]u8{ 0, 0, 0, 0 }; - var ptr = &arr; - assert(arr.len == 4); - comptime assert(arr.len == 4); - assert(ptr.len == 4); - comptime assert(ptr.len == 4); -} - -test "single-item pointer to array indexing and slicing" { - testSingleItemPtrArrayIndexSlice(); - comptime testSingleItemPtrArrayIndexSlice(); -} - -fn testSingleItemPtrArrayIndexSlice() void { - var array = "aaaa"; - doSomeMangling(&array); - assert(mem.eql(u8, "azya", array)); -} - -fn doSomeMangling(array: *[4]u8) void { - array[1] = 'z'; - array[2..3][0] = 'y'; -} - -test "implicit cast single-item pointer" { - testImplicitCastSingleItemPtr(); - comptime testImplicitCastSingleItemPtr(); -} - -fn testImplicitCastSingleItemPtr() void { - var byte: u8 = 100; - const slice = (*[1]u8)(&byte)[0..]; - slice[0] += 1; - assert(byte == 101); -} - -fn testArrayByValAtComptime(b: [2]u8) u8 { - return b[0]; -} - -test "comptime evalutating function that takes array by value" { - const arr = []u8{ 0, 1 }; - _ = comptime testArrayByValAtComptime(arr); - _ = comptime testArrayByValAtComptime(arr); -} - -test "implicit comptime in array type size" { - var arr: [plusOne(10)]bool = undefined; - assert(arr.len == 11); -} - -fn plusOne(x: u32) u32 { - return x + 1; -} diff --git a/test/cases/asm.zig b/test/cases/asm.zig deleted file mode 100644 index 63e37c857c..0000000000 --- a/test/cases/asm.zig +++ /dev/null @@ -1,48 +0,0 @@ -const config = @import("builtin"); -const assert = @import("std").debug.assert; - -comptime { - if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { - asm volatile ( - \\.globl aoeu; - \\.type aoeu, @function; - \\.set aoeu, derp; - ); - } -} - -test "module level assembly" { - if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { - assert(aoeu() == 1234); - } -} - -test "output constraint modifiers" { - // This is only testing compilation. - var a: u32 = 3; - asm volatile ("" : [_]"=m,r"(a) : : ""); - asm volatile ("" : [_]"=r,m"(a) : : ""); -} - -test "alternative constraints" { - // Make sure we allow commas as a separator for alternative constraints. - var a: u32 = 3; - asm volatile ("" : [_]"=r,m"(a) : [_]"r,m"(a) : ""); -} - -test "sized integer/float in asm input" { - asm volatile ("" : : [_]"m"(usize(3)) : ""); - asm volatile ("" : : [_]"m"(i15(-3)) : ""); - asm volatile ("" : : [_]"m"(u3(3)) : ""); - asm volatile ("" : : [_]"m"(i3(3)) : ""); - asm volatile ("" : : [_]"m"(u121(3)) : ""); - asm volatile ("" : : [_]"m"(i121(3)) : ""); - asm volatile ("" : : [_]"m"(f32(3.17)) : ""); - asm volatile ("" : : [_]"m"(f64(3.17)) : ""); -} - -extern fn aoeu() i32; - -export fn derp() i32 { - return 1234; -} diff --git a/test/cases/bitreverse.zig b/test/cases/bitreverse.zig deleted file mode 100644 index 3721e68a94..0000000000 --- a/test/cases/bitreverse.zig +++ /dev/null @@ -1,81 +0,0 @@ -const std = @import("std"); -const assert = std.debug.assert; -const minInt = std.math.minInt; - -test "@bitreverse" { - comptime testBitReverse(); - testBitReverse(); -} - -fn testBitReverse() void { - // using comptime_ints, unsigned - assert(@bitreverse(u0, 0) == 0); - assert(@bitreverse(u5, 0x12) == 0x9); - assert(@bitreverse(u8, 0x12) == 0x48); - assert(@bitreverse(u16, 0x1234) == 0x2c48); - assert(@bitreverse(u24, 0x123456) == 0x6a2c48); - assert(@bitreverse(u32, 0x12345678) == 0x1e6a2c48); - assert(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48); - assert(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48); - assert(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48); - assert(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48); - assert(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48); - - // using runtime uints, unsigned - var num0: u0 = 0; - assert(@bitreverse(u0, num0) == 0); - var num5: u5 = 0x12; - assert(@bitreverse(u5, num5) == 0x9); - var num8: u8 = 0x12; - assert(@bitreverse(u8, num8) == 0x48); - var num16: u16 = 0x1234; - assert(@bitreverse(u16, num16) == 0x2c48); - var num24: u24 = 0x123456; - assert(@bitreverse(u24, num24) == 0x6a2c48); - var num32: u32 = 0x12345678; - assert(@bitreverse(u32, num32) == 0x1e6a2c48); - var num40: u40 = 0x123456789a; - assert(@bitreverse(u40, num40) == 0x591e6a2c48); - var num48: u48 = 0x123456789abc; - assert(@bitreverse(u48, num48) == 0x3d591e6a2c48); - var num56: u56 = 0x123456789abcde; - assert(@bitreverse(u56, num56) == 0x7b3d591e6a2c48); - var num64: u64 = 0x123456789abcdef1; - assert(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48); - var num128: u128 = 0x123456789abcdef11121314151617181; - assert(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48); - - // using comptime_ints, signed, positive - assert(@bitreverse(i0, 0) == 0); - assert(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8( 0x49))); - assert(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16( 0x2c48))); - assert(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24( 0x6a2c48))); - assert(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32( 0x1e6a2c48))); - assert(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40( 0x591e6a2c48))); - assert(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48( 0x3d591e6a2c48))); - assert(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56( 0x7b3d591e6a2c48))); - assert(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64,u64(0x8f7b3d591e6a2c48))); - assert(@bitreverse(i128, @bitCast(i128,u128(0x123456789abcdef11121314151617181))) == @bitCast(i128,u128(0x818e868a828c84888f7b3d591e6a2c48))); - - // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm. - var neg5: i5 = minInt(i5) + 1; - assert(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5)); - var neg8: i8 = -18; - assert(@bitreverse(i8, -18) == @bitreverse(i8, neg8)); - var neg16: i16 = -32694; - assert(@bitreverse(i16, -32694) == @bitreverse(i16, neg16)); - var neg24: i24 = -6773785; - assert(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24)); - var neg32: i32 = -16773785; - assert(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32)); - var neg40: i40 = minInt(i40) + 12345; - assert(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40)); - var neg48: i48 = minInt(i48) + 12345; - assert(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48)); - var neg56: i56 = minInt(i56) + 12345; - assert(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56)); - var neg64: i64 = minInt(i64) + 12345; - assert(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64)); - var neg128: i128 = minInt(i128) + 12345; - assert(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128)); -} diff --git a/test/cases/bswap.zig b/test/cases/bswap.zig deleted file mode 100644 index 57993077e1..0000000000 --- a/test/cases/bswap.zig +++ /dev/null @@ -1,32 +0,0 @@ -const std = @import("std"); -const assert = std.debug.assert; - -test "@bswap" { - comptime testByteSwap(); - testByteSwap(); -} - -fn testByteSwap() void { - assert(@bswap(u0, 0) == 0); - assert(@bswap(u8, 0x12) == 0x12); - assert(@bswap(u16, 0x1234) == 0x3412); - assert(@bswap(u24, 0x123456) == 0x563412); - assert(@bswap(u32, 0x12345678) == 0x78563412); - assert(@bswap(u40, 0x123456789a) == 0x9a78563412); - assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412); - assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412); - assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412); - assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412); - - assert(@bswap(i0, 0) == 0); - assert(@bswap(i8, -50) == -50); - assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412))); - assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412))); - assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412))); - assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412))); - assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412))); - assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412))); - assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412))); - assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == - @bitCast(i128, u128(0x8171615141312111f1debc9a78563412))); -} diff --git a/test/cases/import.zig b/test/cases/import.zig deleted file mode 100644 index 6d6d4b0208..0000000000 --- a/test/cases/import.zig +++ /dev/null @@ -1,10 +0,0 @@ -const assert = @import("std").debug.assert; -const a_namespace = @import("import/a_namespace.zig"); - -test "call fn via namespace lookup" { - assert(a_namespace.foo() == 1234); -} - -test "importing the same thing gives the same import" { - assert(@import("std") == @import("std")); -} diff --git a/test/cases/optional.zig b/test/cases/optional.zig deleted file mode 100644 index d43682bbec..0000000000 --- a/test/cases/optional.zig +++ /dev/null @@ -1,30 +0,0 @@ -const assert = @import("std").debug.assert; - -pub const EmptyStruct = struct {}; - -test "optional pointer to size zero struct" { - var e = EmptyStruct{}; - var o: ?*EmptyStruct = &e; - assert(o != null); -} - -test "equality compare nullable pointers" { - testNullPtrsEql(); - comptime testNullPtrsEql(); -} - -fn testNullPtrsEql() void { - var number: i32 = 1234; - - var x: ?*i32 = null; - var y: ?*i32 = null; - assert(x == y); - y = &number; - assert(x != y); - assert(x != &number); - assert(&number != x); - x = &number; - assert(x == y); - assert(x == &number); - assert(&number == x); -} diff --git a/test/cases/popcount.zig b/test/cases/popcount.zig deleted file mode 100644 index 7dc7f28c0e..0000000000 --- a/test/cases/popcount.zig +++ /dev/null @@ -1,24 +0,0 @@ -const assert = @import("std").debug.assert; - -test "@popCount" { - comptime testPopCount(); - testPopCount(); -} - -fn testPopCount() void { - { - var x: u32 = 0xaa; - assert(@popCount(x) == 4); - } - { - var x: u32 = 0xaaaaaaaa; - assert(@popCount(x) == 16); - } - { - var x: i16 = -1; - assert(@popCount(x) == 16); - } - comptime { - assert(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24); - } -} diff --git a/test/cases/reflection.zig b/test/cases/reflection.zig deleted file mode 100644 index b9b8aff4e1..0000000000 --- a/test/cases/reflection.zig +++ /dev/null @@ -1,95 +0,0 @@ -const assert = @import("std").debug.assert; -const mem = @import("std").mem; -const reflection = @This(); - -test "reflection: array, pointer, optional, error union type child" { - comptime { - assert(([10]u8).Child == u8); - assert((*u8).Child == u8); - assert((anyerror!u8).Payload == u8); - assert((?u8).Child == u8); - } -} - -test "reflection: function return type, var args, and param types" { - comptime { - assert(@typeOf(dummy).ReturnType == i32); - assert(!@typeOf(dummy).is_var_args); - assert(@typeOf(dummy_varargs).is_var_args); - assert(@typeOf(dummy).arg_count == 3); - assert(@ArgType(@typeOf(dummy), 0) == bool); - assert(@ArgType(@typeOf(dummy), 1) == i32); - assert(@ArgType(@typeOf(dummy), 2) == f32); - } -} - -fn dummy(a: bool, b: i32, c: f32) i32 { - return 1234; -} -fn dummy_varargs(args: ...) void {} - -test "reflection: struct member types and names" { - comptime { - assert(@memberCount(Foo) == 3); - - assert(@memberType(Foo, 0) == i32); - assert(@memberType(Foo, 1) == bool); - assert(@memberType(Foo, 2) == void); - - assert(mem.eql(u8, @memberName(Foo, 0), "one")); - assert(mem.eql(u8, @memberName(Foo, 1), "two")); - assert(mem.eql(u8, @memberName(Foo, 2), "three")); - } -} - -test "reflection: enum member types and names" { - comptime { - assert(@memberCount(Bar) == 4); - - assert(@memberType(Bar, 0) == void); - assert(@memberType(Bar, 1) == i32); - assert(@memberType(Bar, 2) == bool); - assert(@memberType(Bar, 3) == f64); - - assert(mem.eql(u8, @memberName(Bar, 0), "One")); - assert(mem.eql(u8, @memberName(Bar, 1), "Two")); - assert(mem.eql(u8, @memberName(Bar, 2), "Three")); - assert(mem.eql(u8, @memberName(Bar, 3), "Four")); - } -} - -test "reflection: @field" { - var f = Foo{ - .one = 42, - .two = true, - .three = void{}, - }; - - assert(f.one == f.one); - assert(@field(f, "o" ++ "ne") == f.one); - assert(@field(f, "t" ++ "wo") == f.two); - assert(@field(f, "th" ++ "ree") == f.three); - assert(@field(Foo, "const" ++ "ant") == Foo.constant); - assert(@field(Bar, "O" ++ "ne") == Bar.One); - assert(@field(Bar, "T" ++ "wo") == Bar.Two); - assert(@field(Bar, "Th" ++ "ree") == Bar.Three); - assert(@field(Bar, "F" ++ "our") == Bar.Four); - assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2)); - @field(f, "o" ++ "ne") = 4; - assert(f.one == 4); -} - -const Foo = struct { - const constant = 52; - - one: i32, - two: bool, - three: void, -}; - -const Bar = union(enum) { - One: void, - Two: i32, - Three: bool, - Four: f64, -}; diff --git a/test/cases/sizeof_and_typeof.zig b/test/cases/sizeof_and_typeof.zig deleted file mode 100644 index 11c6b2f6ba..0000000000 --- a/test/cases/sizeof_and_typeof.zig +++ /dev/null @@ -1,69 +0,0 @@ -const builtin = @import("builtin"); -const assert = @import("std").debug.assert; - -test "@sizeOf and @typeOf" { - const y: @typeOf(x) = 120; - assert(@sizeOf(@typeOf(y)) == 2); -} -const x: u16 = 13; -const z: @typeOf(x) = 19; - -const A = struct { - a: u8, - b: u32, - c: u8, - d: u3, - e: u5, - f: u16, - g: u16, -}; - -const P = packed struct { - a: u8, - b: u32, - c: u8, - d: u3, - e: u5, - f: u16, - g: u16, -}; - -test "@byteOffsetOf" { - // Packed structs have fixed memory layout - assert(@byteOffsetOf(P, "a") == 0); - assert(@byteOffsetOf(P, "b") == 1); - assert(@byteOffsetOf(P, "c") == 5); - assert(@byteOffsetOf(P, "d") == 6); - assert(@byteOffsetOf(P, "e") == 6); - assert(@byteOffsetOf(P, "f") == 7); - assert(@byteOffsetOf(P, "g") == 9); - - // Normal struct fields can be moved/padded - var a: A = undefined; - assert(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a")); - assert(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b")); - assert(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c")); - assert(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d")); - assert(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e")); - assert(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f")); - assert(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g")); -} - -test "@bitOffsetOf" { - // Packed structs have fixed memory layout - assert(@bitOffsetOf(P, "a") == 0); - assert(@bitOffsetOf(P, "b") == 8); - assert(@bitOffsetOf(P, "c") == 40); - assert(@bitOffsetOf(P, "d") == 48); - assert(@bitOffsetOf(P, "e") == 51); - assert(@bitOffsetOf(P, "f") == 56); - assert(@bitOffsetOf(P, "g") == 72); - - assert(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a")); - assert(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b")); - assert(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c")); - assert(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d")); - assert(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e")); - assert(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); - assert(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); -} diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig deleted file mode 100644 index cec532d5d3..0000000000 --- a/test/cases/type_info.zig +++ /dev/null @@ -1,264 +0,0 @@ -const assert = @import("std").debug.assert; -const mem = @import("std").mem; -const TypeInfo = @import("builtin").TypeInfo; -const TypeId = @import("builtin").TypeId; - -test "type info: tag type, void info" { - testBasic(); - comptime testBasic(); -} - -fn testBasic() void { - assert(@TagType(TypeInfo) == TypeId); - const void_info = @typeInfo(void); - assert(TypeId(void_info) == TypeId.Void); - assert(void_info.Void == {}); -} - -test "type info: integer, floating point type info" { - testIntFloat(); - comptime testIntFloat(); -} - -fn testIntFloat() void { - const u8_info = @typeInfo(u8); - assert(TypeId(u8_info) == TypeId.Int); - assert(!u8_info.Int.is_signed); - assert(u8_info.Int.bits == 8); - - const f64_info = @typeInfo(f64); - assert(TypeId(f64_info) == TypeId.Float); - assert(f64_info.Float.bits == 64); -} - -test "type info: pointer type info" { - testPointer(); - comptime testPointer(); -} - -fn testPointer() void { - const u32_ptr_info = @typeInfo(*u32); - assert(TypeId(u32_ptr_info) == TypeId.Pointer); - assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); - assert(u32_ptr_info.Pointer.is_const == false); - assert(u32_ptr_info.Pointer.is_volatile == false); - assert(u32_ptr_info.Pointer.alignment == @alignOf(u32)); - assert(u32_ptr_info.Pointer.child == u32); -} - -test "type info: unknown length pointer type info" { - testUnknownLenPtr(); - comptime testUnknownLenPtr(); -} - -fn testUnknownLenPtr() void { - const u32_ptr_info = @typeInfo([*]const volatile f64); - assert(TypeId(u32_ptr_info) == TypeId.Pointer); - assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); - assert(u32_ptr_info.Pointer.is_const == true); - assert(u32_ptr_info.Pointer.is_volatile == true); - assert(u32_ptr_info.Pointer.alignment == @alignOf(f64)); - assert(u32_ptr_info.Pointer.child == f64); -} - -test "type info: slice type info" { - testSlice(); - comptime testSlice(); -} - -fn testSlice() void { - const u32_slice_info = @typeInfo([]u32); - assert(TypeId(u32_slice_info) == TypeId.Pointer); - assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); - assert(u32_slice_info.Pointer.is_const == false); - assert(u32_slice_info.Pointer.is_volatile == false); - assert(u32_slice_info.Pointer.alignment == 4); - assert(u32_slice_info.Pointer.child == u32); -} - -test "type info: array type info" { - testArray(); - comptime testArray(); -} - -fn testArray() void { - const arr_info = @typeInfo([42]bool); - assert(TypeId(arr_info) == TypeId.Array); - assert(arr_info.Array.len == 42); - assert(arr_info.Array.child == bool); -} - -test "type info: optional type info" { - testOptional(); - comptime testOptional(); -} - -fn testOptional() void { - const null_info = @typeInfo(?void); - assert(TypeId(null_info) == TypeId.Optional); - assert(null_info.Optional.child == void); -} - -test "type info: promise info" { - testPromise(); - comptime testPromise(); -} - -fn testPromise() void { - const null_promise_info = @typeInfo(promise); - assert(TypeId(null_promise_info) == TypeId.Promise); - assert(null_promise_info.Promise.child == null); - - const promise_info = @typeInfo(promise->usize); - assert(TypeId(promise_info) == TypeId.Promise); - assert(promise_info.Promise.child.? == usize); -} - -test "type info: error set, error union info" { - testErrorSet(); - comptime testErrorSet(); -} - -fn testErrorSet() void { - const TestErrorSet = error{ - First, - Second, - Third, - }; - - const error_set_info = @typeInfo(TestErrorSet); - assert(TypeId(error_set_info) == TypeId.ErrorSet); - assert(error_set_info.ErrorSet.errors.len == 3); - assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); - assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third)); - - const error_union_info = @typeInfo(TestErrorSet!usize); - assert(TypeId(error_union_info) == TypeId.ErrorUnion); - assert(error_union_info.ErrorUnion.error_set == TestErrorSet); - assert(error_union_info.ErrorUnion.payload == usize); -} - -test "type info: enum info" { - testEnum(); - comptime testEnum(); -} - -fn testEnum() void { - const Os = enum { - Windows, - Macos, - Linux, - FreeBSD, - }; - - const os_info = @typeInfo(Os); - assert(TypeId(os_info) == TypeId.Enum); - assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); - assert(os_info.Enum.fields.len == 4); - assert(mem.eql(u8, os_info.Enum.fields[1].name, "Macos")); - assert(os_info.Enum.fields[3].value == 3); - assert(os_info.Enum.tag_type == u2); - assert(os_info.Enum.defs.len == 0); -} - -test "type info: union info" { - testUnion(); - comptime testUnion(); -} - -fn testUnion() void { - const typeinfo_info = @typeInfo(TypeInfo); - assert(TypeId(typeinfo_info) == TypeId.Union); - assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); - assert(typeinfo_info.Union.tag_type.? == TypeId); - assert(typeinfo_info.Union.fields.len == 24); - assert(typeinfo_info.Union.fields[4].enum_field != null); - assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4); - assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); - assert(typeinfo_info.Union.defs.len == 20); - - const TestNoTagUnion = union { - Foo: void, - Bar: u32, - }; - - const notag_union_info = @typeInfo(TestNoTagUnion); - assert(TypeId(notag_union_info) == TypeId.Union); - assert(notag_union_info.Union.tag_type == null); - assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); - assert(notag_union_info.Union.fields.len == 2); - assert(notag_union_info.Union.fields[0].enum_field == null); - assert(notag_union_info.Union.fields[1].field_type == u32); - - const TestExternUnion = extern union { - foo: *c_void, - }; - - const extern_union_info = @typeInfo(TestExternUnion); - assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); - assert(extern_union_info.Union.tag_type == null); - assert(extern_union_info.Union.fields[0].enum_field == null); - assert(extern_union_info.Union.fields[0].field_type == *c_void); -} - -test "type info: struct info" { - testStruct(); - comptime testStruct(); -} - -fn testStruct() void { - const struct_info = @typeInfo(TestStruct); - assert(TypeId(struct_info) == TypeId.Struct); - assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); - assert(struct_info.Struct.fields.len == 3); - assert(struct_info.Struct.fields[1].offset == null); - assert(struct_info.Struct.fields[2].field_type == *TestStruct); - assert(struct_info.Struct.defs.len == 2); - assert(struct_info.Struct.defs[0].is_pub); - assert(!struct_info.Struct.defs[0].data.Fn.is_extern); - assert(struct_info.Struct.defs[0].data.Fn.lib_name == null); - assert(struct_info.Struct.defs[0].data.Fn.return_type == void); - assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void); -} - -const TestStruct = packed struct { - const Self = @This(); - - fieldA: usize, - fieldB: void, - fieldC: *Self, - - pub fn foo(self: *const Self) void {} -}; - -test "type info: function type info" { - testFunction(); - comptime testFunction(); -} - -fn testFunction() void { - const fn_info = @typeInfo(@typeOf(foo)); - assert(TypeId(fn_info) == TypeId.Fn); - assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); - assert(fn_info.Fn.is_generic); - assert(fn_info.Fn.args.len == 2); - assert(fn_info.Fn.is_var_args); - assert(fn_info.Fn.return_type == null); - assert(fn_info.Fn.async_allocator_type == null); - - const test_instance: TestStruct = undefined; - const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); - assert(TypeId(bound_fn_info) == TypeId.BoundFn); - assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct); -} - -fn foo(comptime a: usize, b: bool, args: ...) usize { - return 0; -} - -test "typeInfo with comptime parameter in struct fn def" { - const S = struct { - pub fn func(comptime x: f32) void {} - }; - comptime var info = @typeInfo(S); -} diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 0754f223e8..bc1ef660c3 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3220,7 +3220,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ return 2; \\} , - ".tmp_source.zig:2:15: error: unable to infer expression type", + ".tmp_source.zig:2:15: error: values of type 'comptime_int' must be comptime known", ); cases.add( @@ -3566,7 +3566,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(a)); } , - ".tmp_source.zig:2:11: error: expected type, found 'i32'", + ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'", ); cases.add( diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig new file mode 100644 index 0000000000..e545a4c418 --- /dev/null +++ b/test/stage1/behavior.zig @@ -0,0 +1,80 @@ +comptime { + _ = @import("behavior/align.zig"); + _ = @import("behavior/alignof.zig"); + _ = @import("behavior/array.zig"); + _ = @import("behavior/asm.zig"); + _ = @import("behavior/atomics.zig"); + _ = @import("behavior/bit_shifting.zig"); + _ = @import("behavior/bitcast.zig"); + _ = @import("behavior/bitreverse.zig"); + _ = @import("behavior/bool.zig"); + _ = @import("behavior/bswap.zig"); + _ = @import("behavior/bugs/1076.zig"); + _ = @import("behavior/bugs/1111.zig"); + _ = @import("behavior/bugs/1277.zig"); + _ = @import("behavior/bugs/1322.zig"); + _ = @import("behavior/bugs/1381.zig"); + _ = @import("behavior/bugs/1421.zig"); + _ = @import("behavior/bugs/1442.zig"); + _ = @import("behavior/bugs/1486.zig"); + _ = @import("behavior/bugs/394.zig"); + _ = @import("behavior/bugs/655.zig"); + _ = @import("behavior/bugs/656.zig"); + _ = @import("behavior/bugs/726.zig"); + _ = @import("behavior/bugs/828.zig"); + _ = @import("behavior/bugs/920.zig"); + _ = @import("behavior/byval_arg_var.zig"); + _ = @import("behavior/cancel.zig"); + _ = @import("behavior/cast.zig"); + _ = @import("behavior/const_slice_child.zig"); + _ = @import("behavior/coroutine_await_struct.zig"); + _ = @import("behavior/coroutines.zig"); + _ = @import("behavior/defer.zig"); + _ = @import("behavior/enum.zig"); + _ = @import("behavior/enum_with_members.zig"); + _ = @import("behavior/error.zig"); + _ = @import("behavior/eval.zig"); + _ = @import("behavior/field_parent_ptr.zig"); + _ = @import("behavior/fn.zig"); + _ = @import("behavior/fn_in_struct_in_comptime.zig"); + _ = @import("behavior/for.zig"); + _ = @import("behavior/generics.zig"); + _ = @import("behavior/if.zig"); + _ = @import("behavior/import.zig"); + _ = @import("behavior/incomplete_struct_param_tld.zig"); + _ = @import("behavior/inttoptr.zig"); + _ = @import("behavior/ir_block_deps.zig"); + _ = @import("behavior/math.zig"); + _ = @import("behavior/merge_error_sets.zig"); + _ = @import("behavior/misc.zig"); + _ = @import("behavior/namespace_depends_on_compile_var/index.zig"); + _ = @import("behavior/new_stack_call.zig"); + _ = @import("behavior/null.zig"); + _ = @import("behavior/optional.zig"); + _ = @import("behavior/pointers.zig"); + _ = @import("behavior/popcount.zig"); + _ = @import("behavior/ptrcast.zig"); + _ = @import("behavior/pub_enum/index.zig"); + _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); + _ = @import("behavior/reflection.zig"); + _ = @import("behavior/sizeof_and_typeof.zig"); + _ = @import("behavior/slice.zig"); + _ = @import("behavior/struct.zig"); + _ = @import("behavior/struct_contains_null_ptr_itself.zig"); + _ = @import("behavior/struct_contains_slice_of_itself.zig"); + _ = @import("behavior/switch.zig"); + _ = @import("behavior/switch_prong_err_enum.zig"); + _ = @import("behavior/switch_prong_implicit_cast.zig"); + _ = @import("behavior/syntax.zig"); + _ = @import("behavior/this.zig"); + _ = @import("behavior/truncate.zig"); + _ = @import("behavior/try.zig"); + _ = @import("behavior/type_info.zig"); + _ = @import("behavior/undefined.zig"); + _ = @import("behavior/underscore.zig"); + _ = @import("behavior/union.zig"); + _ = @import("behavior/var_args.zig"); + _ = @import("behavior/void.zig"); + _ = @import("behavior/while.zig"); + _ = @import("behavior/widening.zig"); +} diff --git a/test/cases/align.zig b/test/stage1/behavior/align.zig similarity index 69% rename from test/cases/align.zig rename to test/stage1/behavior/align.zig index 3dff57feb8..aa7a93ad84 100644 --- a/test/cases/align.zig +++ b/test/stage1/behavior/align.zig @@ -1,13 +1,13 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const builtin = @import("builtin"); var foo: u8 align(4) = 100; test "global variable alignment" { - assert(@typeOf(&foo).alignment == 4); - assert(@typeOf(&foo) == *align(4) u8); + assertOrPanic(@typeOf(&foo).alignment == 4); + assertOrPanic(@typeOf(&foo) == *align(4) u8); const slice = (*[1]u8)(&foo)[0..]; - assert(@typeOf(slice) == []align(4) u8); + assertOrPanic(@typeOf(slice) == []align(4) u8); } fn derp() align(@sizeOf(usize) * 2) i32 { @@ -17,9 +17,9 @@ fn noop1() align(1) void {} fn noop4() align(4) void {} test "function alignment" { - assert(derp() == 1234); - assert(@typeOf(noop1) == fn () align(1) void); - assert(@typeOf(noop4) == fn () align(4) void); + assertOrPanic(derp() == 1234); + assertOrPanic(@typeOf(noop1) == fn () align(1) void); + assertOrPanic(@typeOf(noop4) == fn () align(4) void); noop1(); noop4(); } @@ -30,7 +30,7 @@ var baz: packed struct { } = undefined; test "packed struct alignment" { - assert(@typeOf(&baz.b) == *align(1) u32); + assertOrPanic(@typeOf(&baz.b) == *align(1) u32); } const blah: packed struct { @@ -40,17 +40,17 @@ const blah: packed struct { } = undefined; test "bit field alignment" { - assert(@typeOf(&blah.b) == *align(1:3:1) const u3); + assertOrPanic(@typeOf(&blah.b) == *align(1:3:1) const u3); } test "default alignment allows unspecified in type syntax" { - assert(*u32 == *align(@alignOf(u32)) u32); + assertOrPanic(*u32 == *align(@alignOf(u32)) u32); } test "implicitly decreasing pointer alignment" { const a: u32 align(4) = 3; const b: u32 align(8) = 4; - assert(addUnaligned(&a, &b) == 7); + assertOrPanic(addUnaligned(&a, &b) == 7); } fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { @@ -60,7 +60,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { test "implicitly decreasing slice alignment" { const a: u32 align(4) = 3; const b: u32 align(8) = 4; - assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7); + assertOrPanic(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7); } fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { return a[0] + b[0]; @@ -77,7 +77,7 @@ fn testBytesAlign(b: u8) void { b, }; const ptr = @ptrCast(*u32, &bytes[0]); - assert(ptr.* == 0x33333333); + assertOrPanic(ptr.* == 0x33333333); } test "specifying alignment allows slice cast" { @@ -91,13 +91,13 @@ fn testBytesAlignSlice(b: u8) void { b, }; const slice: []u32 = @bytesToSlice(u32, bytes[0..]); - assert(slice[0] == 0x33333333); + assertOrPanic(slice[0] == 0x33333333); } test "@alignCast pointers" { var x: u32 align(4) = 1; expectsOnly1(&x); - assert(x == 2); + assertOrPanic(x == 2); } fn expectsOnly1(x: *align(1) u32) void { expects4(@alignCast(4, x)); @@ -113,7 +113,7 @@ test "@alignCast slices" { }; const slice = array[0..]; sliceExpectsOnly1(slice); - assert(slice[0] == 2); + assertOrPanic(slice[0] == 2); } fn sliceExpectsOnly1(slice: []align(1) u32) void { sliceExpects4(@alignCast(4, slice)); @@ -128,7 +128,7 @@ test "implicitly decreasing fn alignment" { } fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void { - assert(ptr() == answer); + assertOrPanic(ptr() == answer); } fn alignedSmall() align(8) i32 { @@ -139,7 +139,7 @@ fn alignedBig() align(16) i32 { } test "@alignCast functions" { - assert(fnExpectsOnly1(simple4) == 0x19); + assertOrPanic(fnExpectsOnly1(simple4) == 0x19); } fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 { return fnExpects4(@alignCast(4, ptr)); @@ -152,9 +152,9 @@ fn simple4() align(4) i32 { } test "generic function with align param" { - assert(whyWouldYouEverDoThis(1) == 0x1); - assert(whyWouldYouEverDoThis(4) == 0x1); - assert(whyWouldYouEverDoThis(8) == 0x1); + assertOrPanic(whyWouldYouEverDoThis(1) == 0x1); + assertOrPanic(whyWouldYouEverDoThis(4) == 0x1); + assertOrPanic(whyWouldYouEverDoThis(8) == 0x1); } fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { @@ -164,28 +164,28 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { test "@ptrCast preserves alignment of bigger source" { var x: u32 align(16) = 1234; const ptr = @ptrCast(*u8, &x); - assert(@typeOf(ptr) == *align(16) u8); + assertOrPanic(@typeOf(ptr) == *align(16) u8); } test "runtime known array index has best alignment possible" { // take full advantage of over-alignment var array align(4) = []u8{ 1, 2, 3, 4 }; - assert(@typeOf(&array[0]) == *align(4) u8); - assert(@typeOf(&array[1]) == *u8); - assert(@typeOf(&array[2]) == *align(2) u8); - assert(@typeOf(&array[3]) == *u8); + assertOrPanic(@typeOf(&array[0]) == *align(4) u8); + assertOrPanic(@typeOf(&array[1]) == *u8); + assertOrPanic(@typeOf(&array[2]) == *align(2) u8); + assertOrPanic(@typeOf(&array[3]) == *u8); // because align is too small but we still figure out to use 2 var bigger align(2) = []u64{ 1, 2, 3, 4 }; - assert(@typeOf(&bigger[0]) == *align(2) u64); - assert(@typeOf(&bigger[1]) == *align(2) u64); - assert(@typeOf(&bigger[2]) == *align(2) u64); - assert(@typeOf(&bigger[3]) == *align(2) u64); + assertOrPanic(@typeOf(&bigger[0]) == *align(2) u64); + assertOrPanic(@typeOf(&bigger[1]) == *align(2) u64); + assertOrPanic(@typeOf(&bigger[2]) == *align(2) u64); + assertOrPanic(@typeOf(&bigger[3]) == *align(2) u64); // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 var smaller align(2) = []u32{ 1, 2, 3, 4 }; - comptime assert(@typeOf(smaller[0..]) == []align(2) u32); - comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32); + comptime assertOrPanic(@typeOf(smaller[0..]) == []align(2) u32); + comptime assertOrPanic(@typeOf(smaller[0..].ptr) == [*]align(2) u32); testIndex(smaller[0..].ptr, 0, *align(2) u32); testIndex(smaller[0..].ptr, 1, *align(2) u32); testIndex(smaller[0..].ptr, 2, *align(2) u32); @@ -198,14 +198,14 @@ test "runtime known array index has best alignment possible" { testIndex2(array[0..].ptr, 3, *u8); } fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void { - comptime assert(@typeOf(&smaller[index]) == T); + comptime assertOrPanic(@typeOf(&smaller[index]) == T); } fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void { - comptime assert(@typeOf(&ptr[index]) == T); + comptime assertOrPanic(@typeOf(&ptr[index]) == T); } test "alignstack" { - assert(fnWithAlignedStack() == 1234); + assertOrPanic(fnWithAlignedStack() == 1234); } fn fnWithAlignedStack() i32 { @@ -214,7 +214,7 @@ fn fnWithAlignedStack() i32 { } test "alignment of structs" { - assert(@alignOf(struct { + assertOrPanic(@alignOf(struct { a: i32, b: *i32, }) == @alignOf(usize)); diff --git a/test/cases/alignof.zig b/test/stage1/behavior/alignof.zig similarity index 61% rename from test/cases/alignof.zig rename to test/stage1/behavior/alignof.zig index 433e86e45e..98c805908b 100644 --- a/test/cases/alignof.zig +++ b/test/stage1/behavior/alignof.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const builtin = @import("builtin"); const maxInt = std.math.maxInt; @@ -10,8 +10,9 @@ const Foo = struct { }; test "@alignOf(T) before referencing T" { - comptime assert(@alignOf(Foo) != maxInt(usize)); + comptime assertOrPanic(@alignOf(Foo) != maxInt(usize)); if (builtin.arch == builtin.Arch.x86_64) { - comptime assert(@alignOf(Foo) == 4); + comptime assertOrPanic(@alignOf(Foo) == 4); } } + diff --git a/test/stage1/behavior/array.zig b/test/stage1/behavior/array.zig new file mode 100644 index 0000000000..1183305209 --- /dev/null +++ b/test/stage1/behavior/array.zig @@ -0,0 +1,270 @@ +const assertOrPanic = @import("std").debug.assertOrPanic; +const mem = @import("std").mem; + +test "arrays" { + var array: [5]u32 = undefined; + + var i: u32 = 0; + while (i < 5) { + array[i] = i + 1; + i = array[i]; + } + + i = 0; + var accumulator = u32(0); + while (i < 5) { + accumulator += array[i]; + + i += 1; + } + + assertOrPanic(accumulator == 15); + assertOrPanic(getArrayLen(array) == 5); +} +fn getArrayLen(a: []const u32) usize { + return a.len; +} + +test "void arrays" { + var array: [4]void = undefined; + array[0] = void{}; + array[1] = array[2]; + assertOrPanic(@sizeOf(@typeOf(array)) == 0); + assertOrPanic(array.len == 4); +} + +test "array literal" { + const hex_mult = []u16{ + 4096, + 256, + 16, + 1, + }; + + assertOrPanic(hex_mult.len == 4); + assertOrPanic(hex_mult[1] == 256); +} + +test "array dot len const expr" { + assertOrPanic(comptime x: { + break :x some_array.len == 4; + }); +} + +const ArrayDotLenConstExpr = struct { + y: [some_array.len]u8, +}; +const some_array = []u8{ + 0, + 1, + 2, + 3, +}; + +test "nested arrays" { + const array_of_strings = [][]const u8{ + "hello", + "this", + "is", + "my", + "thing", + }; + for (array_of_strings) |s, i| { + if (i == 0) assertOrPanic(mem.eql(u8, s, "hello")); + if (i == 1) assertOrPanic(mem.eql(u8, s, "this")); + if (i == 2) assertOrPanic(mem.eql(u8, s, "is")); + if (i == 3) assertOrPanic(mem.eql(u8, s, "my")); + if (i == 4) assertOrPanic(mem.eql(u8, s, "thing")); + } +} + +var s_array: [8]Sub = undefined; +const Sub = struct { + b: u8, +}; +const Str = struct { + a: []Sub, +}; +test "set global var array via slice embedded in struct" { + var s = Str{ .a = s_array[0..] }; + + s.a[0].b = 1; + s.a[1].b = 2; + s.a[2].b = 3; + + assertOrPanic(s_array[0].b == 1); + assertOrPanic(s_array[1].b == 2); + assertOrPanic(s_array[2].b == 3); +} + +test "array literal with specified size" { + var array = [2]u8{ + 1, + 2, + }; + assertOrPanic(array[0] == 1); + assertOrPanic(array[1] == 2); +} + +test "array child property" { + var x: [5]i32 = undefined; + assertOrPanic(@typeOf(x).Child == i32); +} + +test "array len property" { + var x: [5]i32 = undefined; + assertOrPanic(@typeOf(x).len == 5); +} + +test "array len field" { + var arr = [4]u8{ 0, 0, 0, 0 }; + var ptr = &arr; + assertOrPanic(arr.len == 4); + comptime assertOrPanic(arr.len == 4); + assertOrPanic(ptr.len == 4); + comptime assertOrPanic(ptr.len == 4); +} + +test "single-item pointer to array indexing and slicing" { + testSingleItemPtrArrayIndexSlice(); + comptime testSingleItemPtrArrayIndexSlice(); +} + +fn testSingleItemPtrArrayIndexSlice() void { + var array = "aaaa"; + doSomeMangling(&array); + assertOrPanic(mem.eql(u8, "azya", array)); +} + +fn doSomeMangling(array: *[4]u8) void { + array[1] = 'z'; + array[2..3][0] = 'y'; +} + +test "implicit cast single-item pointer" { + testImplicitCastSingleItemPtr(); + comptime testImplicitCastSingleItemPtr(); +} + +fn testImplicitCastSingleItemPtr() void { + var byte: u8 = 100; + const slice = (*[1]u8)(&byte)[0..]; + slice[0] += 1; + assertOrPanic(byte == 101); +} + +fn testArrayByValAtComptime(b: [2]u8) u8 { + return b[0]; +} + +test "comptime evalutating function that takes array by value" { + const arr = []u8{ 0, 1 }; + _ = comptime testArrayByValAtComptime(arr); + _ = comptime testArrayByValAtComptime(arr); +} + +test "implicit comptime in array type size" { + var arr: [plusOne(10)]bool = undefined; + assertOrPanic(arr.len == 11); +} + +fn plusOne(x: u32) u32 { + return x + 1; +} + +test "array literal as argument to function" { + const S = struct { + fn entry(two: i32) void { + foo([]i32{ + 1, + 2, + 3, + }); + foo([]i32{ + 1, + two, + 3, + }); + foo2(true, []i32{ + 1, + 2, + 3, + }); + foo2(true, []i32{ + 1, + two, + 3, + }); + } + fn foo(x: []const i32) void { + assertOrPanic(x[0] == 1); + assertOrPanic(x[1] == 2); + assertOrPanic(x[2] == 3); + } + fn foo2(trash: bool, x: []const i32) void { + assertOrPanic(trash); + assertOrPanic(x[0] == 1); + assertOrPanic(x[1] == 2); + assertOrPanic(x[2] == 3); + } + }; + S.entry(2); + comptime S.entry(2); +} + +test "double nested array to const slice cast in array literal" { + const S = struct { + fn entry(two: i32) void { + const cases = [][]const []const i32{ + [][]const i32{[]i32{1}}, + [][]const i32{[]i32{ 2, 3 }}, + [][]const i32{ + []i32{4}, + []i32{ 5, 6, 7 }, + }, + }; + check(cases); + + const cases2 = [][]const i32{ + []i32{1}, + []i32{ two, 3 }, + }; + assertOrPanic(cases2.len == 2); + assertOrPanic(cases2[0].len == 1); + assertOrPanic(cases2[0][0] == 1); + assertOrPanic(cases2[1].len == 2); + assertOrPanic(cases2[1][0] == 2); + assertOrPanic(cases2[1][1] == 3); + + const cases3 = [][]const []const i32{ + [][]const i32{[]i32{1}}, + [][]const i32{[]i32{ two, 3 }}, + [][]const i32{ + []i32{4}, + []i32{ 5, 6, 7 }, + }, + }; + check(cases3); + } + + fn check(cases: []const []const []const i32) void { + assertOrPanic(cases.len == 3); + assertOrPanic(cases[0].len == 1); + assertOrPanic(cases[0][0].len == 1); + assertOrPanic(cases[0][0][0] == 1); + assertOrPanic(cases[1].len == 1); + assertOrPanic(cases[1][0].len == 2); + assertOrPanic(cases[1][0][0] == 2); + assertOrPanic(cases[1][0][1] == 3); + assertOrPanic(cases[2].len == 2); + assertOrPanic(cases[2][0].len == 1); + assertOrPanic(cases[2][0][0] == 4); + assertOrPanic(cases[2][1].len == 3); + assertOrPanic(cases[2][1][0] == 5); + assertOrPanic(cases[2][1][1] == 6); + assertOrPanic(cases[2][1][2] == 7); + } + }; + S.entry(2); + comptime S.entry(2); +} diff --git a/test/stage1/behavior/asm.zig b/test/stage1/behavior/asm.zig new file mode 100644 index 0000000000..48701c5836 --- /dev/null +++ b/test/stage1/behavior/asm.zig @@ -0,0 +1,92 @@ +const config = @import("builtin"); +const assertOrPanic = @import("std").debug.assertOrPanic; + +comptime { + if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { + asm volatile ( + \\.globl aoeu; + \\.type aoeu, @function; + \\.set aoeu, derp; + ); + } +} + +test "module level assembly" { + if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { + assertOrPanic(aoeu() == 1234); + } +} + +test "output constraint modifiers" { + // This is only testing compilation. + var a: u32 = 3; + asm volatile ("" + : [_] "=m,r" (a) + : + : "" + ); + asm volatile ("" + : [_] "=r,m" (a) + : + : "" + ); +} + +test "alternative constraints" { + // Make sure we allow commas as a separator for alternative constraints. + var a: u32 = 3; + asm volatile ("" + : [_] "=r,m" (a) + : [_] "r,m" (a) + : "" + ); +} + +test "sized integer/float in asm input" { + asm volatile ("" + : + : [_] "m" (usize(3)) + : "" + ); + asm volatile ("" + : + : [_] "m" (i15(-3)) + : "" + ); + asm volatile ("" + : + : [_] "m" (u3(3)) + : "" + ); + asm volatile ("" + : + : [_] "m" (i3(3)) + : "" + ); + asm volatile ("" + : + : [_] "m" (u121(3)) + : "" + ); + asm volatile ("" + : + : [_] "m" (i121(3)) + : "" + ); + asm volatile ("" + : + : [_] "m" (f32(3.17)) + : "" + ); + asm volatile ("" + : + : [_] "m" (f64(3.17)) + : "" + ); +} + +extern fn aoeu() i32; + +export fn derp() i32 { + return 1234; +} diff --git a/test/cases/atomics.zig b/test/stage1/behavior/atomics.zig similarity index 65% rename from test/cases/atomics.zig rename to test/stage1/behavior/atomics.zig index 67c9ab3dd1..fa3c5f29a6 100644 --- a/test/cases/atomics.zig +++ b/test/stage1/behavior/atomics.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const builtin = @import("builtin"); const AtomicRmwOp = builtin.AtomicRmwOp; const AtomicOrder = builtin.AtomicOrder; @@ -7,18 +7,18 @@ const AtomicOrder = builtin.AtomicOrder; test "cmpxchg" { var x: i32 = 1234; if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { - assert(x1 == 1234); + assertOrPanic(x1 == 1234); } else { @panic("cmpxchg should have failed"); } while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { - assert(x1 == 1234); + assertOrPanic(x1 == 1234); } - assert(x == 5678); + assertOrPanic(x == 5678); - assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); - assert(x == 42); + assertOrPanic(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); + assertOrPanic(x == 42); } test "fence" { @@ -30,24 +30,24 @@ test "fence" { test "atomicrmw and atomicload" { var data: u8 = 200; testAtomicRmw(&data); - assert(data == 42); + assertOrPanic(data == 42); testAtomicLoad(&data); } fn testAtomicRmw(ptr: *u8) void { const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst); - assert(prev_value == 200); + assertOrPanic(prev_value == 200); comptime { var x: i32 = 1234; const y: i32 = 12345; - assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234); - assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345); + assertOrPanic(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234); + assertOrPanic(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345); } } fn testAtomicLoad(ptr: *u8) void { const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst); - assert(x == 42); + assertOrPanic(x == 42); } test "cmpxchg with ptr" { @@ -56,16 +56,16 @@ test "cmpxchg with ptr" { var data3: i32 = 9101; var x: *i32 = &data1; if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { - assert(x1 == &data1); + assertOrPanic(x1 == &data1); } else { @panic("cmpxchg should have failed"); } while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { - assert(x1 == &data1); + assertOrPanic(x1 == &data1); } - assert(x == &data3); + assertOrPanic(x == &data3); - assert(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); - assert(x == &data2); + assertOrPanic(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); + assertOrPanic(x == &data2); } diff --git a/test/cases/bit_shifting.zig b/test/stage1/behavior/bit_shifting.zig similarity index 90% rename from test/cases/bit_shifting.zig rename to test/stage1/behavior/bit_shifting.zig index 325e765bb0..3290688358 100644 --- a/test/cases/bit_shifting.zig +++ b/test/stage1/behavior/bit_shifting.zig @@ -1,9 +1,9 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type { - assert(Key == @IntType(false, Key.bit_count)); - assert(Key.bit_count >= mask_bit_count); + assertOrPanic(Key == @IntType(false, Key.bit_count)); + assertOrPanic(Key.bit_count >= mask_bit_count); const ShardKey = @IntType(false, mask_bit_count); const shift_amount = Key.bit_count - ShardKey.bit_count; return struct { @@ -77,12 +77,12 @@ fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, c var node_buffer: [node_count]Table.Node = undefined; for (node_buffer) |*node, i| { const key = @intCast(Key, i); - assert(table.get(key) == null); + assertOrPanic(table.get(key) == null); node.init(key, {}); table.put(node); } for (node_buffer) |*node, i| { - assert(table.get(@intCast(Key, i)) == node); + assertOrPanic(table.get(@intCast(Key, i)) == node); } } diff --git a/test/cases/bitcast.zig b/test/stage1/behavior/bitcast.zig similarity index 78% rename from test/cases/bitcast.zig rename to test/stage1/behavior/bitcast.zig index d85a84ed22..19030255e4 100644 --- a/test/cases/bitcast.zig +++ b/test/stage1/behavior/bitcast.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const maxInt = std.math.maxInt; test "@bitCast i32 -> u32" { @@ -8,8 +8,8 @@ test "@bitCast i32 -> u32" { } fn testBitCast_i32_u32() void { - assert(conv(-1) == maxInt(u32)); - assert(conv2(maxInt(u32)) == -1); + assertOrPanic(conv(-1) == maxInt(u32)); + assertOrPanic(conv2(maxInt(u32)) == -1); } fn conv(x: i32) u32 { @@ -27,11 +27,10 @@ test "@bitCast extern enum to its integer type" { fn testBitCastExternEnum() void { var SOCK_DGRAM = @This().B; var sock_dgram = @bitCast(c_int, SOCK_DGRAM); - assert(sock_dgram == 1); + assertOrPanic(sock_dgram == 1); } }; SOCK.testBitCastExternEnum(); comptime SOCK.testBitCastExternEnum(); } - diff --git a/test/stage1/behavior/bitreverse.zig b/test/stage1/behavior/bitreverse.zig new file mode 100644 index 0000000000..97787ace84 --- /dev/null +++ b/test/stage1/behavior/bitreverse.zig @@ -0,0 +1,81 @@ +const std = @import("std"); +const assertOrPanic = std.debug.assertOrPanic; +const minInt = std.math.minInt; + +test "@bitreverse" { + comptime testBitReverse(); + testBitReverse(); +} + +fn testBitReverse() void { + // using comptime_ints, unsigned + assertOrPanic(@bitreverse(u0, 0) == 0); + assertOrPanic(@bitreverse(u5, 0x12) == 0x9); + assertOrPanic(@bitreverse(u8, 0x12) == 0x48); + assertOrPanic(@bitreverse(u16, 0x1234) == 0x2c48); + assertOrPanic(@bitreverse(u24, 0x123456) == 0x6a2c48); + assertOrPanic(@bitreverse(u32, 0x12345678) == 0x1e6a2c48); + assertOrPanic(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48); + assertOrPanic(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48); + assertOrPanic(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48); + assertOrPanic(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48); + assertOrPanic(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48); + + // using runtime uints, unsigned + var num0: u0 = 0; + assertOrPanic(@bitreverse(u0, num0) == 0); + var num5: u5 = 0x12; + assertOrPanic(@bitreverse(u5, num5) == 0x9); + var num8: u8 = 0x12; + assertOrPanic(@bitreverse(u8, num8) == 0x48); + var num16: u16 = 0x1234; + assertOrPanic(@bitreverse(u16, num16) == 0x2c48); + var num24: u24 = 0x123456; + assertOrPanic(@bitreverse(u24, num24) == 0x6a2c48); + var num32: u32 = 0x12345678; + assertOrPanic(@bitreverse(u32, num32) == 0x1e6a2c48); + var num40: u40 = 0x123456789a; + assertOrPanic(@bitreverse(u40, num40) == 0x591e6a2c48); + var num48: u48 = 0x123456789abc; + assertOrPanic(@bitreverse(u48, num48) == 0x3d591e6a2c48); + var num56: u56 = 0x123456789abcde; + assertOrPanic(@bitreverse(u56, num56) == 0x7b3d591e6a2c48); + var num64: u64 = 0x123456789abcdef1; + assertOrPanic(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48); + var num128: u128 = 0x123456789abcdef11121314151617181; + assertOrPanic(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48); + + // using comptime_ints, signed, positive + assertOrPanic(@bitreverse(i0, 0) == 0); + assertOrPanic(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49))); + assertOrPanic(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48))); + assertOrPanic(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48))); + assertOrPanic(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48))); + assertOrPanic(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48))); + assertOrPanic(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48))); + assertOrPanic(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48))); + assertOrPanic(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48))); + assertOrPanic(@bitreverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48))); + + // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm. + var neg5: i5 = minInt(i5) + 1; + assertOrPanic(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5)); + var neg8: i8 = -18; + assertOrPanic(@bitreverse(i8, -18) == @bitreverse(i8, neg8)); + var neg16: i16 = -32694; + assertOrPanic(@bitreverse(i16, -32694) == @bitreverse(i16, neg16)); + var neg24: i24 = -6773785; + assertOrPanic(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24)); + var neg32: i32 = -16773785; + assertOrPanic(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32)); + var neg40: i40 = minInt(i40) + 12345; + assertOrPanic(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40)); + var neg48: i48 = minInt(i48) + 12345; + assertOrPanic(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48)); + var neg56: i56 = minInt(i56) + 12345; + assertOrPanic(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56)); + var neg64: i64 = minInt(i64) + 12345; + assertOrPanic(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64)); + var neg128: i128 = minInt(i128) + 12345; + assertOrPanic(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128)); +} diff --git a/test/cases/bool.zig b/test/stage1/behavior/bool.zig similarity index 50% rename from test/cases/bool.zig rename to test/stage1/behavior/bool.zig index 3e4ac9c1cf..2d7241526f 100644 --- a/test/cases/bool.zig +++ b/test/stage1/behavior/bool.zig @@ -1,25 +1,25 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "bool literals" { - assert(true); - assert(!false); + assertOrPanic(true); + assertOrPanic(!false); } test "cast bool to int" { const t = true; const f = false; - assert(@boolToInt(t) == u32(1)); - assert(@boolToInt(f) == u32(0)); + assertOrPanic(@boolToInt(t) == u32(1)); + assertOrPanic(@boolToInt(f) == u32(0)); nonConstCastBoolToInt(t, f); } fn nonConstCastBoolToInt(t: bool, f: bool) void { - assert(@boolToInt(t) == u32(1)); - assert(@boolToInt(f) == u32(0)); + assertOrPanic(@boolToInt(t) == u32(1)); + assertOrPanic(@boolToInt(f) == u32(0)); } test "bool cmp" { - assert(testBoolCmp(true, false) == false); + assertOrPanic(testBoolCmp(true, false) == false); } fn testBoolCmp(a: bool, b: bool) bool { return a == b; @@ -30,6 +30,6 @@ const global_t = true; const not_global_f = !global_f; const not_global_t = !global_t; test "compile time bool not" { - assert(not_global_f); - assert(!not_global_t); + assertOrPanic(not_global_f); + assertOrPanic(!not_global_t); } diff --git a/test/stage1/behavior/bswap.zig b/test/stage1/behavior/bswap.zig new file mode 100644 index 0000000000..8084538e03 --- /dev/null +++ b/test/stage1/behavior/bswap.zig @@ -0,0 +1,32 @@ +const std = @import("std"); +const assertOrPanic = std.debug.assertOrPanic; + +test "@bswap" { + comptime testByteSwap(); + testByteSwap(); +} + +fn testByteSwap() void { + assertOrPanic(@bswap(u0, 0) == 0); + assertOrPanic(@bswap(u8, 0x12) == 0x12); + assertOrPanic(@bswap(u16, 0x1234) == 0x3412); + assertOrPanic(@bswap(u24, 0x123456) == 0x563412); + assertOrPanic(@bswap(u32, 0x12345678) == 0x78563412); + assertOrPanic(@bswap(u40, 0x123456789a) == 0x9a78563412); + assertOrPanic(@bswap(u48, 0x123456789abc) == 0xbc9a78563412); + assertOrPanic(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412); + assertOrPanic(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412); + assertOrPanic(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412); + + assertOrPanic(@bswap(i0, 0) == 0); + assertOrPanic(@bswap(i8, -50) == -50); + assertOrPanic(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412))); + assertOrPanic(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412))); + assertOrPanic(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412))); + assertOrPanic(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412))); + assertOrPanic(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412))); + assertOrPanic(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412))); + assertOrPanic(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412))); + assertOrPanic(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == + @bitCast(i128, u128(0x8171615141312111f1debc9a78563412))); +} diff --git a/test/cases/bugs/1076.zig b/test/stage1/behavior/bugs/1076.zig similarity index 75% rename from test/cases/bugs/1076.zig rename to test/stage1/behavior/bugs/1076.zig index 7b84312310..69a7e70f7d 100644 --- a/test/cases/bugs/1076.zig +++ b/test/stage1/behavior/bugs/1076.zig @@ -1,6 +1,6 @@ const std = @import("std"); const mem = std.mem; -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; test "comptime code should not modify constant data" { testCastPtrOfArrayToSliceAndPtr(); @@ -11,6 +11,6 @@ fn testCastPtrOfArrayToSliceAndPtr() void { var array = "aoeu"; const x: [*]u8 = &array; x[0] += 1; - assert(mem.eql(u8, array[0..], "boeu")); + assertOrPanic(mem.eql(u8, array[0..], "boeu")); } diff --git a/test/cases/bugs/1111.zig b/test/stage1/behavior/bugs/1111.zig similarity index 100% rename from test/cases/bugs/1111.zig rename to test/stage1/behavior/bugs/1111.zig diff --git a/test/cases/bugs/1277.zig b/test/stage1/behavior/bugs/1277.zig similarity index 100% rename from test/cases/bugs/1277.zig rename to test/stage1/behavior/bugs/1277.zig diff --git a/test/cases/bugs/1322.zig b/test/stage1/behavior/bugs/1322.zig similarity index 66% rename from test/cases/bugs/1322.zig rename to test/stage1/behavior/bugs/1322.zig index 2de92191ec..2e67f4473f 100644 --- a/test/cases/bugs/1322.zig +++ b/test/stage1/behavior/bugs/1322.zig @@ -13,7 +13,7 @@ const C = struct {}; test "tagged union with all void fields but a meaningful tag" { var a: A = A{ .b = B{ .c = C{} } }; - std.debug.assert(@TagType(B)(a.b) == @TagType(B).c); + std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).c); a = A{ .b = B.None }; - std.debug.assert(@TagType(B)(a.b) == @TagType(B).None); + std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).None); } diff --git a/test/cases/bugs/1381.zig b/test/stage1/behavior/bugs/1381.zig similarity index 100% rename from test/cases/bugs/1381.zig rename to test/stage1/behavior/bugs/1381.zig diff --git a/test/cases/bugs/1421.zig b/test/stage1/behavior/bugs/1421.zig similarity index 70% rename from test/cases/bugs/1421.zig rename to test/stage1/behavior/bugs/1421.zig index fcbb8b70e4..fbc932781a 100644 --- a/test/cases/bugs/1421.zig +++ b/test/stage1/behavior/bugs/1421.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const S = struct { fn method() builtin.TypeInfo { @@ -10,5 +10,5 @@ const S = struct { test "functions with return type required to be comptime are generic" { const ti = S.method(); - assert(builtin.TypeId(ti) == builtin.TypeId.Struct); + assertOrPanic(builtin.TypeId(ti) == builtin.TypeId.Struct); } diff --git a/test/cases/bugs/1442.zig b/test/stage1/behavior/bugs/1442.zig similarity index 100% rename from test/cases/bugs/1442.zig rename to test/stage1/behavior/bugs/1442.zig diff --git a/test/cases/bugs/1486.zig b/test/stage1/behavior/bugs/1486.zig similarity index 51% rename from test/cases/bugs/1486.zig rename to test/stage1/behavior/bugs/1486.zig index 98fae36d3a..0483e3828c 100644 --- a/test/cases/bugs/1486.zig +++ b/test/stage1/behavior/bugs/1486.zig @@ -1,11 +1,11 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const ptr = &global; var global: u64 = 123; test "constant pointer to global variable causes runtime load" { global = 1234; - assert(&global == ptr); - assert(ptr.* == 1234); + assertOrPanic(&global == ptr); + assertOrPanic(ptr.* == 1234); } diff --git a/test/cases/bugs/394.zig b/test/stage1/behavior/bugs/394.zig similarity index 68% rename from test/cases/bugs/394.zig rename to test/stage1/behavior/bugs/394.zig index b0afec2357..766ad9e157 100644 --- a/test/cases/bugs/394.zig +++ b/test/stage1/behavior/bugs/394.zig @@ -7,12 +7,12 @@ const S = struct { y: E, }; -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "bug 394 fixed" { const x = S{ .x = 3, .y = E{ .B = 1 }, }; - assert(x.x == 3); + assertOrPanic(x.x == 3); } diff --git a/test/cases/bugs/655.zig b/test/stage1/behavior/bugs/655.zig similarity index 67% rename from test/cases/bugs/655.zig rename to test/stage1/behavior/bugs/655.zig index ebb8da0658..67ba6a231f 100644 --- a/test/cases/bugs/655.zig +++ b/test/stage1/behavior/bugs/655.zig @@ -3,10 +3,10 @@ const other_file = @import("655_other_file.zig"); test "function with *const parameter with type dereferenced by namespace" { const x: other_file.Integer = 1234; - comptime std.debug.assert(@typeOf(&x) == *const other_file.Integer); + comptime std.debug.assertOrPanic(@typeOf(&x) == *const other_file.Integer); foo(&x); } fn foo(x: *const other_file.Integer) void { - std.debug.assert(x.* == 1234); + std.debug.assertOrPanic(x.* == 1234); } diff --git a/test/cases/bugs/655_other_file.zig b/test/stage1/behavior/bugs/655_other_file.zig similarity index 100% rename from test/cases/bugs/655_other_file.zig rename to test/stage1/behavior/bugs/655_other_file.zig diff --git a/test/cases/bugs/656.zig b/test/stage1/behavior/bugs/656.zig similarity index 84% rename from test/cases/bugs/656.zig rename to test/stage1/behavior/bugs/656.zig index f93f0ac4d5..cb37fe67fe 100644 --- a/test/cases/bugs/656.zig +++ b/test/stage1/behavior/bugs/656.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const PrefixOp = union(enum) { Return, @@ -22,7 +22,7 @@ fn foo(a: bool, b: bool) void { PrefixOp.AddrOf => |addr_of_info| { if (b) {} if (addr_of_info.align_expr) |align_expr| { - assert(align_expr == 1234); + assertOrPanic(align_expr == 1234); } }, PrefixOp.Return => {}, diff --git a/test/cases/bugs/726.zig b/test/stage1/behavior/bugs/726.zig similarity index 71% rename from test/cases/bugs/726.zig rename to test/stage1/behavior/bugs/726.zig index 2acc91eb26..ce20480c63 100644 --- a/test/cases/bugs/726.zig +++ b/test/stage1/behavior/bugs/726.zig @@ -1,9 +1,9 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "@ptrCast from const to nullable" { const c: u8 = 4; var x: ?*const u8 = @ptrCast(?*const u8, &c); - assert(x.?.* == 4); + assertOrPanic(x.?.* == 4); } test "@ptrCast from var in empty struct to nullable" { @@ -11,6 +11,6 @@ test "@ptrCast from var in empty struct to nullable" { var c: u8 = 4; }; var x: ?*const u8 = @ptrCast(?*const u8, &container.c); - assert(x.?.* == 4); + assertOrPanic(x.?.* == 4); } diff --git a/test/cases/bugs/828.zig b/test/stage1/behavior/bugs/828.zig similarity index 100% rename from test/cases/bugs/828.zig rename to test/stage1/behavior/bugs/828.zig diff --git a/test/cases/bugs/920.zig b/test/stage1/behavior/bugs/920.zig similarity index 95% rename from test/cases/bugs/920.zig rename to test/stage1/behavior/bugs/920.zig index 2903f05a29..e29c5c4acf 100644 --- a/test/cases/bugs/920.zig +++ b/test/stage1/behavior/bugs/920.zig @@ -60,6 +60,6 @@ test "bug 920 fixed" { }; for (NormalDist1.f) |_, i| { - std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]); + std.debug.assertOrPanic(NormalDist1.f[i] == NormalDist.f[i]); } } diff --git a/test/cases/byval_arg_var.zig b/test/stage1/behavior/byval_arg_var.zig similarity index 70% rename from test/cases/byval_arg_var.zig rename to test/stage1/behavior/byval_arg_var.zig index 826b9cc9e5..14ee212ce0 100644 --- a/test/cases/byval_arg_var.zig +++ b/test/stage1/behavior/byval_arg_var.zig @@ -2,11 +2,11 @@ const std = @import("std"); var result: []const u8 = "wrong"; -test "aoeu" { +test "pass string literal byvalue to a generic var param" { start(); blowUpStack(10); - std.debug.assert(std.mem.eql(u8, result, "string literal")); + std.debug.assertOrPanic(std.mem.eql(u8, result, "string literal")); } fn start() void { diff --git a/test/cases/cancel.zig b/test/stage1/behavior/cancel.zig similarity index 84% rename from test/cases/cancel.zig rename to test/stage1/behavior/cancel.zig index c0f74fd34f..863da4bdb8 100644 --- a/test/cases/cancel.zig +++ b/test/stage1/behavior/cancel.zig @@ -10,9 +10,9 @@ test "cancel forwards" { const p = async<&da.allocator> f1() catch unreachable; cancel p; - std.debug.assert(defer_f1); - std.debug.assert(defer_f2); - std.debug.assert(defer_f3); + std.debug.assertOrPanic(defer_f1); + std.debug.assertOrPanic(defer_f2); + std.debug.assertOrPanic(defer_f3); } async fn f1() void { @@ -47,10 +47,10 @@ test "cancel backwards" { const p = async<&da.allocator> b1() catch unreachable; cancel p; - std.debug.assert(defer_b1); - std.debug.assert(defer_b2); - std.debug.assert(defer_b3); - std.debug.assert(defer_b4); + std.debug.assertOrPanic(defer_b1); + std.debug.assertOrPanic(defer_b2); + std.debug.assertOrPanic(defer_b3); + std.debug.assertOrPanic(defer_b4); } async fn b1() void { diff --git a/test/cases/cast.zig b/test/stage1/behavior/cast.zig similarity index 67% rename from test/cases/cast.zig rename to test/stage1/behavior/cast.zig index bd45bbc00f..61ddcd8135 100644 --- a/test/cases/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const mem = std.mem; const maxInt = std.math.maxInt; @@ -7,12 +7,12 @@ test "int to ptr cast" { const x = usize(13); const y = @intToPtr(*u8, x); const z = @ptrToInt(y); - assert(z == 13); + assertOrPanic(z == 13); } test "integer literal to pointer cast" { const vga_mem = @intToPtr(*u16, 0xB8000); - assert(@ptrToInt(vga_mem) == 0xB8000); + assertOrPanic(@ptrToInt(vga_mem) == 0xB8000); } test "pointer reinterpret const float to int" { @@ -20,7 +20,7 @@ test "pointer reinterpret const float to int" { const float_ptr = &float; const int_ptr = @ptrCast(*const i32, float_ptr); const int_val = int_ptr.*; - assert(int_val == 858993411); + assertOrPanic(int_val == 858993411); } test "implicitly cast indirect pointer to maybe-indirect pointer" { @@ -44,10 +44,10 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" { const p = &s; const q = &p; const r = &q; - assert(42 == S.constConst(q)); - assert(42 == S.maybeConstConst(q)); - assert(42 == S.constConstConst(r)); - assert(42 == S.maybeConstConstConst(r)); + assertOrPanic(42 == S.constConst(q)); + assertOrPanic(42 == S.maybeConstConst(q)); + assertOrPanic(42 == S.constConstConst(r)); + assertOrPanic(42 == S.maybeConstConstConst(r)); } test "explicit cast from integer to error type" { @@ -57,14 +57,14 @@ test "explicit cast from integer to error type" { fn testCastIntToErr(err: anyerror) void { const x = @errorToInt(err); const y = @intToError(x); - assert(error.ItBroke == y); + assertOrPanic(error.ItBroke == y); } test "peer resolve arrays of different size to const slice" { - assert(mem.eql(u8, boolToStr(true), "true")); - assert(mem.eql(u8, boolToStr(false), "false")); - comptime assert(mem.eql(u8, boolToStr(true), "true")); - comptime assert(mem.eql(u8, boolToStr(false), "false")); + assertOrPanic(mem.eql(u8, boolToStr(true), "true")); + assertOrPanic(mem.eql(u8, boolToStr(false), "false")); + comptime assertOrPanic(mem.eql(u8, boolToStr(true), "true")); + comptime assertOrPanic(mem.eql(u8, boolToStr(false), "false")); } fn boolToStr(b: bool) []const u8 { return if (b) "true" else "false"; @@ -77,28 +77,29 @@ test "peer resolve array and const slice" { fn testPeerResolveArrayConstSlice(b: bool) void { const value1 = if (b) "aoeu" else ([]const u8)("zz"); const value2 = if (b) ([]const u8)("zz") else "aoeu"; - assert(mem.eql(u8, value1, "aoeu")); - assert(mem.eql(u8, value2, "zz")); + assertOrPanic(mem.eql(u8, value1, "aoeu")); + assertOrPanic(mem.eql(u8, value2, "zz")); } test "implicitly cast from T to anyerror!?T" { castToOptionalTypeError(1); comptime castToOptionalTypeError(1); } + const A = struct { a: i32, }; fn castToOptionalTypeError(z: i32) void { const x = i32(1); const y: anyerror!?i32 = x; - assert((try y).? == 1); + assertOrPanic((try y).? == 1); const f = z; const g: anyerror!?i32 = f; const a = A{ .a = z }; const b: anyerror!?A = a; - assert((b catch unreachable).?.a == 1); + assertOrPanic((b catch unreachable).?.a == 1); } test "implicitly cast from int to anyerror!?T" { @@ -113,7 +114,7 @@ fn implicitIntLitToOptional() void { test "return null from fn() anyerror!?&T" { const a = returnNullFromOptionalTypeErrorRef(); const b = returnNullLitFromOptionalTypeErrorRef(); - assert((try a) == null and (try b) == null); + assertOrPanic((try a) == null and (try b) == null); } fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { const a: ?*A = null; @@ -124,11 +125,11 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { } test "peer type resolution: ?T and T" { - assert(peerTypeTAndOptionalT(true, false).? == 0); - assert(peerTypeTAndOptionalT(false, false).? == 3); + assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0); + assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3); comptime { - assert(peerTypeTAndOptionalT(true, false).? == 0); - assert(peerTypeTAndOptionalT(false, false).? == 3); + assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0); + assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3); } } fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { @@ -140,11 +141,11 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { } test "peer type resolution: [0]u8 and []const u8" { - assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); - assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); comptime { - assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); - assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); } } fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { @@ -156,8 +157,8 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { } test "implicitly cast from [N]T to ?[]const T" { - assert(mem.eql(u8, castToOptionalSlice().?, "hi")); - comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi")); + assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi")); + comptime assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi")); } fn castToOptionalSlice() ?[]const u8 { @@ -170,7 +171,7 @@ test "implicitly cast from [0]T to anyerror![]T" { } fn testCastZeroArrayToErrSliceMut() void { - assert((gimmeErrOrSlice() catch unreachable).len == 0); + assertOrPanic((gimmeErrOrSlice() catch unreachable).len == 0); } fn gimmeErrOrSlice() anyerror![]u8 { @@ -181,14 +182,14 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { { var data = "hi"; const slice = data[0..]; - assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); - assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); + assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); + assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); } comptime { var data = "hi"; const slice = data[0..]; - assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); - assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); + assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); + assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); } } fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { @@ -206,7 +207,7 @@ test "resolve undefined with integer" { fn testResolveUndefWithInt(b: bool, x: i32) void { const value = if (b) x else undefined; if (b) { - assert(value == x); + assertOrPanic(value == x); } } @@ -218,17 +219,17 @@ test "implicit cast from &const [N]T to []const T" { fn testCastConstArrayRefToConstSlice() void { const blah = "aoeu"; const const_array_ref = &blah; - assert(@typeOf(const_array_ref) == *const [4]u8); + assertOrPanic(@typeOf(const_array_ref) == *const [4]u8); const slice: []const u8 = const_array_ref; - assert(mem.eql(u8, slice, "aoeu")); + assertOrPanic(mem.eql(u8, slice, "aoeu")); } test "peer type resolution: error and [N]T" { // TODO: implicit error!T to error!U where T can implicitly cast to U - //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); - //comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); - assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); - comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); + //assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); + //comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); + assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); + comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); } //fn testPeerErrorAndArray(x: u8) error![]const u8 { @@ -252,9 +253,9 @@ test "@floatToInt" { fn testFloatToInts() void { const x = i32(1e4); - assert(x == 10000); + assertOrPanic(x == 10000); const y = @floatToInt(i32, f32(1e4)); - assert(y == 10000); + assertOrPanic(y == 10000); expectFloatToInt(f16, 255.1, u8, 255); expectFloatToInt(f16, 127.2, i8, 127); expectFloatToInt(f16, -128.2, i8, -128); @@ -265,7 +266,7 @@ fn testFloatToInts() void { } fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void { - assert(@floatToInt(I, f) == i); + assertOrPanic(@floatToInt(I, f) == i); } test "cast u128 to f128 and back" { @@ -274,7 +275,7 @@ test "cast u128 to f128 and back" { } fn testCast128() void { - assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); + assertOrPanic(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); } fn cast128Int(x: f128) u128 { @@ -294,9 +295,9 @@ test "const slice widen cast" { }; const u32_value = @bytesToSlice(u32, bytes[0..])[0]; - assert(u32_value == 0x12121212); + assertOrPanic(u32_value == 0x12121212); - assert(@bitCast(u32, bytes) == 0x12121212); + assertOrPanic(@bitCast(u32, bytes) == 0x12121212); } test "single-item pointer of array to slice and to unknown length pointer" { @@ -308,76 +309,76 @@ fn testCastPtrOfArrayToSliceAndPtr() void { var array = "aoeu"; const x: [*]u8 = &array; x[0] += 1; - assert(mem.eql(u8, array[0..], "boeu")); + assertOrPanic(mem.eql(u8, array[0..], "boeu")); const y: []u8 = &array; y[0] += 1; - assert(mem.eql(u8, array[0..], "coeu")); + assertOrPanic(mem.eql(u8, array[0..], "coeu")); } test "cast *[1][*]const u8 to [*]const ?[*]const u8" { const window_name = [1][*]const u8{c"window name"}; const x: [*]const ?[*]const u8 = &window_name; - assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name")); + assertOrPanic(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name")); } test "@intCast comptime_int" { const result = @intCast(i32, 1234); - assert(@typeOf(result) == i32); - assert(result == 1234); + assertOrPanic(@typeOf(result) == i32); + assertOrPanic(result == 1234); } test "@floatCast comptime_int and comptime_float" { { const result = @floatCast(f16, 1234); - assert(@typeOf(result) == f16); - assert(result == 1234.0); + assertOrPanic(@typeOf(result) == f16); + assertOrPanic(result == 1234.0); } { const result = @floatCast(f16, 1234.0); - assert(@typeOf(result) == f16); - assert(result == 1234.0); + assertOrPanic(@typeOf(result) == f16); + assertOrPanic(result == 1234.0); } { const result = @floatCast(f32, 1234); - assert(@typeOf(result) == f32); - assert(result == 1234.0); + assertOrPanic(@typeOf(result) == f32); + assertOrPanic(result == 1234.0); } { const result = @floatCast(f32, 1234.0); - assert(@typeOf(result) == f32); - assert(result == 1234.0); + assertOrPanic(@typeOf(result) == f32); + assertOrPanic(result == 1234.0); } } test "comptime_int @intToFloat" { { const result = @intToFloat(f16, 1234); - assert(@typeOf(result) == f16); - assert(result == 1234.0); + assertOrPanic(@typeOf(result) == f16); + assertOrPanic(result == 1234.0); } { const result = @intToFloat(f32, 1234); - assert(@typeOf(result) == f32); - assert(result == 1234.0); + assertOrPanic(@typeOf(result) == f32); + assertOrPanic(result == 1234.0); } } test "@bytesToSlice keeps pointer alignment" { var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 }; const numbers = @bytesToSlice(u32, bytes[0..]); - comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32); + comptime assertOrPanic(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32); } test "@intCast i32 to u7" { var x: u128 = maxInt(u128); var y: i32 = 120; var z = x >> @intCast(u7, y); - assert(z == 0xff); + assertOrPanic(z == 0xff); } test "implicit cast undefined to optional" { - assert(MakeType(void).getNull() == null); - assert(MakeType(void).getNonNull() != null); + assertOrPanic(MakeType(void).getNull() == null); + assertOrPanic(MakeType(void).getNonNull() != null); } fn MakeType(comptime T: type) type { @@ -397,16 +398,16 @@ test "implicit cast from *[N]T to ?[*]T" { var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; x = &y; - assert(std.mem.eql(u16, x.?[0..4], y[0..4])); + assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4])); x.?[0] = 8; y[3] = 6; - assert(std.mem.eql(u16, x.?[0..4], y[0..4])); + assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4])); } test "implicit cast from *T to ?*c_void" { var a: u8 = 1; incrementVoidPtrValue(&a); - std.debug.assert(a == 2); + std.debug.assertOrPanic(a == 2); } fn incrementVoidPtrValue(value: ?*c_void) void { @@ -416,7 +417,7 @@ fn incrementVoidPtrValue(value: ?*c_void) void { test "implicit cast from [*]T to ?*c_void" { var a = []u8{ 3, 2, 1 }; incrementVoidPtrArray(a[0..].ptr, 3); - assert(std.mem.eql(u8, a, []u8{ 4, 3, 2 })); + assertOrPanic(std.mem.eql(u8, a, []u8{ 4, 3, 2 })); } fn incrementVoidPtrArray(array: ?*c_void, len: usize) void { @@ -440,27 +441,27 @@ pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize)); pub const PFN_void = extern fn (*c_void) void; fn foobar(func: PFN_void) void { - std.debug.assert(@ptrToInt(func) == maxInt(usize)); + std.debug.assertOrPanic(@ptrToInt(func) == maxInt(usize)); } test "implicit ptr to *c_void" { var a: u32 = 1; var ptr: *c_void = &a; var b: *u32 = @ptrCast(*u32, ptr); - assert(b.* == 1); + assertOrPanic(b.* == 1); var ptr2: ?*c_void = &a; var c: *u32 = @ptrCast(*u32, ptr2.?); - assert(c.* == 1); + assertOrPanic(c.* == 1); } test "@intCast to comptime_int" { - assert(@intCast(comptime_int, 0) == 0); + assertOrPanic(@intCast(comptime_int, 0) == 0); } test "implicit cast comptime numbers to any type when the value fits" { const a: u64 = 255; var b: u8 = a; - assert(b == 255); + assertOrPanic(b == 255); } test "@intToEnum passed a comptime_int to an enum with one item" { @@ -468,5 +469,5 @@ test "@intToEnum passed a comptime_int to an enum with one item" { A, }; const x = @intToEnum(E, 0); - assert(x == E.A); + assertOrPanic(x == E.A); } diff --git a/test/cases/const_slice_child.zig b/test/stage1/behavior/const_slice_child.zig similarity index 80% rename from test/cases/const_slice_child.zig rename to test/stage1/behavior/const_slice_child.zig index 07d02d5df0..5b9b70a558 100644 --- a/test/cases/const_slice_child.zig +++ b/test/stage1/behavior/const_slice_child.zig @@ -1,5 +1,5 @@ const debug = @import("std").debug; -const assert = debug.assert; +const assertOrPanic = debug.assertOrPanic; var argv: [*]const [*]const u8 = undefined; @@ -15,10 +15,10 @@ test "const slice child" { } fn foo(args: [][]const u8) void { - assert(args.len == 3); - assert(streql(args[0], "one")); - assert(streql(args[1], "two")); - assert(streql(args[2], "three")); + assertOrPanic(args.len == 3); + assertOrPanic(streql(args[0], "one")); + assertOrPanic(streql(args[1], "two")); + assertOrPanic(streql(args[2], "three")); } fn bar(argc: usize) void { diff --git a/test/cases/coroutine_await_struct.zig b/test/stage1/behavior/coroutine_await_struct.zig similarity index 86% rename from test/cases/coroutine_await_struct.zig rename to test/stage1/behavior/coroutine_await_struct.zig index 79168715d8..6ca2a301ec 100644 --- a/test/cases/coroutine_await_struct.zig +++ b/test/stage1/behavior/coroutine_await_struct.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const Foo = struct { x: i32, @@ -18,8 +18,8 @@ test "coroutine await struct" { await_seq('f'); resume await_a_promise; await_seq('i'); - assert(await_final_result.x == 1234); - assert(std.mem.eql(u8, await_points, "abcdefghi")); + assertOrPanic(await_final_result.x == 1234); + assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi")); } async fn await_amain() void { await_seq('b'); diff --git a/test/cases/coroutines.zig b/test/stage1/behavior/coroutines.zig similarity index 86% rename from test/cases/coroutines.zig rename to test/stage1/behavior/coroutines.zig index 89490ebc2c..a2327c5060 100644 --- a/test/cases/coroutines.zig +++ b/test/stage1/behavior/coroutines.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; var x: i32 = 1; @@ -9,9 +9,9 @@ test "create a coroutine and cancel it" { defer da.deinit(); const p = try async<&da.allocator> simpleAsyncFn(); - comptime assert(@typeOf(p) == promise->void); + comptime assertOrPanic(@typeOf(p) == promise->void); cancel p; - assert(x == 2); + assertOrPanic(x == 2); } async fn simpleAsyncFn() void { x += 1; @@ -31,7 +31,7 @@ test "coroutine suspend, resume, cancel" { cancel p; seq('g'); - assert(std.mem.eql(u8, points, "abcdefg")); + assertOrPanic(std.mem.eql(u8, points, "abcdefg")); } async fn testAsyncSeq() void { defer seq('e'); @@ -53,9 +53,9 @@ test "coroutine suspend with block" { defer da.deinit(); const p = try async<&da.allocator> testSuspendBlock(); - std.debug.assert(!result); + std.debug.assertOrPanic(!result); resume a_promise; - std.debug.assert(result); + std.debug.assertOrPanic(result); cancel p; } @@ -63,13 +63,13 @@ var a_promise: promise = undefined; var result = false; async fn testSuspendBlock() void { suspend { - comptime assert(@typeOf(@handle()) == promise->void); + comptime assertOrPanic(@typeOf(@handle()) == promise->void); a_promise = @handle(); } //Test to make sure that @handle() works as advertised (issue #1296) //var our_handle: promise = @handle(); - assert( a_promise == @handle() ); + assertOrPanic(a_promise == @handle()); result = true; } @@ -86,8 +86,8 @@ test "coroutine await" { await_seq('f'); resume await_a_promise; await_seq('i'); - assert(await_final_result == 1234); - assert(std.mem.eql(u8, await_points, "abcdefghi")); + assertOrPanic(await_final_result == 1234); + assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi")); } async fn await_amain() void { await_seq('b'); @@ -123,8 +123,8 @@ test "coroutine await early return" { early_seq('a'); const p = async<&da.allocator> early_amain() catch @panic("out of memory"); early_seq('f'); - assert(early_final_result == 1234); - assert(std.mem.eql(u8, early_points, "abcdef")); + assertOrPanic(early_final_result == 1234); + assertOrPanic(std.mem.eql(u8, early_points, "abcdef")); } async fn early_amain() void { early_seq('b'); @@ -170,7 +170,7 @@ test "async function with dot syntax" { defer da.deinit(); const p = try async<&da.allocator> S.foo(); cancel p; - assert(S.y == 2); + assertOrPanic(S.y == 2); } test "async fn pointer in a struct field" { @@ -182,9 +182,9 @@ test "async fn pointer in a struct field" { var da = std.heap.DirectAllocator.init(); defer da.deinit(); const p = (async<&da.allocator> foo.bar(&data)) catch unreachable; - assert(data == 2); + assertOrPanic(data == 2); cancel p; - assert(data == 4); + assertOrPanic(data == 4); } async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void { defer y.* += 2; @@ -199,6 +199,7 @@ test "async fn with inferred error set" { resume p; cancel p; } + async fn failing() !void { suspend; return error.Fail; @@ -220,8 +221,7 @@ test "error return trace across suspend points - async return" { cancel p2; } -// TODO https://github.com/ziglang/zig/issues/760 -fn nonFailing() promise->(anyerror!void) { +fn nonFailing() (promise->anyerror!void) { return async suspendThenFail() catch unreachable; } async fn suspendThenFail() anyerror!void { @@ -230,9 +230,9 @@ async fn suspendThenFail() anyerror!void { } async fn printTrace(p: promise->(anyerror!void)) void { (await p) catch |e| { - std.debug.assert(e == error.Fail); + std.debug.assertOrPanic(e == error.Fail); if (@errorReturnTrace()) |trace| { - assert(trace.index == 1); + assertOrPanic(trace.index == 1); } else switch (builtin.mode) { builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"), builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {}, @@ -246,7 +246,7 @@ test "break from suspend" { var my_result: i32 = 1; const p = try async testBreakFromSuspend(&my_result); cancel p; - std.debug.assert(my_result == 2); + std.debug.assertOrPanic(my_result == 2); } async fn testBreakFromSuspend(my_result: *i32) void { suspend { diff --git a/test/cases/defer.zig b/test/stage1/behavior/defer.zig similarity index 72% rename from test/cases/defer.zig rename to test/stage1/behavior/defer.zig index f9a2b69cd9..6c6c60311e 100644 --- a/test/cases/defer.zig +++ b/test/stage1/behavior/defer.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; var result: [3]u8 = undefined; var index: usize = undefined; @@ -21,18 +21,18 @@ fn runSomeErrorDefers(x: bool) !bool { } test "mixing normal and error defers" { - assert(runSomeErrorDefers(true) catch unreachable); - assert(result[0] == 'c'); - assert(result[1] == 'a'); + assertOrPanic(runSomeErrorDefers(true) catch unreachable); + assertOrPanic(result[0] == 'c'); + assertOrPanic(result[1] == 'a'); const ok = runSomeErrorDefers(false) catch |err| x: { - assert(err == error.FalseNotAllowed); + assertOrPanic(err == error.FalseNotAllowed); break :x true; }; - assert(ok); - assert(result[0] == 'c'); - assert(result[1] == 'b'); - assert(result[2] == 'a'); + assertOrPanic(ok); + assertOrPanic(result[0] == 'c'); + assertOrPanic(result[1] == 'b'); + assertOrPanic(result[2] == 'a'); } test "break and continue inside loop inside defer expression" { @@ -47,7 +47,7 @@ fn testBreakContInDefer(x: usize) void { if (i < 5) continue; if (i == 5) break; } - assert(i == 5); + assertOrPanic(i == 5); } } @@ -59,11 +59,11 @@ test "defer and labeled break" { break :blk; } - assert(i == 1); + assertOrPanic(i == 1); } test "errdefer does not apply to fn inside fn" { - if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad); + if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assertOrPanic(e == error.Bad); } fn testNestedFnErrDefer() anyerror!void { diff --git a/test/cases/enum.zig b/test/stage1/behavior/enum.zig similarity index 84% rename from test/cases/enum.zig rename to test/stage1/behavior/enum.zig index 2dd552488c..9de138ef78 100644 --- a/test/cases/enum.zig +++ b/test/stage1/behavior/enum.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const mem = @import("std").mem; test "enum type" { @@ -11,16 +11,16 @@ test "enum type" { }; const bar = Bar.B; - assert(bar == Bar.B); - assert(@memberCount(Foo) == 3); - assert(@memberCount(Bar) == 4); - assert(@sizeOf(Foo) == @sizeOf(FooNoVoid)); - assert(@sizeOf(Bar) == 1); + assertOrPanic(bar == Bar.B); + assertOrPanic(@memberCount(Foo) == 3); + assertOrPanic(@memberCount(Bar) == 4); + assertOrPanic(@sizeOf(Foo) == @sizeOf(FooNoVoid)); + assertOrPanic(@sizeOf(Bar) == 1); } test "enum as return value" { switch (returnAnInt(13)) { - Foo.One => |value| assert(value == 13), + Foo.One => |value| assertOrPanic(value == 13), else => unreachable, } } @@ -92,14 +92,14 @@ test "enum to int" { } fn shouldEqual(n: Number, expected: u3) void { - assert(@enumToInt(n) == expected); + assertOrPanic(@enumToInt(n) == expected); } test "int to enum" { testIntToEnumEval(3); } fn testIntToEnumEval(x: i32) void { - assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three); + assertOrPanic(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three); } const IntToEnumNumber = enum { Zero, @@ -110,8 +110,8 @@ const IntToEnumNumber = enum { }; test "@tagName" { - assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); - comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); + assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); + comptime assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); } fn testEnumTagNameBare(n: BareNumber) []const u8 { @@ -126,8 +126,8 @@ const BareNumber = enum { test "enum alignment" { comptime { - assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); - assert(@alignOf(AlignTestEnum) >= @alignOf(u64)); + assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); + assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf(u64)); } } @@ -663,10 +663,10 @@ const ValueCount257 = enum { test "enum sizes" { comptime { - assert(@sizeOf(ValueCount1) == 0); - assert(@sizeOf(ValueCount2) == 1); - assert(@sizeOf(ValueCount256) == 1); - assert(@sizeOf(ValueCount257) == 2); + assertOrPanic(@sizeOf(ValueCount1) == 0); + assertOrPanic(@sizeOf(ValueCount2) == 1); + assertOrPanic(@sizeOf(ValueCount256) == 1); + assertOrPanic(@sizeOf(ValueCount257) == 2); } } @@ -685,12 +685,12 @@ test "set enum tag type" { { var x = Small.One; x = Small.Two; - comptime assert(@TagType(Small) == u2); + comptime assertOrPanic(@TagType(Small) == u2); } { var x = Small2.One; x = Small2.Two; - comptime assert(@TagType(Small2) == u2); + comptime assertOrPanic(@TagType(Small2) == u2); } } @@ -737,17 +737,17 @@ const bit_field_1 = BitFieldOfEnums{ test "bit field access with enum fields" { var data = bit_field_1; - assert(getA(&data) == A.Two); - assert(getB(&data) == B.Three3); - assert(getC(&data) == C.Four4); - comptime assert(@sizeOf(BitFieldOfEnums) == 1); + assertOrPanic(getA(&data) == A.Two); + assertOrPanic(getB(&data) == B.Three3); + assertOrPanic(getC(&data) == C.Four4); + comptime assertOrPanic(@sizeOf(BitFieldOfEnums) == 1); data.b = B.Four3; - assert(data.b == B.Four3); + assertOrPanic(data.b == B.Four3); data.a = A.Three; - assert(data.a == A.Three); - assert(data.b == B.Four3); + assertOrPanic(data.a == A.Three); + assertOrPanic(data.b == B.Four3); } fn getA(data: *const BitFieldOfEnums) A { @@ -768,7 +768,7 @@ test "casting enum to its tag type" { } fn testCastEnumToTagType(value: Small2) void { - assert(@enumToInt(value) == 1); + assertOrPanic(@enumToInt(value) == 1); } const MultipleChoice = enum(u32) { @@ -784,8 +784,8 @@ test "enum with specified tag values" { } fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void { - assert(@enumToInt(x) == 60); - assert(1234 == switch (x) { + assertOrPanic(@enumToInt(x) == 60); + assertOrPanic(1234 == switch (x) { MultipleChoice.A => 1, MultipleChoice.B => 2, MultipleChoice.C => u32(1234), @@ -811,8 +811,8 @@ test "enum with specified and unspecified tag values" { } fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { - assert(@enumToInt(x) == 1000); - assert(1234 == switch (x) { + assertOrPanic(@enumToInt(x) == 1000); + assertOrPanic(1234 == switch (x) { MultipleChoice2.A => 1, MultipleChoice2.B => 2, MultipleChoice2.C => 3, @@ -826,8 +826,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { } test "cast integer literal to enum" { - assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1); - assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B); + assertOrPanic(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1); + assertOrPanic(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B); } const EnumWithOneMember = enum { @@ -865,14 +865,14 @@ const EnumWithTagValues = enum(u4) { D = 1 << 3, }; test "enum with tag values don't require parens" { - assert(@enumToInt(EnumWithTagValues.C) == 0b0100); + assertOrPanic(@enumToInt(EnumWithTagValues.C) == 0b0100); } test "enum with 1 field but explicit tag type should still have the tag type" { const Enum = enum(u8) { B = 2, }; - comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8)); + comptime @import("std").debug.assertOrPanic(@sizeOf(Enum) == @sizeOf(u8)); } test "empty extern enum with members" { @@ -881,14 +881,14 @@ test "empty extern enum with members" { B, C, }; - assert(@sizeOf(E) == @sizeOf(c_int)); + assertOrPanic(@sizeOf(E) == @sizeOf(c_int)); } -test "aoeu" { +test "tag name with assigned enum values" { const LocalFoo = enum { A = 1, B = 0, }; var b = LocalFoo.B; - assert(mem.eql(u8, @tagName(b), "B")); + assertOrPanic(mem.eql(u8, @tagName(b), "B")); } diff --git a/test/cases/enum_with_members.zig b/test/stage1/behavior/enum_with_members.zig similarity index 63% rename from test/cases/enum_with_members.zig rename to test/stage1/behavior/enum_with_members.zig index 088496bd2f..49af1ceae7 100644 --- a/test/cases/enum_with_members.zig +++ b/test/stage1/behavior/enum_with_members.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const mem = @import("std").mem; const fmt = @import("std").fmt; @@ -19,9 +19,9 @@ test "enum with members" { const b = ET{ .UINT = 42 }; var buf: [20]u8 = undefined; - assert((a.print(buf[0..]) catch unreachable) == 3); - assert(mem.eql(u8, buf[0..3], "-42")); + assertOrPanic((a.print(buf[0..]) catch unreachable) == 3); + assertOrPanic(mem.eql(u8, buf[0..3], "-42")); - assert((b.print(buf[0..]) catch unreachable) == 2); - assert(mem.eql(u8, buf[0..2], "42")); + assertOrPanic((b.print(buf[0..]) catch unreachable) == 2); + assertOrPanic(mem.eql(u8, buf[0..2], "42")); } diff --git a/test/cases/error.zig b/test/stage1/behavior/error.zig similarity index 58% rename from test/cases/error.zig rename to test/stage1/behavior/error.zig index a731f39021..c7e38712bc 100644 --- a/test/cases/error.zig +++ b/test/stage1/behavior/error.zig @@ -1,5 +1,6 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; +const assertError = std.debug.assertError; const mem = std.mem; const builtin = @import("builtin"); @@ -18,7 +19,7 @@ pub fn baz() anyerror!i32 { } test "error wrapping" { - assert((baz() catch unreachable) == 15); + assertOrPanic((baz() catch unreachable) == 15); } fn gimmeItBroke() []const u8 { @@ -26,14 +27,14 @@ fn gimmeItBroke() []const u8 { } test "@errorName" { - assert(mem.eql(u8, @errorName(error.AnError), "AnError")); - assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); + assertOrPanic(mem.eql(u8, @errorName(error.AnError), "AnError")); + assertOrPanic(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); } test "error values" { const a = @errorToInt(error.err1); const b = @errorToInt(error.err2); - assert(a != b); + assertOrPanic(a != b); } test "redefinition of error values allowed" { @@ -46,8 +47,8 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void { test "error binary operator" { const a = errBinaryOperatorG(true) catch 3; const b = errBinaryOperatorG(false) catch 3; - assert(a == 3); - assert(b == 10); + assertOrPanic(a == 3); + assertOrPanic(b == 10); } fn errBinaryOperatorG(x: bool) anyerror!isize { return if (x) error.ItBroke else isize(10); @@ -55,7 +56,7 @@ fn errBinaryOperatorG(x: bool) anyerror!isize { test "unwrap simple value from error" { const i = unwrapSimpleValueFromErrorDo() catch unreachable; - assert(i == 13); + assertOrPanic(i == 13); } fn unwrapSimpleValueFromErrorDo() anyerror!isize { return 13; @@ -81,13 +82,13 @@ test "error union type " { fn testErrorUnionType() void { const x: anyerror!i32 = 1234; - if (x) |value| assert(value == 1234) else |_| unreachable; - assert(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion); - assert(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet); - assert(@typeOf(x).ErrorSet == anyerror); + if (x) |value| assertOrPanic(value == 1234) else |_| unreachable; + assertOrPanic(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion); + assertOrPanic(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet); + assertOrPanic(@typeOf(x).ErrorSet == anyerror); } -test "error set type " { +test "error set type" { testErrorSetType(); comptime testErrorSetType(); } @@ -98,12 +99,12 @@ const MyErrSet = error{ }; fn testErrorSetType() void { - assert(@memberCount(MyErrSet) == 2); + assertOrPanic(@memberCount(MyErrSet) == 2); const a: MyErrSet!i32 = 5678; const b: MyErrSet!i32 = MyErrSet.OutOfMemory; - if (a) |value| assert(value == 5678) else |err| switch (err) { + if (a) |value| assertOrPanic(value == 5678) else |err| switch (err) { error.OutOfMemory => unreachable, error.FileNotFound => unreachable, } @@ -126,7 +127,7 @@ const Set2 = error{ fn testExplicitErrorSetCast(set1: Set1) void { var x = @errSetCast(Set2, set1); var y = @errSetCast(Set1, x); - assert(y == error.A); + assertOrPanic(y == error.A); } test "comptime test error for empty error set" { @@ -137,12 +138,12 @@ test "comptime test error for empty error set" { const EmptyErrorSet = error{}; fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void { - if (x) |v| assert(v == 1234) else |err| @compileError("bad"); + if (x) |v| assertOrPanic(v == 1234) else |err| @compileError("bad"); } test "syntax: optional operator in front of error union operator" { comptime { - assert(?(anyerror!i32) == ?(anyerror!i32)); + assertOrPanic(?(anyerror!i32) == ?(anyerror!i32)); } } @@ -161,7 +162,6 @@ fn testErrToIntWithOnePossibleValue( test "error union peer type resolution" { testErrorUnionPeerTypeResolution(1); - comptime testErrorUnionPeerTypeResolution(1); } fn testErrorUnionPeerTypeResolution(x: i32) void { @@ -170,6 +170,11 @@ fn testErrorUnionPeerTypeResolution(x: i32) void { 2 => baz_1(), else => quux_1(), }; + if (y) |_| { + @panic("expected error"); + } else |e| { + assertOrPanic(e == error.A); + } } fn bar_1() anyerror { @@ -243,3 +248,85 @@ fn intLiteral(str: []const u8) !?i64 { return error.T; } + +test "nested error union function call in optional unwrap" { + const S = struct { + const Foo = struct { + a: i32, + }; + + fn errorable() !i32 { + var x: Foo = (try getFoo()) orelse return error.Other; + return x.a; + } + + fn errorable2() !i32 { + var x: Foo = (try getFoo2()) orelse return error.Other; + return x.a; + } + + fn errorable3() !i32 { + var x: Foo = (try getFoo3()) orelse return error.Other; + return x.a; + } + + fn getFoo() anyerror!?Foo { + return Foo{ .a = 1234 }; + } + + fn getFoo2() anyerror!?Foo { + return error.Failure; + } + + fn getFoo3() anyerror!?Foo { + return null; + } + }; + assertOrPanic((try S.errorable()) == 1234); + assertError(S.errorable2(), error.Failure); + assertError(S.errorable3(), error.Other); + comptime { + assertOrPanic((try S.errorable()) == 1234); + assertError(S.errorable2(), error.Failure); + assertError(S.errorable3(), error.Other); + } +} + +test "widen cast integer payload of error union function call" { + const S = struct { + fn errorable() !u64 { + var x = u64(try number()); + return x; + } + + fn number() anyerror!u32 { + return 1234; + } + }; + assertOrPanic((try S.errorable()) == 1234); +} + +test "return function call to error set from error union function" { + const S = struct { + fn errorable() anyerror!i32 { + return fail(); + } + + fn fail() anyerror { + return error.Failure; + } + }; + assertError(S.errorable(), error.Failure); + comptime assertError(S.errorable(), error.Failure); +} + +test "optional error set is the same size as error set" { + comptime assertOrPanic(@sizeOf(?anyerror) == @sizeOf(anyerror)); + const S = struct { + fn returnsOptErrSet() ?anyerror { + return null; + } + }; + assertOrPanic(S.returnsOptErrSet() == null); + comptime assertOrPanic(S.returnsOptErrSet() == null); +} diff --git a/test/cases/eval.zig b/test/stage1/behavior/eval.zig similarity index 70% rename from test/cases/eval.zig rename to test/stage1/behavior/eval.zig index a9eded151e..2d8494eb0b 100644 --- a/test/cases/eval.zig +++ b/test/stage1/behavior/eval.zig @@ -1,9 +1,9 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const builtin = @import("builtin"); test "compile time recursion" { - assert(some_data.len == 21); + assertOrPanic(some_data.len == 21); } var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined; fn fibonacci(x: i32) i32 { @@ -16,7 +16,7 @@ fn unwrapAndAddOne(blah: ?i32) i32 { } const should_be_1235 = unwrapAndAddOne(1234); test "static add one" { - assert(should_be_1235 == 1235); + assertOrPanic(should_be_1235 == 1235); } test "inlined loop" { @@ -24,7 +24,7 @@ test "inlined loop" { comptime var sum = 0; inline while (i <= 5) : (i += 1) sum += i; - assert(sum == 15); + assertOrPanic(sum == 15); } fn gimme1or2(comptime a: bool) i32 { @@ -34,12 +34,12 @@ fn gimme1or2(comptime a: bool) i32 { return z; } test "inline variable gets result of const if" { - assert(gimme1or2(true) == 1); - assert(gimme1or2(false) == 2); + assertOrPanic(gimme1or2(true) == 1); + assertOrPanic(gimme1or2(false) == 2); } test "static function evaluation" { - assert(statically_added_number == 3); + assertOrPanic(statically_added_number == 3); } const statically_added_number = staticAdd(1, 2); fn staticAdd(a: i32, b: i32) i32 { @@ -47,7 +47,8 @@ fn staticAdd(a: i32, b: i32) i32 { } test "const expr eval on single expr blocks" { - assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3); + assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3); + comptime assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3); } fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { @@ -63,10 +64,10 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { } test "statically initialized list" { - assert(static_point_list[0].x == 1); - assert(static_point_list[0].y == 2); - assert(static_point_list[1].x == 3); - assert(static_point_list[1].y == 4); + assertOrPanic(static_point_list[0].x == 1); + assertOrPanic(static_point_list[0].y == 2); + assertOrPanic(static_point_list[1].x == 3); + assertOrPanic(static_point_list[1].y == 4); } const Point = struct { x: i32, @@ -84,8 +85,8 @@ fn makePoint(x: i32, y: i32) Point { } test "static eval list init" { - assert(static_vec3.data[2] == 1.0); - assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0); + assertOrPanic(static_vec3.data[2] == 1.0); + assertOrPanic(vec3(0.0, 0.0, 3.0).data[2] == 3.0); } const static_vec3 = vec3(0.0, 0.0, 1.0); pub const Vec3 = struct { @@ -101,12 +102,12 @@ pub fn vec3(x: f32, y: f32, z: f32) Vec3 { test "constant expressions" { var array: [array_size]u8 = undefined; - assert(@sizeOf(@typeOf(array)) == 20); + assertOrPanic(@sizeOf(@typeOf(array)) == 20); } const array_size: u8 = 20; test "constant struct with negation" { - assert(vertices[0].x == -0.6); + assertOrPanic(vertices[0].x == -0.6); } const Vertex = struct { x: f32, @@ -141,7 +142,7 @@ const vertices = []Vertex{ test "statically initialized struct" { st_init_str_foo.x += 1; - assert(st_init_str_foo.x == 14); + assertOrPanic(st_init_str_foo.x == 14); } const StInitStrFoo = struct { x: i32, @@ -154,7 +155,7 @@ var st_init_str_foo = StInitStrFoo{ test "statically initalized array literal" { const y: [4]u8 = st_init_arr_lit_x; - assert(y[3] == 4); + assertOrPanic(y[3] == 4); } const st_init_arr_lit_x = []u8{ 1, @@ -166,15 +167,15 @@ const st_init_arr_lit_x = []u8{ test "const slice" { comptime { const a = "1234567890"; - assert(a.len == 10); + assertOrPanic(a.len == 10); const b = a[1..2]; - assert(b.len == 1); - assert(b[0] == '2'); + assertOrPanic(b.len == 1); + assertOrPanic(b[0] == '2'); } } test "try to trick eval with runtime if" { - assert(testTryToTrickEvalWithRuntimeIf(true) == 10); + assertOrPanic(testTryToTrickEvalWithRuntimeIf(true) == 10); } fn testTryToTrickEvalWithRuntimeIf(b: bool) usize { @@ -200,16 +201,16 @@ fn letsTryToCompareBools(a: bool, b: bool) bool { return max(bool, a, b); } test "inlined block and runtime block phi" { - assert(letsTryToCompareBools(true, true)); - assert(letsTryToCompareBools(true, false)); - assert(letsTryToCompareBools(false, true)); - assert(!letsTryToCompareBools(false, false)); + assertOrPanic(letsTryToCompareBools(true, true)); + assertOrPanic(letsTryToCompareBools(true, false)); + assertOrPanic(letsTryToCompareBools(false, true)); + assertOrPanic(!letsTryToCompareBools(false, false)); comptime { - assert(letsTryToCompareBools(true, true)); - assert(letsTryToCompareBools(true, false)); - assert(letsTryToCompareBools(false, true)); - assert(!letsTryToCompareBools(false, false)); + assertOrPanic(letsTryToCompareBools(true, true)); + assertOrPanic(letsTryToCompareBools(true, false)); + assertOrPanic(letsTryToCompareBools(false, true)); + assertOrPanic(!letsTryToCompareBools(false, false)); } } @@ -254,14 +255,14 @@ fn performFn(comptime prefix_char: u8, start_value: i32) i32 { } test "comptime iterate over fn ptr list" { - assert(performFn('t', 1) == 6); - assert(performFn('o', 0) == 1); - assert(performFn('w', 99) == 99); + assertOrPanic(performFn('t', 1) == 6); + assertOrPanic(performFn('o', 0) == 1); + assertOrPanic(performFn('w', 99) == 99); } test "eval @setRuntimeSafety at compile-time" { const result = comptime fnWithSetRuntimeSafety(); - assert(result == 1234); + assertOrPanic(result == 1234); } fn fnWithSetRuntimeSafety() i32 { @@ -271,7 +272,7 @@ fn fnWithSetRuntimeSafety() i32 { test "eval @setFloatMode at compile-time" { const result = comptime fnWithFloatMode(); - assert(result == 1234.0); + assertOrPanic(result == 1234.0); } fn fnWithFloatMode() f32 { @@ -292,15 +293,15 @@ var simple_struct = SimpleStruct{ .field = 1234 }; const bound_fn = simple_struct.method; test "call method on bound fn referring to var instance" { - assert(bound_fn() == 1237); + assertOrPanic(bound_fn() == 1237); } test "ptr to local array argument at comptime" { comptime { var bytes: [10]u8 = undefined; modifySomeBytes(bytes[0..]); - assert(bytes[0] == 'a'); - assert(bytes[9] == 'b'); + assertOrPanic(bytes[0] == 'a'); + assertOrPanic(bytes[9] == 'b'); } } @@ -328,9 +329,9 @@ fn testCompTimeUIntComparisons(x: u32) void { } test "const ptr to variable data changes at runtime" { - assert(foo_ref.name[0] == 'a'); + assertOrPanic(foo_ref.name[0] == 'a'); foo_ref.name = "b"; - assert(foo_ref.name[0] == 'b'); + assertOrPanic(foo_ref.name[0] == 'b'); } const Foo = struct { @@ -341,8 +342,8 @@ var foo_contents = Foo{ .name = "a" }; const foo_ref = &foo_contents; test "create global array with for loop" { - assert(global_array[5] == 5 * 5); - assert(global_array[9] == 9 * 9); + assertOrPanic(global_array[5] == 5 * 5); + assertOrPanic(global_array[9] == 9 * 9); } const global_array = x: { @@ -357,7 +358,7 @@ test "compile-time downcast when the bits fit" { comptime { const spartan_count: u16 = 255; const byte = @intCast(u8, spartan_count); - assert(byte == 255); + assertOrPanic(byte == 255); } } @@ -365,44 +366,45 @@ const hi1 = "hi"; const hi2 = hi1; test "const global shares pointer with other same one" { assertEqualPtrs(&hi1[0], &hi2[0]); - comptime assert(&hi1[0] == &hi2[0]); + comptime assertOrPanic(&hi1[0] == &hi2[0]); } fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void { - assert(ptr1 == ptr2); + assertOrPanic(ptr1 == ptr2); } test "@setEvalBranchQuota" { comptime { - // 1001 for the loop and then 1 more for the assert fn call + // 1001 for the loop and then 1 more for the assertOrPanic fn call @setEvalBranchQuota(1002); var i = 0; var sum = 0; while (i < 1001) : (i += 1) { sum += i; } - assert(sum == 500500); + assertOrPanic(sum == 500500); } } // TODO test "float literal at compile time not lossy" { -// TODO assert(16777216.0 + 1.0 == 16777217.0); -// TODO assert(9007199254740992.0 + 1.0 == 9007199254740993.0); +// TODO assertOrPanic(16777216.0 + 1.0 == 16777217.0); +// TODO assertOrPanic(9007199254740992.0 + 1.0 == 9007199254740993.0); // TODO } test "f32 at compile time is lossy" { - assert(f32(1 << 24) + 1 == 1 << 24); + assertOrPanic(f32(1 << 24) + 1 == 1 << 24); } test "f64 at compile time is lossy" { - assert(f64(1 << 53) + 1 == 1 << 53); + assertOrPanic(f64(1 << 53) + 1 == 1 << 53); } test "f128 at compile time is lossy" { - assert(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); + assertOrPanic(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); } -// TODO need a better implementation of bigfloat_init_bigint -// assert(f128(1 << 113) == 10384593717069655257060992658440192); +comptime { + assertOrPanic(f128(1 << 113) == 10384593717069655257060992658440192); +} pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { return struct { @@ -413,15 +415,15 @@ pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { test "string literal used as comptime slice is memoized" { const a = "link"; const b = "link"; - comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node); - comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node); + comptime assertOrPanic(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node); + comptime assertOrPanic(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node); } test "comptime slice of undefined pointer of length 0" { const slice1 = ([*]i32)(undefined)[0..0]; - assert(slice1.len == 0); + assertOrPanic(slice1.len == 0); const slice2 = ([*]i32)(undefined)[100..100]; - assert(slice2.len == 0); + assertOrPanic(slice2.len == 0); } fn copyWithPartialInline(s: []u32, b: []u8) void { @@ -443,16 +445,16 @@ test "binary math operator in partially inlined function" { r.* = @intCast(u8, i + 1); copyWithPartialInline(s[0..], b[0..]); - assert(s[0] == 0x1020304); - assert(s[1] == 0x5060708); - assert(s[2] == 0x90a0b0c); - assert(s[3] == 0xd0e0f10); + assertOrPanic(s[0] == 0x1020304); + assertOrPanic(s[1] == 0x5060708); + assertOrPanic(s[2] == 0x90a0b0c); + assertOrPanic(s[3] == 0xd0e0f10); } test "comptime function with the same args is memoized" { comptime { - assert(MakeType(i32) == MakeType(i32)); - assert(MakeType(i32) != MakeType(f64)); + assertOrPanic(MakeType(i32) == MakeType(i32)); + assertOrPanic(MakeType(i32) != MakeType(f64)); } } @@ -468,7 +470,7 @@ test "comptime function with mutable pointer is not memoized" { const ptr = &x; increment(ptr); increment(ptr); - assert(x == 3); + assertOrPanic(x == 3); } } @@ -494,14 +496,14 @@ fn doesAlotT(comptime T: type, value: usize) T { } test "@setEvalBranchQuota at same scope as generic function call" { - assert(doesAlotT(u32, 2) == 2); + assertOrPanic(doesAlotT(u32, 2) == 2); } test "comptime slice of slice preserves comptime var" { comptime { var buff: [10]u8 = undefined; buff[0..][0..][0] = 1; - assert(buff[0..][0..][0] == 1); + assertOrPanic(buff[0..][0..][0] == 1); } } @@ -510,7 +512,7 @@ test "comptime slice of pointer preserves comptime var" { var buff: [10]u8 = undefined; var a = buff[0..].ptr; a[0..1][0] = 1; - assert(buff[0..][0..][0] == 1); + assertOrPanic(buff[0..][0..][0] == 1); } } @@ -524,9 +526,9 @@ const SingleFieldStruct = struct { test "const ptr to comptime mutable data is not memoized" { comptime { var foo = SingleFieldStruct{ .x = 1 }; - assert(foo.read_x() == 1); + assertOrPanic(foo.read_x() == 1); foo.x = 2; - assert(foo.read_x() == 2); + assertOrPanic(foo.read_x() == 2); } } @@ -535,7 +537,7 @@ test "array concat of slices gives slice" { var a: []const u8 = "aoeu"; var b: []const u8 = "asdf"; const c = a ++ b; - assert(std.mem.eql(u8, c, "aoeuasdf")); + assertOrPanic(std.mem.eql(u8, c, "aoeuasdf")); } } @@ -552,14 +554,14 @@ test "comptime shlWithOverflow" { break :amt amt; }; - assert(ct_shifted == rt_shifted); + assertOrPanic(ct_shifted == rt_shifted); } test "runtime 128 bit integer division" { var a: u128 = 152313999999999991610955792383; var b: u128 = 10000000000000000000; var c = a / b; - assert(c == 15231399999); + assertOrPanic(c == 15231399999); } pub const Info = struct { @@ -572,20 +574,20 @@ test "comptime modification of const struct field" { comptime { var res = diamond_info; res.version = 1; - assert(diamond_info.version == 0); - assert(res.version == 1); + assertOrPanic(diamond_info.version == 0); + assertOrPanic(res.version == 1); } } test "pointer to type" { comptime { var T: type = i32; - assert(T == i32); + assertOrPanic(T == i32); var ptr = &T; - assert(@typeOf(ptr) == *type); + assertOrPanic(@typeOf(ptr) == *type); ptr.* = f32; - assert(T == f32); - assert(*T == *f32); + assertOrPanic(T == f32); + assertOrPanic(*T == *f32); } } @@ -594,17 +596,17 @@ test "slice of type" { var types_array = []type{ i32, f64, type }; for (types_array) |T, i| { switch (i) { - 0 => assert(T == i32), - 1 => assert(T == f64), - 2 => assert(T == type), + 0 => assertOrPanic(T == i32), + 1 => assertOrPanic(T == f64), + 2 => assertOrPanic(T == type), else => unreachable, } } for (types_array[0..]) |T, i| { switch (i) { - 0 => assert(T == i32), - 1 => assert(T == f64), - 2 => assert(T == type), + 0 => assertOrPanic(T == i32), + 1 => assertOrPanic(T == f64), + 2 => assertOrPanic(T == type), else => unreachable, } } @@ -621,7 +623,7 @@ fn wrap(comptime T: type) Wrapper { test "function which returns struct with type field causes implicit comptime" { const ty = wrap(i32).T; - assert(ty == i32); + assertOrPanic(ty == i32); } test "call method with comptime pass-by-non-copying-value self parameter" { @@ -635,12 +637,12 @@ test "call method with comptime pass-by-non-copying-value self parameter" { const s = S{ .a = 2 }; var b = s.b(); - assert(b == 2); + assertOrPanic(b == 2); } test "@tagName of @typeId" { const str = @tagName(@typeId(u8)); - assert(std.mem.eql(u8, str, "Int")); + assertOrPanic(std.mem.eql(u8, str, "Int")); } test "setting backward branch quota just before a generic fn call" { @@ -661,8 +663,8 @@ fn testVarInsideInlineLoop(args: ...) void { comptime var i = 0; inline while (i < args.len) : (i += 1) { const x = args[i]; - if (i == 0) assert(x); - if (i == 1) assert(x == 42); + if (i == 0) assertOrPanic(x); + if (i == 1) assertOrPanic(x == 42); } } @@ -672,7 +674,7 @@ test "inline for with same type but different values" { var a: T = undefined; res += a.len; } - assert(res == 5); + assertOrPanic(res == 5); } test "refer to the type of a generic function" { @@ -686,19 +688,19 @@ fn doNothingWithType(comptime T: type) void {} test "zero extend from u0 to u1" { var zero_u0: u0 = 0; var zero_u1: u1 = zero_u0; - assert(zero_u1 == 0); + assertOrPanic(zero_u1 == 0); } test "bit shift a u1" { var x: u1 = 1; var y = x << 0; - assert(y == 1); + assertOrPanic(y == 1); } test "@intCast to a u0" { var x: u8 = 0; var y: u0 = @intCast(u0, x); - assert(y == 0); + assertOrPanic(y == 0); } test "@bytesToslice on a packed struct" { @@ -708,7 +710,7 @@ test "@bytesToslice on a packed struct" { var b = [1]u8{9}; var f = @bytesToSlice(F, b); - assert(f[0].a == 9); + assertOrPanic(f[0].a == 9); } test "comptime pointer cast array and then slice" { @@ -720,8 +722,8 @@ test "comptime pointer cast array and then slice" { const ptrB: [*]const u8 = &array; const sliceB: []const u8 = ptrB[0..2]; - assert(sliceA[1] == 2); - assert(sliceB[1] == 2); + assertOrPanic(sliceA[1] == 2); + assertOrPanic(sliceB[1] == 2); } test "slice bounds in comptime concatenation" { @@ -730,47 +732,47 @@ test "slice bounds in comptime concatenation" { break :blk b[0..1]; }; const str = "" ++ bs; - assert(str.len == 1); - assert(std.mem.eql(u8, str, "1")); + assertOrPanic(str.len == 1); + assertOrPanic(std.mem.eql(u8, str, "1")); const str2 = bs ++ ""; - assert(str2.len == 1); - assert(std.mem.eql(u8, str2, "1")); + assertOrPanic(str2.len == 1); + assertOrPanic(std.mem.eql(u8, str2, "1")); } test "comptime bitwise operators" { comptime { - assert(3 & 1 == 1); - assert(3 & -1 == 3); - assert(-3 & -1 == -3); - assert(3 | -1 == -1); - assert(-3 | -1 == -1); - assert(3 ^ -1 == -4); - assert(-3 ^ -1 == 2); - assert(~i8(-1) == 0); - assert(~i128(-1) == 0); - assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611); - assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615); - assert(~u128(0) == 0xffffffffffffffffffffffffffffffff); + assertOrPanic(3 & 1 == 1); + assertOrPanic(3 & -1 == 3); + assertOrPanic(-3 & -1 == -3); + assertOrPanic(3 | -1 == -1); + assertOrPanic(-3 | -1 == -1); + assertOrPanic(3 ^ -1 == -4); + assertOrPanic(-3 ^ -1 == 2); + assertOrPanic(~i8(-1) == 0); + assertOrPanic(~i128(-1) == 0); + assertOrPanic(18446744073709551615 & 18446744073709551611 == 18446744073709551611); + assertOrPanic(-18446744073709551615 & -18446744073709551611 == -18446744073709551615); + assertOrPanic(~u128(0) == 0xffffffffffffffffffffffffffffffff); } } test "*align(1) u16 is the same as *align(1:0:2) u16" { comptime { - assert(*align(1:0:2) u16 == *align(1) u16); + assertOrPanic(*align(1:0:2) u16 == *align(1) u16); // TODO add parsing support for this syntax - //assert(*align(:0:2) u16 == *u16); + //assertOrPanic(*align(:0:2) u16 == *u16); } } test "array concatenation forces comptime" { var a = oneItem(3) ++ oneItem(4); - assert(std.mem.eql(i32, a, []i32{3, 4})); + assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 4 })); } test "array multiplication forces comptime" { var a = oneItem(3) ** scalar(2); - assert(std.mem.eql(i32, a, []i32{3, 3})); + assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 3 })); } fn oneItem(x: i32) [1]i32 { diff --git a/test/cases/field_parent_ptr.zig b/test/stage1/behavior/field_parent_ptr.zig similarity index 69% rename from test/cases/field_parent_ptr.zig rename to test/stage1/behavior/field_parent_ptr.zig index 00d4e0f367..ed2487c020 100644 --- a/test/cases/field_parent_ptr.zig +++ b/test/stage1/behavior/field_parent_ptr.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "@fieldParentPtr non-first field" { testParentFieldPtr(&foo.c); @@ -25,17 +25,17 @@ const foo = Foo{ }; fn testParentFieldPtr(c: *const i32) void { - assert(c == &foo.c); + assertOrPanic(c == &foo.c); const base = @fieldParentPtr(Foo, "c", c); - assert(base == &foo); - assert(&base.c == c); + assertOrPanic(base == &foo); + assertOrPanic(&base.c == c); } fn testParentFieldPtrFirst(a: *const bool) void { - assert(a == &foo.a); + assertOrPanic(a == &foo.a); const base = @fieldParentPtr(Foo, "a", a); - assert(base == &foo); - assert(&base.a == a); + assertOrPanic(base == &foo); + assertOrPanic(&base.a == a); } diff --git a/test/cases/fn.zig b/test/stage1/behavior/fn.zig similarity index 78% rename from test/cases/fn.zig rename to test/stage1/behavior/fn.zig index 8908bd7854..3011bc41d0 100644 --- a/test/cases/fn.zig +++ b/test/stage1/behavior/fn.zig @@ -1,7 +1,7 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "params" { - assert(testParamsAdd(22, 11) == 33); + assertOrPanic(testParamsAdd(22, 11) == 33); } fn testParamsAdd(a: i32, b: i32) i32 { return a + b; @@ -21,32 +21,32 @@ test "void parameters" { fn voidFun(a: i32, b: void, c: i32, d: void) void { const v = b; const vv: void = if (a == 1) v else {}; - assert(a + c == 3); + assertOrPanic(a + c == 3); return vv; } test "mutable local variables" { var zero: i32 = 0; - assert(zero == 0); + assertOrPanic(zero == 0); var i = i32(0); while (i != 3) { i += 1; } - assert(i == 3); + assertOrPanic(i == 3); } test "separate block scopes" { { const no_conflict: i32 = 5; - assert(no_conflict == 5); + assertOrPanic(no_conflict == 5); } const c = x: { const no_conflict = i32(10); break :x no_conflict; }; - assert(c == 10); + assertOrPanic(c == 10); } test "call function with empty string" { @@ -59,7 +59,7 @@ fn @"weird function name"() i32 { return 1234; } test "weird function name" { - assert(@"weird function name"() == 1234); + assertOrPanic(@"weird function name"() == 1234); } test "implicit cast function unreachable return" { @@ -80,7 +80,7 @@ test "function pointers" { fn4, }; for (fns) |f, i| { - assert(f() == @intCast(u32, i) + 5); + assertOrPanic(f() == @intCast(u32, i) + 5); } } fn fn1() u32 { @@ -97,7 +97,7 @@ fn fn4() u32 { } test "inline function call" { - assert(@inlineCall(add, 3, 9) == 12); + assertOrPanic(@inlineCall(add, 3, 9) == 12); } fn add(a: i32, b: i32) i32 { @@ -110,7 +110,7 @@ test "number literal as an argument" { } fn numberLiteralArg(a: var) void { - assert(a == 3); + assertOrPanic(a == 3); } test "assign inline fn to const variable" { @@ -121,7 +121,7 @@ test "assign inline fn to const variable" { inline fn inlineFn() void {} test "pass by non-copying value" { - assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3); + assertOrPanic(addPointCoords(Point{ .x = 1, .y = 2 }) == 3); } const Point = struct { @@ -134,17 +134,17 @@ fn addPointCoords(pt: Point) i32 { } test "pass by non-copying value through var arg" { - assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3); + assertOrPanic(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3); } fn addPointCoordsVar(pt: var) i32 { - comptime assert(@typeOf(pt) == Point); + comptime assertOrPanic(@typeOf(pt) == Point); return pt.x + pt.y; } test "pass by non-copying value as method" { var pt = Point2{ .x = 1, .y = 2 }; - assert(pt.addPointCoords() == 3); + assertOrPanic(pt.addPointCoords() == 3); } const Point2 = struct { @@ -158,7 +158,7 @@ const Point2 = struct { test "pass by non-copying value as method, which is generic" { var pt = Point3{ .x = 1, .y = 2 }; - assert(pt.addPointCoords(i32) == 3); + assertOrPanic(pt.addPointCoords(i32) == 3); } const Point3 = struct { @@ -173,7 +173,7 @@ const Point3 = struct { test "pass by non-copying value as method, at comptime" { comptime { var pt = Point2{ .x = 1, .y = 2 }; - assert(pt.addPointCoords() == 3); + assertOrPanic(pt.addPointCoords() == 3); } } @@ -189,7 +189,7 @@ fn outer(y: u32) fn (u32) u32 { test "return inner function which references comptime variable of outer function" { var func = outer(10); - assert(func(3) == 7); + assertOrPanic(func(3) == 7); } test "extern struct with stdcallcc fn pointer" { @@ -203,5 +203,6 @@ test "extern struct with stdcallcc fn pointer" { var s: S = undefined; s.ptr = S.foo; - assert(s.ptr() == 1234); + assertOrPanic(s.ptr() == 1234); } + diff --git a/test/cases/fn_in_struct_in_comptime.zig b/test/stage1/behavior/fn_in_struct_in_comptime.zig similarity index 72% rename from test/cases/fn_in_struct_in_comptime.zig rename to test/stage1/behavior/fn_in_struct_in_comptime.zig index fabb57e9cb..0af076d40a 100644 --- a/test/cases/fn_in_struct_in_comptime.zig +++ b/test/stage1/behavior/fn_in_struct_in_comptime.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; fn get_foo() fn (*u8) usize { comptime { @@ -13,5 +13,5 @@ fn get_foo() fn (*u8) usize { test "define a function in an anonymous struct in comptime" { const foo = get_foo(); - assert(foo(@intToPtr(*u8, 12345)) == 12345); + assertOrPanic(foo(@intToPtr(*u8, 12345)) == 12345); } diff --git a/test/cases/for.zig b/test/stage1/behavior/for.zig similarity index 89% rename from test/cases/for.zig rename to test/stage1/behavior/for.zig index aecd8b9a07..b6d1ef24c4 100644 --- a/test/cases/for.zig +++ b/test/stage1/behavior/for.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const mem = std.mem; test "continue in for loop" { @@ -26,7 +26,7 @@ test "for loop with pointer elem var" { var target: [source.len]u8 = undefined; mem.copy(u8, target[0..], source); mangleString(target[0..]); - assert(mem.eql(u8, target, "bcdefgh")); + assertOrPanic(mem.eql(u8, target, "bcdefgh")); } fn mangleString(s: []u8) void { for (s) |*c| { @@ -68,7 +68,7 @@ test "basic for loop" { buf_index += 1; } - assert(mem.eql(u8, buffer[0..buf_index], expected_result)); + assertOrPanic(mem.eql(u8, buffer[0..buf_index], expected_result)); } test "break from outer for loop" { @@ -85,7 +85,7 @@ fn testBreakOuter() void { break :outer; } } - assert(count == 1); + assertOrPanic(count == 1); } test "continue outer for loop" { @@ -102,5 +102,5 @@ fn testContinueOuter() void { continue :outer; } } - assert(counter == array.len); + assertOrPanic(counter == array.len); } diff --git a/test/cases/generics.zig b/test/stage1/behavior/generics.zig similarity index 68% rename from test/cases/generics.zig rename to test/stage1/behavior/generics.zig index 52aa013989..a0928634a7 100644 --- a/test/cases/generics.zig +++ b/test/stage1/behavior/generics.zig @@ -1,9 +1,9 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "simple generic fn" { - assert(max(i32, 3, -1) == 3); - assert(max(f32, 0.123, 0.456) == 0.456); - assert(add(2, 3) == 5); + assertOrPanic(max(i32, 3, -1) == 3); + assertOrPanic(max(f32, 0.123, 0.456) == 0.456); + assertOrPanic(add(2, 3) == 5); } fn max(comptime T: type, a: T, b: T) T { @@ -16,7 +16,7 @@ fn add(comptime a: i32, b: i32) i32 { const the_max = max(u32, 1234, 5678); test "compile time generic eval" { - assert(the_max == 5678); + assertOrPanic(the_max == 5678); } fn gimmeTheBigOne(a: u32, b: u32) u32 { @@ -32,19 +32,19 @@ fn sameButWithFloats(a: f64, b: f64) f64 { } test "fn with comptime args" { - assert(gimmeTheBigOne(1234, 5678) == 5678); - assert(shouldCallSameInstance(34, 12) == 34); - assert(sameButWithFloats(0.43, 0.49) == 0.49); + assertOrPanic(gimmeTheBigOne(1234, 5678) == 5678); + assertOrPanic(shouldCallSameInstance(34, 12) == 34); + assertOrPanic(sameButWithFloats(0.43, 0.49) == 0.49); } test "var params" { - assert(max_i32(12, 34) == 34); - assert(max_f64(1.2, 3.4) == 3.4); + assertOrPanic(max_i32(12, 34) == 34); + assertOrPanic(max_f64(1.2, 3.4) == 3.4); } comptime { - assert(max_i32(12, 34) == 34); - assert(max_f64(1.2, 3.4) == 3.4); + assertOrPanic(max_i32(12, 34) == 34); + assertOrPanic(max_f64(1.2, 3.4) == 3.4); } fn max_var(a: var, b: var) @typeOf(a + b) { @@ -76,8 +76,8 @@ test "function with return type type" { var list2: List(i32) = undefined; list.length = 10; list2.length = 10; - assert(list.prealloc_items.len == 8); - assert(list2.prealloc_items.len == 8); + assertOrPanic(list.prealloc_items.len == 8); + assertOrPanic(list2.prealloc_items.len == 8); } test "generic struct" { @@ -89,9 +89,9 @@ test "generic struct" { .value = true, .next = null, }; - assert(a1.value == 13); - assert(a1.value == a1.getVal()); - assert(b1.getVal()); + assertOrPanic(a1.value == 13); + assertOrPanic(a1.value == a1.getVal()); + assertOrPanic(b1.getVal()); } fn GenNode(comptime T: type) type { return struct { @@ -104,7 +104,7 @@ fn GenNode(comptime T: type) type { } test "const decls in struct" { - assert(GenericDataThing(3).count_plus_one == 4); + assertOrPanic(GenericDataThing(3).count_plus_one == 4); } fn GenericDataThing(comptime count: isize) type { return struct { @@ -113,15 +113,15 @@ fn GenericDataThing(comptime count: isize) type { } test "use generic param in generic param" { - assert(aGenericFn(i32, 3, 4) == 7); + assertOrPanic(aGenericFn(i32, 3, 4) == 7); } fn aGenericFn(comptime T: type, comptime a: T, b: T) T { return a + b; } test "generic fn with implicit cast" { - assert(getFirstByte(u8, []u8{13}) == 13); - assert(getFirstByte(u16, []u16{ + assertOrPanic(getFirstByte(u8, []u8{13}) == 13); + assertOrPanic(getFirstByte(u16, []u16{ 0, 13, }) == 0); @@ -146,6 +146,6 @@ fn foo2(arg: var) bool { } test "array of generic fns" { - assert(foos[0](true)); - assert(!foos[1](true)); + assertOrPanic(foos[0](true)); + assertOrPanic(!foos[1](true)); } diff --git a/test/cases/if.zig b/test/stage1/behavior/if.zig similarity index 85% rename from test/cases/if.zig rename to test/stage1/behavior/if.zig index 808936bfa5..58d1b8fd73 100644 --- a/test/cases/if.zig +++ b/test/stage1/behavior/if.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "if statements" { shouldBeEqual(1, 1); @@ -24,7 +24,7 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void { } test "else if expression" { - assert(elseIfExpressionF(1) == 1); + assertOrPanic(elseIfExpressionF(1) == 1); } fn elseIfExpressionF(c: u8) u8 { if (c == 0) { diff --git a/test/stage1/behavior/import.zig b/test/stage1/behavior/import.zig new file mode 100644 index 0000000000..736e4c219d --- /dev/null +++ b/test/stage1/behavior/import.zig @@ -0,0 +1,10 @@ +const assertOrPanic = @import("std").debug.assertOrPanic; +const a_namespace = @import("import/a_namespace.zig"); + +test "call fn via namespace lookup" { + assertOrPanic(a_namespace.foo() == 1234); +} + +test "importing the same thing gives the same import" { + assertOrPanic(@import("std") == @import("std")); +} diff --git a/test/cases/import/a_namespace.zig b/test/stage1/behavior/import/a_namespace.zig similarity index 100% rename from test/cases/import/a_namespace.zig rename to test/stage1/behavior/import/a_namespace.zig diff --git a/test/cases/incomplete_struct_param_tld.zig b/test/stage1/behavior/incomplete_struct_param_tld.zig similarity index 78% rename from test/cases/incomplete_struct_param_tld.zig rename to test/stage1/behavior/incomplete_struct_param_tld.zig index f1ac03a292..d062311b2e 100644 --- a/test/cases/incomplete_struct_param_tld.zig +++ b/test/stage1/behavior/incomplete_struct_param_tld.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const A = struct { b: B, @@ -26,5 +26,5 @@ test "incomplete struct param top level declaration" { .c = C{ .x = 13 }, }, }; - assert(foo(a) == 13); + assertOrPanic(foo(a) == 13); } diff --git a/test/cases/inttoptr.zig b/test/stage1/behavior/inttoptr.zig similarity index 99% rename from test/cases/inttoptr.zig rename to test/stage1/behavior/inttoptr.zig index ba3cc52f09..bf657fc86a 100644 --- a/test/cases/inttoptr.zig +++ b/test/stage1/behavior/inttoptr.zig @@ -24,4 +24,3 @@ fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void { return; } } - diff --git a/test/cases/ir_block_deps.zig b/test/stage1/behavior/ir_block_deps.zig similarity index 64% rename from test/cases/ir_block_deps.zig rename to test/stage1/behavior/ir_block_deps.zig index 5c1b18c00e..bc61e11df7 100644 --- a/test/cases/ir_block_deps.zig +++ b/test/stage1/behavior/ir_block_deps.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; fn foo(id: u64) !i32 { return switch (id) { @@ -16,6 +16,6 @@ fn getErrInt() anyerror!i32 { } test "ir block deps" { - assert((foo(1) catch unreachable) == 0); - assert((foo(2) catch unreachable) == 0); + assertOrPanic((foo(1) catch unreachable) == 0); + assertOrPanic((foo(2) catch unreachable) == 0); } diff --git a/test/cases/math.zig b/test/stage1/behavior/math.zig similarity index 56% rename from test/cases/math.zig rename to test/stage1/behavior/math.zig index 7d6b1bd9ac..9d6a5a4997 100644 --- a/test/cases/math.zig +++ b/test/stage1/behavior/math.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const maxInt = std.math.maxInt; const minInt = std.math.minInt; @@ -8,57 +8,57 @@ test "division" { comptime testDivision(); } fn testDivision() void { - assert(div(u32, 13, 3) == 4); - assert(div(f16, 1.0, 2.0) == 0.5); - assert(div(f32, 1.0, 2.0) == 0.5); + assertOrPanic(div(u32, 13, 3) == 4); + assertOrPanic(div(f16, 1.0, 2.0) == 0.5); + assertOrPanic(div(f32, 1.0, 2.0) == 0.5); - assert(divExact(u32, 55, 11) == 5); - assert(divExact(i32, -55, 11) == -5); - assert(divExact(f16, 55.0, 11.0) == 5.0); - assert(divExact(f16, -55.0, 11.0) == -5.0); - assert(divExact(f32, 55.0, 11.0) == 5.0); - assert(divExact(f32, -55.0, 11.0) == -5.0); + assertOrPanic(divExact(u32, 55, 11) == 5); + assertOrPanic(divExact(i32, -55, 11) == -5); + assertOrPanic(divExact(f16, 55.0, 11.0) == 5.0); + assertOrPanic(divExact(f16, -55.0, 11.0) == -5.0); + assertOrPanic(divExact(f32, 55.0, 11.0) == 5.0); + assertOrPanic(divExact(f32, -55.0, 11.0) == -5.0); - assert(divFloor(i32, 5, 3) == 1); - assert(divFloor(i32, -5, 3) == -2); - assert(divFloor(f16, 5.0, 3.0) == 1.0); - assert(divFloor(f16, -5.0, 3.0) == -2.0); - assert(divFloor(f32, 5.0, 3.0) == 1.0); - assert(divFloor(f32, -5.0, 3.0) == -2.0); - assert(divFloor(i32, -0x80000000, -2) == 0x40000000); - assert(divFloor(i32, 0, -0x80000000) == 0); - assert(divFloor(i32, -0x40000001, 0x40000000) == -2); - assert(divFloor(i32, -0x80000000, 1) == -0x80000000); + assertOrPanic(divFloor(i32, 5, 3) == 1); + assertOrPanic(divFloor(i32, -5, 3) == -2); + assertOrPanic(divFloor(f16, 5.0, 3.0) == 1.0); + assertOrPanic(divFloor(f16, -5.0, 3.0) == -2.0); + assertOrPanic(divFloor(f32, 5.0, 3.0) == 1.0); + assertOrPanic(divFloor(f32, -5.0, 3.0) == -2.0); + assertOrPanic(divFloor(i32, -0x80000000, -2) == 0x40000000); + assertOrPanic(divFloor(i32, 0, -0x80000000) == 0); + assertOrPanic(divFloor(i32, -0x40000001, 0x40000000) == -2); + assertOrPanic(divFloor(i32, -0x80000000, 1) == -0x80000000); - assert(divTrunc(i32, 5, 3) == 1); - assert(divTrunc(i32, -5, 3) == -1); - assert(divTrunc(f16, 5.0, 3.0) == 1.0); - assert(divTrunc(f16, -5.0, 3.0) == -1.0); - assert(divTrunc(f32, 5.0, 3.0) == 1.0); - assert(divTrunc(f32, -5.0, 3.0) == -1.0); - assert(divTrunc(f64, 5.0, 3.0) == 1.0); - assert(divTrunc(f64, -5.0, 3.0) == -1.0); + assertOrPanic(divTrunc(i32, 5, 3) == 1); + assertOrPanic(divTrunc(i32, -5, 3) == -1); + assertOrPanic(divTrunc(f16, 5.0, 3.0) == 1.0); + assertOrPanic(divTrunc(f16, -5.0, 3.0) == -1.0); + assertOrPanic(divTrunc(f32, 5.0, 3.0) == 1.0); + assertOrPanic(divTrunc(f32, -5.0, 3.0) == -1.0); + assertOrPanic(divTrunc(f64, 5.0, 3.0) == 1.0); + assertOrPanic(divTrunc(f64, -5.0, 3.0) == -1.0); comptime { - assert( + assertOrPanic( 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600, ); - assert( + assertOrPanic( @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600, ); - assert( + assertOrPanic( 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2, ); - assert( + assertOrPanic( @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2, ); - assert( + assertOrPanic( @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2, ); - assert( + assertOrPanic( @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2, ); - assert( + assertOrPanic( 4126227191251978491697987544882340798050766755606969681711 % 10 == 1, ); } @@ -78,9 +78,9 @@ fn divTrunc(comptime T: type, a: T, b: T) T { test "@addWithOverflow" { var result: u8 = undefined; - assert(@addWithOverflow(u8, 250, 100, &result)); - assert(!@addWithOverflow(u8, 100, 150, &result)); - assert(result == 250); + assertOrPanic(@addWithOverflow(u8, 250, 100, &result)); + assertOrPanic(!@addWithOverflow(u8, 100, 150, &result)); + assertOrPanic(result == 250); } // TODO test mulWithOverflow @@ -88,9 +88,9 @@ test "@addWithOverflow" { test "@shlWithOverflow" { var result: u16 = undefined; - assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result)); - assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result)); - assert(result == 0b1011111111111100); + assertOrPanic(@shlWithOverflow(u16, 0b0010111111111111, 3, &result)); + assertOrPanic(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result)); + assertOrPanic(result == 0b1011111111111100); } test "@clz" { @@ -99,11 +99,11 @@ test "@clz" { } fn testClz() void { - assert(clz(u8(0b00001010)) == 4); - assert(clz(u8(0b10001010)) == 0); - assert(clz(u8(0b00000000)) == 8); - assert(clz(u128(0xffffffffffffffff)) == 64); - assert(clz(u128(0x10000000000000000)) == 63); + assertOrPanic(clz(u8(0b00001010)) == 4); + assertOrPanic(clz(u8(0b10001010)) == 0); + assertOrPanic(clz(u8(0b00000000)) == 8); + assertOrPanic(clz(u128(0xffffffffffffffff)) == 64); + assertOrPanic(clz(u128(0x10000000000000000)) == 63); } fn clz(x: var) usize { @@ -116,9 +116,9 @@ test "@ctz" { } fn testCtz() void { - assert(ctz(u8(0b10100000)) == 5); - assert(ctz(u8(0b10001010)) == 1); - assert(ctz(u8(0b00000000)) == 8); + assertOrPanic(ctz(u8(0b10100000)) == 5); + assertOrPanic(ctz(u8(0b10001010)) == 1); + assertOrPanic(ctz(u8(0b00000000)) == 8); } fn ctz(x: var) usize { @@ -128,27 +128,27 @@ fn ctz(x: var) usize { test "assignment operators" { var i: u32 = 0; i += 5; - assert(i == 5); + assertOrPanic(i == 5); i -= 2; - assert(i == 3); + assertOrPanic(i == 3); i *= 20; - assert(i == 60); + assertOrPanic(i == 60); i /= 3; - assert(i == 20); + assertOrPanic(i == 20); i %= 11; - assert(i == 9); + assertOrPanic(i == 9); i <<= 1; - assert(i == 18); + assertOrPanic(i == 18); i >>= 2; - assert(i == 4); + assertOrPanic(i == 4); i = 6; i &= 5; - assert(i == 4); + assertOrPanic(i == 4); i ^= 6; - assert(i == 2); + assertOrPanic(i == 2); i = 6; i |= 3; - assert(i == 7); + assertOrPanic(i == 7); } test "three expr in a row" { @@ -170,14 +170,14 @@ fn testThreeExprInARow(f: bool, t: bool) void { assertFalse(i32(7) != --(i32(7))); } fn assertFalse(b: bool) void { - assert(!b); + assertOrPanic(!b); } test "const number literal" { const one = 1; const eleven = ten + one; - assert(eleven == 11); + assertOrPanic(eleven == 11); } const ten = 10; @@ -187,9 +187,9 @@ test "unsigned wrapping" { } fn testUnsignedWrappingEval(x: u32) void { const zero = x +% 1; - assert(zero == 0); + assertOrPanic(zero == 0); const orig = zero -% 1; - assert(orig == maxInt(u32)); + assertOrPanic(orig == maxInt(u32)); } test "signed wrapping" { @@ -198,9 +198,9 @@ test "signed wrapping" { } fn testSignedWrappingEval(x: i32) void { const min_val = x +% 1; - assert(min_val == minInt(i32)); + assertOrPanic(min_val == minInt(i32)); const max_val = min_val -% 1; - assert(max_val == maxInt(i32)); + assertOrPanic(max_val == maxInt(i32)); } test "negation wrapping" { @@ -208,9 +208,9 @@ test "negation wrapping" { comptime testNegationWrappingEval(minInt(i16)); } fn testNegationWrappingEval(x: i16) void { - assert(x == -32768); + assertOrPanic(x == -32768); const neg = -%x; - assert(neg == -32768); + assertOrPanic(neg == -32768); } test "unsigned 64-bit division" { @@ -219,8 +219,8 @@ test "unsigned 64-bit division" { } fn test_u64_div() void { const result = divWithResult(1152921504606846976, 34359738365); - assert(result.quotient == 33554432); - assert(result.remainder == 100663296); + assertOrPanic(result.quotient == 33554432); + assertOrPanic(result.remainder == 100663296); } fn divWithResult(a: u64, b: u64) DivResult { return DivResult{ @@ -234,36 +234,36 @@ const DivResult = struct { }; test "binary not" { - assert(comptime x: { + assertOrPanic(comptime x: { break :x ~u16(0b1010101010101010) == 0b0101010101010101; }); - assert(comptime x: { + assertOrPanic(comptime x: { break :x ~u64(2147483647) == 18446744071562067968; }); testBinaryNot(0b1010101010101010); } fn testBinaryNot(x: u16) void { - assert(~x == 0b0101010101010101); + assertOrPanic(~x == 0b0101010101010101); } test "small int addition" { var x: @IntType(false, 2) = 0; - assert(x == 0); + assertOrPanic(x == 0); x += 1; - assert(x == 1); + assertOrPanic(x == 1); x += 1; - assert(x == 2); + assertOrPanic(x == 2); x += 1; - assert(x == 3); + assertOrPanic(x == 3); var result: @typeOf(x) = 3; - assert(@addWithOverflow(@typeOf(x), x, 1, &result)); + assertOrPanic(@addWithOverflow(@typeOf(x), x, 1, &result)); - assert(result == 0); + assertOrPanic(result == 0); } test "float equality" { @@ -276,20 +276,20 @@ test "float equality" { fn testFloatEqualityImpl(x: f64, y: f64) void { const y2 = x + 1.0; - assert(y == y2); + assertOrPanic(y == y2); } test "allow signed integer division/remainder when values are comptime known and positive or exact" { - assert(5 / 3 == 1); - assert(-5 / -3 == 1); - assert(-6 / 3 == -2); + assertOrPanic(5 / 3 == 1); + assertOrPanic(-5 / -3 == 1); + assertOrPanic(-6 / 3 == -2); - assert(5 % 3 == 2); - assert(-6 % 3 == 0); + assertOrPanic(5 % 3 == 2); + assertOrPanic(-6 % 3 == 0); } test "hex float literal parsing" { - comptime assert(0x1.0 == 1.0); + comptime assertOrPanic(0x1.0 == 1.0); } test "quad hex float literal parsing in range" { @@ -304,7 +304,7 @@ test "quad hex float literal parsing accurate" { // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing. const expected: u128 = 0x3fff1111222233334444555566667777; - assert(@bitCast(u128, a) == expected); + assertOrPanic(@bitCast(u128, a) == expected); } test "hex float literal within range" { @@ -319,7 +319,7 @@ test "truncating shift left" { } fn testShlTrunc(x: u16) void { const shifted = x << 1; - assert(shifted == 65534); + assertOrPanic(shifted == 65534); } test "truncating shift right" { @@ -328,7 +328,7 @@ test "truncating shift right" { } fn testShrTrunc(x: u16) void { const shifted = x >> 1; - assert(shifted == 32767); + assertOrPanic(shifted == 32767); } test "exact shift left" { @@ -337,7 +337,7 @@ test "exact shift left" { } fn testShlExact(x: u8) void { const shifted = @shlExact(x, 2); - assert(shifted == 0b11010100); + assertOrPanic(shifted == 0b11010100); } test "exact shift right" { @@ -346,22 +346,22 @@ test "exact shift right" { } fn testShrExact(x: u8) void { const shifted = @shrExact(x, 2); - assert(shifted == 0b00101101); + assertOrPanic(shifted == 0b00101101); } test "comptime_int addition" { comptime { - assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950); - assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380); + assertOrPanic(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950); + assertOrPanic(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380); } } test "comptime_int multiplication" { comptime { - assert( + assertOrPanic( 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567, ); - assert( + assertOrPanic( 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016, ); } @@ -369,7 +369,7 @@ test "comptime_int multiplication" { test "comptime_int shifting" { comptime { - assert((u128(1) << 127) == 0x80000000000000000000000000000000); + assertOrPanic((u128(1) << 127) == 0x80000000000000000000000000000000); } } @@ -377,16 +377,16 @@ test "comptime_int multi-limb shift and mask" { comptime { var a = 0xefffffffa0000001eeeeeeefaaaaaaab; - assert(u32(a & 0xffffffff) == 0xaaaaaaab); + assertOrPanic(u32(a & 0xffffffff) == 0xaaaaaaab); a >>= 32; - assert(u32(a & 0xffffffff) == 0xeeeeeeef); + assertOrPanic(u32(a & 0xffffffff) == 0xeeeeeeef); a >>= 32; - assert(u32(a & 0xffffffff) == 0xa0000001); + assertOrPanic(u32(a & 0xffffffff) == 0xa0000001); a >>= 32; - assert(u32(a & 0xffffffff) == 0xefffffff); + assertOrPanic(u32(a & 0xffffffff) == 0xefffffff); a >>= 32; - assert(a == 0); + assertOrPanic(a == 0); } } @@ -394,7 +394,7 @@ test "comptime_int multi-limb partial shift right" { comptime { var a = 0x1ffffffffeeeeeeee; a >>= 16; - assert(a == 0x1ffffffffeeee); + assertOrPanic(a == 0x1ffffffffeeee); } } @@ -404,23 +404,23 @@ test "xor" { } fn test_xor() void { - assert(0xFF ^ 0x00 == 0xFF); - assert(0xF0 ^ 0x0F == 0xFF); - assert(0xFF ^ 0xF0 == 0x0F); - assert(0xFF ^ 0x0F == 0xF0); - assert(0xFF ^ 0xFF == 0x00); + assertOrPanic(0xFF ^ 0x00 == 0xFF); + assertOrPanic(0xF0 ^ 0x0F == 0xFF); + assertOrPanic(0xFF ^ 0xF0 == 0x0F); + assertOrPanic(0xFF ^ 0x0F == 0xF0); + assertOrPanic(0xFF ^ 0xFF == 0x00); } test "comptime_int xor" { comptime { - assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF); - assert(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000); - assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000); - assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); - assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF); - assert(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000); + assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF); + assertOrPanic(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000); + assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000); + assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF); + assertOrPanic(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000); } } @@ -434,23 +434,23 @@ fn make_f128(x: f128) f128 { } fn test_f128() void { - assert(@sizeOf(f128) == 16); - assert(make_f128(1.0) == 1.0); - assert(make_f128(1.0) != 1.1); - assert(make_f128(1.0) > 0.9); - assert(make_f128(1.0) >= 0.9); - assert(make_f128(1.0) >= 1.0); + assertOrPanic(@sizeOf(f128) == 16); + assertOrPanic(make_f128(1.0) == 1.0); + assertOrPanic(make_f128(1.0) != 1.1); + assertOrPanic(make_f128(1.0) > 0.9); + assertOrPanic(make_f128(1.0) >= 0.9); + assertOrPanic(make_f128(1.0) >= 1.0); should_not_be_zero(1.0); } fn should_not_be_zero(x: f128) void { - assert(x != 0.0); + assertOrPanic(x != 0.0); } test "comptime float rem int" { comptime { var x = f32(1) % 2; - assert(x == 1.0); + assertOrPanic(x == 1.0); } } @@ -465,8 +465,8 @@ test "remainder division" { } fn remdiv(comptime T: type) void { - assert(T(1) == T(1) % T(2)); - assert(T(1) == T(7) % T(3)); + assertOrPanic(T(1) == T(1) % T(2)); + assertOrPanic(T(1) == T(7) % T(3)); } test "@sqrt" { @@ -480,19 +480,19 @@ test "@sqrt" { const x = 14.0; const y = x * x; const z = @sqrt(@typeOf(y), y); - comptime assert(z == x); + comptime assertOrPanic(z == x); } fn testSqrt(comptime T: type, x: T) void { - assert(@sqrt(T, x * x) == x); + assertOrPanic(@sqrt(T, x * x) == x); } test "comptime_int param and return" { const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702); - assert(a == 137114567242441932203689521744947848950); + assertOrPanic(a == 137114567242441932203689521744947848950); const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768); - assert(b == 985095453608931032642182098849559179469148836107390954364380); + assertOrPanic(b == 985095453608931032642182098849559179469148836107390954364380); } fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int { diff --git a/test/cases/merge_error_sets.zig b/test/stage1/behavior/merge_error_sets.zig similarity index 100% rename from test/cases/merge_error_sets.zig rename to test/stage1/behavior/merge_error_sets.zig diff --git a/test/cases/misc.zig b/test/stage1/behavior/misc.zig similarity index 61% rename from test/cases/misc.zig rename to test/stage1/behavior/misc.zig index 1a34d54e9e..8d2555dddd 100644 --- a/test/cases/misc.zig +++ b/test/stage1/behavior/misc.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const mem = std.mem; const cstr = std.cstr; const builtin = @import("builtin"); @@ -26,38 +26,38 @@ test "call disabled extern fn" { } test "@IntType builtin" { - assert(@IntType(true, 8) == i8); - assert(@IntType(true, 16) == i16); - assert(@IntType(true, 32) == i32); - assert(@IntType(true, 64) == i64); + assertOrPanic(@IntType(true, 8) == i8); + assertOrPanic(@IntType(true, 16) == i16); + assertOrPanic(@IntType(true, 32) == i32); + assertOrPanic(@IntType(true, 64) == i64); - assert(@IntType(false, 8) == u8); - assert(@IntType(false, 16) == u16); - assert(@IntType(false, 32) == u32); - assert(@IntType(false, 64) == u64); + assertOrPanic(@IntType(false, 8) == u8); + assertOrPanic(@IntType(false, 16) == u16); + assertOrPanic(@IntType(false, 32) == u32); + assertOrPanic(@IntType(false, 64) == u64); - assert(i8.bit_count == 8); - assert(i16.bit_count == 16); - assert(i32.bit_count == 32); - assert(i64.bit_count == 64); + assertOrPanic(i8.bit_count == 8); + assertOrPanic(i16.bit_count == 16); + assertOrPanic(i32.bit_count == 32); + assertOrPanic(i64.bit_count == 64); - assert(i8.is_signed); - assert(i16.is_signed); - assert(i32.is_signed); - assert(i64.is_signed); - assert(isize.is_signed); + assertOrPanic(i8.is_signed); + assertOrPanic(i16.is_signed); + assertOrPanic(i32.is_signed); + assertOrPanic(i64.is_signed); + assertOrPanic(isize.is_signed); - assert(!u8.is_signed); - assert(!u16.is_signed); - assert(!u32.is_signed); - assert(!u64.is_signed); - assert(!usize.is_signed); + assertOrPanic(!u8.is_signed); + assertOrPanic(!u16.is_signed); + assertOrPanic(!u32.is_signed); + assertOrPanic(!u64.is_signed); + assertOrPanic(!usize.is_signed); } test "floating point primitive bit counts" { - assert(f16.bit_count == 16); - assert(f32.bit_count == 32); - assert(f64.bit_count == 64); + assertOrPanic(f16.bit_count == 16); + assertOrPanic(f32.bit_count == 32); + assertOrPanic(f64.bit_count == 64); } test "short circuit" { @@ -72,7 +72,7 @@ fn testShortCircuit(f: bool, t: bool) void { var hit_4 = f; if (t or x: { - assert(f); + assertOrPanic(f); break :x f; }) { hit_1 = t; @@ -81,31 +81,31 @@ fn testShortCircuit(f: bool, t: bool) void { hit_2 = t; break :x f; }) { - assert(f); + assertOrPanic(f); } if (t and x: { hit_3 = t; break :x f; }) { - assert(f); + assertOrPanic(f); } if (f and x: { - assert(f); + assertOrPanic(f); break :x f; }) { - assert(f); + assertOrPanic(f); } else { hit_4 = t; } - assert(hit_1); - assert(hit_2); - assert(hit_3); - assert(hit_4); + assertOrPanic(hit_1); + assertOrPanic(hit_2); + assertOrPanic(hit_3); + assertOrPanic(hit_4); } test "truncate" { - assert(testTruncate(0x10fd) == 0xfd); + assertOrPanic(testTruncate(0x10fd) == 0xfd); } fn testTruncate(x: u32) u8 { return @truncate(u8, x); @@ -116,16 +116,16 @@ fn first4KeysOfHomeRow() []const u8 { } test "return string from function" { - assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); + assertOrPanic(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); } const g1: i32 = 1233 + 1; var g2: i32 = 0; test "global variables" { - assert(g2 == 0); + assertOrPanic(g2 == 0); g2 = g1; - assert(g2 == 1234); + assertOrPanic(g2 == 1234); } test "memcpy and memset intrinsics" { @@ -142,7 +142,7 @@ test "builtin static eval" { const x: i32 = comptime x: { break :x 1 + 2 + 3; }; - assert(x == comptime 6); + assertOrPanic(x == comptime 6); } test "slicing" { @@ -163,7 +163,7 @@ test "slicing" { test "constant equal function pointers" { const alias = emptyFn; - assert(comptime x: { + assertOrPanic(comptime x: { break :x emptyFn == alias; }); } @@ -171,25 +171,25 @@ test "constant equal function pointers" { fn emptyFn() void {} test "hex escape" { - assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); + assertOrPanic(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); } test "string concatenation" { - assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); + assertOrPanic(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); } test "array mult operator" { - assert(mem.eql(u8, "ab" ** 5, "ababababab")); + assertOrPanic(mem.eql(u8, "ab" ** 5, "ababababab")); } test "string escapes" { - assert(mem.eql(u8, "\"", "\x22")); - assert(mem.eql(u8, "\'", "\x27")); - assert(mem.eql(u8, "\n", "\x0a")); - assert(mem.eql(u8, "\r", "\x0d")); - assert(mem.eql(u8, "\t", "\x09")); - assert(mem.eql(u8, "\\", "\x5c")); - assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69")); + assertOrPanic(mem.eql(u8, "\"", "\x22")); + assertOrPanic(mem.eql(u8, "\'", "\x27")); + assertOrPanic(mem.eql(u8, "\n", "\x0a")); + assertOrPanic(mem.eql(u8, "\r", "\x0d")); + assertOrPanic(mem.eql(u8, "\t", "\x09")); + assertOrPanic(mem.eql(u8, "\\", "\x5c")); + assertOrPanic(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69")); } test "multiline string" { @@ -199,7 +199,7 @@ test "multiline string" { \\three ; const s2 = "one\ntwo)\nthree"; - assert(mem.eql(u8, s1, s2)); + assertOrPanic(mem.eql(u8, s1, s2)); } test "multiline C string" { @@ -209,11 +209,11 @@ test "multiline C string" { c\\three ; const s2 = c"one\ntwo)\nthree"; - assert(cstr.cmp(s1, s2) == 0); + assertOrPanic(cstr.cmp(s1, s2) == 0); } test "type equality" { - assert(*const u8 != *u8); + assertOrPanic(*const u8 != *u8); } const global_a: i32 = 1234; @@ -221,7 +221,7 @@ const global_b: *const i32 = &global_a; const global_c: *const f32 = @ptrCast(*const f32, global_b); test "compile time global reinterpret" { const d = @ptrCast(*const i32, global_c); - assert(d.* == 1234); + assertOrPanic(d.* == 1234); } test "explicit cast maybe pointers" { @@ -247,8 +247,8 @@ test "cast undefined" { fn testCastUndefined(x: []const u8) void {} test "cast small unsigned to larger signed" { - assert(castSmallUnsignedToLargerSigned1(200) == i16(200)); - assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); + assertOrPanic(castSmallUnsignedToLargerSigned1(200) == i16(200)); + assertOrPanic(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); } fn castSmallUnsignedToLargerSigned1(x: u8) i16 { return x; @@ -258,7 +258,7 @@ fn castSmallUnsignedToLargerSigned2(x: u16) i64 { } test "implicit cast after unreachable" { - assert(outer() == 1234); + assertOrPanic(outer() == 1234); } fn inner() i32 { return 1234; @@ -273,13 +273,13 @@ test "pointer dereferencing" { y.* += 1; - assert(x == 4); - assert(y.* == 4); + assertOrPanic(x == 4); + assertOrPanic(y.* == 4); } test "call result of if else expression" { - assert(mem.eql(u8, f2(true), "a")); - assert(mem.eql(u8, f2(false), "b")); + assertOrPanic(mem.eql(u8, f2(true), "a")); + assertOrPanic(mem.eql(u8, f2(false), "b")); } fn f2(x: bool) []const u8 { return (if (x) fA else fB)(); @@ -321,8 +321,8 @@ const test3_bar = Test3Foo{ .Two = 13 }; fn test3_1(f: Test3Foo) void { switch (f) { Test3Foo.Three => |pt| { - assert(pt.x == 3); - assert(pt.y == 4); + assertOrPanic(pt.x == 3); + assertOrPanic(pt.y == 4); }, else => unreachable, } @@ -330,14 +330,14 @@ fn test3_1(f: Test3Foo) void { fn test3_2(f: Test3Foo) void { switch (f) { Test3Foo.Two => |x| { - assert(x == 13); + assertOrPanic(x == 13); }, else => unreachable, } } test "character literals" { - assert('\'' == single_quote); + assertOrPanic('\'' == single_quote); } const single_quote = '\''; @@ -346,13 +346,13 @@ test "take address of parameter" { } fn testTakeAddressOfParameter(f: f32) void { const f_ptr = &f; - assert(f_ptr.* == 12.34); + assertOrPanic(f_ptr.* == 12.34); } test "pointer comparison" { const a = ([]const u8)("a"); const b = &a; - assert(ptrEql(b, b)); + assertOrPanic(ptrEql(b, b)); } fn ptrEql(a: *const []const u8, b: *const []const u8) bool { return a == b; @@ -367,36 +367,31 @@ test "C string concatenation" { { var i: u32 = 0; while (i < len_with_null) : (i += 1) { - assert(a[i] == b[i]); + assertOrPanic(a[i] == b[i]); } } - assert(a[len] == 0); - assert(b[len] == 0); + assertOrPanic(a[len] == 0); + assertOrPanic(b[len] == 0); } test "cast slice to u8 slice" { - assert(@sizeOf(i32) == 4); - var big_thing_array = []i32{ - 1, - 2, - 3, - 4, - }; + assertOrPanic(@sizeOf(i32) == 4); + var big_thing_array = []i32{ 1, 2, 3, 4 }; const big_thing_slice: []i32 = big_thing_array[0..]; const bytes = @sliceToBytes(big_thing_slice); - assert(bytes.len == 4 * 4); + assertOrPanic(bytes.len == 4 * 4); bytes[4] = 0; bytes[5] = 0; bytes[6] = 0; bytes[7] = 0; - assert(big_thing_slice[1] == 0); + assertOrPanic(big_thing_slice[1] == 0); const big_thing_again = @bytesToSlice(i32, bytes); - assert(big_thing_again[2] == 3); + assertOrPanic(big_thing_again[2] == 3); big_thing_again[2] = -1; - assert(bytes[8] == maxInt(u8)); - assert(bytes[9] == maxInt(u8)); - assert(bytes[10] == maxInt(u8)); - assert(bytes[11] == maxInt(u8)); + assertOrPanic(bytes[8] == maxInt(u8)); + assertOrPanic(bytes[9] == maxInt(u8)); + assertOrPanic(bytes[10] == maxInt(u8)); + assertOrPanic(bytes[11] == maxInt(u8)); } test "pointer to void return type" { @@ -413,7 +408,7 @@ fn testPointerToVoidReturnType2() *const void { test "non const ptr to aliased type" { const int = i32; - assert(?*int == ?*i32); + assertOrPanic(?*int == ?*i32); } test "array 2D const double ptr" { @@ -426,8 +421,8 @@ test "array 2D const double ptr" { fn testArray2DConstDoublePtr(ptr: *const f32) void { const ptr2 = @ptrCast([*]const f32, ptr); - assert(ptr2[0] == 1.0); - assert(ptr2[1] == 2.0); + assertOrPanic(ptr2[0] == 1.0); + assertOrPanic(ptr2[1] == 2.0); } const Tid = builtin.TypeId; @@ -449,32 +444,32 @@ const AUnion = union { test "@typeId" { comptime { - assert(@typeId(type) == Tid.Type); - assert(@typeId(void) == Tid.Void); - assert(@typeId(bool) == Tid.Bool); - assert(@typeId(noreturn) == Tid.NoReturn); - assert(@typeId(i8) == Tid.Int); - assert(@typeId(u8) == Tid.Int); - assert(@typeId(i64) == Tid.Int); - assert(@typeId(u64) == Tid.Int); - assert(@typeId(f32) == Tid.Float); - assert(@typeId(f64) == Tid.Float); - assert(@typeId(*f32) == Tid.Pointer); - assert(@typeId([2]u8) == Tid.Array); - assert(@typeId(AStruct) == Tid.Struct); - assert(@typeId(@typeOf(1)) == Tid.ComptimeInt); - assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat); - assert(@typeId(@typeOf(undefined)) == Tid.Undefined); - assert(@typeId(@typeOf(null)) == Tid.Null); - assert(@typeId(?i32) == Tid.Optional); - assert(@typeId(anyerror!i32) == Tid.ErrorUnion); - assert(@typeId(anyerror) == Tid.ErrorSet); - assert(@typeId(AnEnum) == Tid.Enum); - assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); - assert(@typeId(AUnionEnum) == Tid.Union); - assert(@typeId(AUnion) == Tid.Union); - assert(@typeId(fn () void) == Tid.Fn); - assert(@typeId(@typeOf(builtin)) == Tid.Namespace); + assertOrPanic(@typeId(type) == Tid.Type); + assertOrPanic(@typeId(void) == Tid.Void); + assertOrPanic(@typeId(bool) == Tid.Bool); + assertOrPanic(@typeId(noreturn) == Tid.NoReturn); + assertOrPanic(@typeId(i8) == Tid.Int); + assertOrPanic(@typeId(u8) == Tid.Int); + assertOrPanic(@typeId(i64) == Tid.Int); + assertOrPanic(@typeId(u64) == Tid.Int); + assertOrPanic(@typeId(f32) == Tid.Float); + assertOrPanic(@typeId(f64) == Tid.Float); + assertOrPanic(@typeId(*f32) == Tid.Pointer); + assertOrPanic(@typeId([2]u8) == Tid.Array); + assertOrPanic(@typeId(AStruct) == Tid.Struct); + assertOrPanic(@typeId(@typeOf(1)) == Tid.ComptimeInt); + assertOrPanic(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat); + assertOrPanic(@typeId(@typeOf(undefined)) == Tid.Undefined); + assertOrPanic(@typeId(@typeOf(null)) == Tid.Null); + assertOrPanic(@typeId(?i32) == Tid.Optional); + assertOrPanic(@typeId(anyerror!i32) == Tid.ErrorUnion); + assertOrPanic(@typeId(anyerror) == Tid.ErrorSet); + assertOrPanic(@typeId(AnEnum) == Tid.Enum); + assertOrPanic(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); + assertOrPanic(@typeId(AUnionEnum) == Tid.Union); + assertOrPanic(@typeId(AUnion) == Tid.Union); + assertOrPanic(@typeId(fn () void) == Tid.Fn); + assertOrPanic(@typeId(@typeOf(builtin)) == Tid.Namespace); // TODO bound fn // TODO arg tuple // TODO opaque @@ -490,13 +485,13 @@ test "@typeName" { Unused, }; comptime { - assert(mem.eql(u8, @typeName(i64), "i64")); - assert(mem.eql(u8, @typeName(*usize), "*usize")); + assertOrPanic(mem.eql(u8, @typeName(i64), "i64")); + assertOrPanic(mem.eql(u8, @typeName(*usize), "*usize")); // https://github.com/ziglang/zig/issues/675 - assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)")); - assert(mem.eql(u8, @typeName(Struct), "Struct")); - assert(mem.eql(u8, @typeName(Union), "Union")); - assert(mem.eql(u8, @typeName(Enum), "Enum")); + assertOrPanic(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)")); + assertOrPanic(mem.eql(u8, @typeName(Struct), "Struct")); + assertOrPanic(mem.eql(u8, @typeName(Union), "Union")); + assertOrPanic(mem.eql(u8, @typeName(Enum), "Enum")); } } @@ -504,28 +499,16 @@ fn TypeFromFn(comptime T: type) type { return struct {}; } -test "volatile load and store" { - var number: i32 = 1234; - const ptr = (*volatile i32)(&number); - ptr.* += 1; - assert(ptr.* == 1235); +test "double implicit cast in same expression" { + var x = i32(u16(nine())); + assertOrPanic(x == 9); } - -test "slice string literal has type []const u8" { - comptime { - assert(@typeOf("aoeu"[0..]) == []const u8); - const array = []i32{ - 1, - 2, - 3, - 4, - }; - assert(@typeOf(array[0..]) == []const i32); - } +fn nine() u8 { + return 9; } test "global variable initialized to global variable array element" { - assert(global_ptr == &gdt[0]); + assertOrPanic(global_ptr == &gdt[0]); } const GDTEntry = struct { field: i32, @@ -543,16 +526,12 @@ export fn writeToVRam() void { vram[0] = 'X'; } -test "pointer child field" { - assert((*u32).Child == u32); -} - const OpaqueA = @OpaqueType(); const OpaqueB = @OpaqueType(); test "@OpaqueType" { - assert(*OpaqueA != *OpaqueB); - assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); - assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); + assertOrPanic(*OpaqueA != *OpaqueB); + assertOrPanic(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); + assertOrPanic(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); } test "variable is allowed to be a pointer to an opaque type" { @@ -581,25 +560,6 @@ test "implicit comptime while" { } } -test "struct inside function" { - testStructInFn(); - comptime testStructInFn(); -} - -fn testStructInFn() void { - const BlockKind = u32; - - const Block = struct { - kind: BlockKind, - }; - - var block = Block{ .kind = 1234 }; - - block.kind += 1; - - assert(block.kind == 1235); -} - fn fnThatClosesOverLocalConst() type { const c = 1; return struct { @@ -611,7 +571,7 @@ fn fnThatClosesOverLocalConst() type { test "function closes over local const" { const x = fnThatClosesOverLocalConst().g(); - assert(x == 1); + assertOrPanic(x == 1); } test "cold function" { @@ -648,21 +608,21 @@ export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: Pack test "slicing zero length array" { const s1 = ""[0..]; const s2 = ([]u32{})[0..]; - assert(s1.len == 0); - assert(s2.len == 0); - assert(mem.eql(u8, s1, "")); - assert(mem.eql(u32, s2, []u32{})); + assertOrPanic(s1.len == 0); + assertOrPanic(s2.len == 0); + assertOrPanic(mem.eql(u8, s1, "")); + assertOrPanic(mem.eql(u32, s2, []u32{})); } const addr1 = @ptrCast(*const u8, emptyFn); test "comptime cast fn to ptr" { const addr2 = @ptrCast(*const u8, emptyFn); - comptime assert(addr1 == addr2); + comptime assertOrPanic(addr1 == addr2); } test "equality compare fn ptrs" { var a = emptyFn; - assert(a == a); + assertOrPanic(a == a); } test "self reference through fn ptr field" { @@ -677,5 +637,51 @@ test "self reference through fn ptr field" { }; var a: S.A = undefined; a.f = S.foo; - assert(a.f(a) == 12); + assertOrPanic(a.f(a) == 12); +} + +test "volatile load and store" { + var number: i32 = 1234; + const ptr = (*volatile i32)(&number); + ptr.* += 1; + assertOrPanic(ptr.* == 1235); +} + +test "slice string literal has type []const u8" { + comptime { + assertOrPanic(@typeOf("aoeu"[0..]) == []const u8); + const array = []i32{ 1, 2, 3, 4 }; + assertOrPanic(@typeOf(array[0..]) == []const i32); + } +} + +test "pointer child field" { + assertOrPanic((*u32).Child == u32); +} + +test "struct inside function" { + testStructInFn(); + comptime testStructInFn(); +} + +fn testStructInFn() void { + const BlockKind = u32; + + const Block = struct { + kind: BlockKind, + }; + + var block = Block{ .kind = 1234 }; + + block.kind += 1; + + assertOrPanic(block.kind == 1235); +} + +test "fn call returning scalar optional in equality expression" { + assertOrPanic(getNull() == null); +} + +fn getNull() ?*i32 { + return null; } diff --git a/test/cases/namespace_depends_on_compile_var/a.zig b/test/stage1/behavior/namespace_depends_on_compile_var/a.zig similarity index 100% rename from test/cases/namespace_depends_on_compile_var/a.zig rename to test/stage1/behavior/namespace_depends_on_compile_var/a.zig diff --git a/test/cases/namespace_depends_on_compile_var/b.zig b/test/stage1/behavior/namespace_depends_on_compile_var/b.zig similarity index 100% rename from test/cases/namespace_depends_on_compile_var/b.zig rename to test/stage1/behavior/namespace_depends_on_compile_var/b.zig diff --git a/test/cases/namespace_depends_on_compile_var/index.zig b/test/stage1/behavior/namespace_depends_on_compile_var/index.zig similarity index 62% rename from test/cases/namespace_depends_on_compile_var/index.zig rename to test/stage1/behavior/namespace_depends_on_compile_var/index.zig index ccc49d9367..fe3e0cc020 100644 --- a/test/cases/namespace_depends_on_compile_var/index.zig +++ b/test/stage1/behavior/namespace_depends_on_compile_var/index.zig @@ -1,11 +1,11 @@ const builtin = @import("builtin"); -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "namespace depends on compile var" { if (some_namespace.a_bool) { - assert(some_namespace.a_bool); + assertOrPanic(some_namespace.a_bool); } else { - assert(!some_namespace.a_bool); + assertOrPanic(!some_namespace.a_bool); } } const some_namespace = switch (builtin.os) { diff --git a/test/cases/new_stack_call.zig b/test/stage1/behavior/new_stack_call.zig similarity index 72% rename from test/cases/new_stack_call.zig rename to test/stage1/behavior/new_stack_call.zig index 5912550d54..b9ae2d27cd 100644 --- a/test/cases/new_stack_call.zig +++ b/test/stage1/behavior/new_stack_call.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; var new_stack_bytes: [1024]u8 = undefined; @@ -10,17 +10,17 @@ test "calling a function with a new stack" { const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg); _ = targetFunction(arg); - assert(arg == 1234); - assert(a < b); + assertOrPanic(arg == 1234); + assertOrPanic(a < b); } fn targetFunction(x: i32) usize { - assert(x == 1234); + assertOrPanic(x == 1234); var local_variable: i32 = 42; const ptr = &local_variable; ptr.* += 1; - assert(local_variable == 43); + assertOrPanic(local_variable == 43); return @ptrToInt(ptr); } diff --git a/test/cases/null.zig b/test/stage1/behavior/null.zig similarity index 80% rename from test/cases/null.zig rename to test/stage1/behavior/null.zig index 825db88b1e..e2f86a05ba 100644 --- a/test/cases/null.zig +++ b/test/stage1/behavior/null.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "optional type" { const x: ?bool = true; @@ -17,13 +17,13 @@ test "optional type" { const z = next_x orelse 1234; - assert(z == 1234); + assertOrPanic(z == 1234); const final_x: ?i32 = 13; const num = final_x orelse unreachable; - assert(num == 13); + assertOrPanic(num == 13); } test "test maybe object and get a pointer to the inner value" { @@ -33,7 +33,7 @@ test "test maybe object and get a pointer to the inner value" { b.* = false; } - assert(maybe_bool.? == false); + assertOrPanic(maybe_bool.? == false); } test "rhs maybe unwrap return" { @@ -47,9 +47,9 @@ test "maybe return" { } fn maybeReturnImpl() void { - assert(foo(1235).?); + assertOrPanic(foo(1235).?); if (foo(null) != null) unreachable; - assert(!foo(1234).?); + assertOrPanic(!foo(1234).?); } fn foo(x: ?i32) ?bool { @@ -58,7 +58,7 @@ fn foo(x: ?i32) ?bool { } test "if var maybe pointer" { - assert(shouldBeAPlus1(Particle{ + assertOrPanic(shouldBeAPlus1(Particle{ .a = 14, .b = 1, .c = 1, @@ -84,10 +84,10 @@ const Particle = struct { test "null literal outside function" { const is_null = here_is_a_null_literal.context == null; - assert(is_null); + assertOrPanic(is_null); const is_non_null = here_is_a_null_literal.context != null; - assert(!is_non_null); + assertOrPanic(!is_non_null); } const SillyStruct = struct { context: ?i32, @@ -98,8 +98,8 @@ test "test null runtime" { testTestNullRuntime(null); } fn testTestNullRuntime(x: ?i32) void { - assert(x == null); - assert(!(x != null)); + assertOrPanic(x == null); + assertOrPanic(!(x != null)); } test "optional void" { @@ -108,8 +108,8 @@ test "optional void" { } fn optionalVoidImpl() void { - assert(bar(null) == null); - assert(bar({}) != null); + assertOrPanic(bar(null) == null); + assertOrPanic(bar({}) != null); } fn bar(x: ?void) ?void { @@ -133,7 +133,7 @@ test "unwrap optional which is field of global var" { } struct_with_optional.field = 1234; if (struct_with_optional.field) |payload| { - assert(payload == 1234); + assertOrPanic(payload == 1234); } else { unreachable; } @@ -141,13 +141,13 @@ test "unwrap optional which is field of global var" { test "null with default unwrap" { const x: i32 = null orelse 1; - assert(x == 1); + assertOrPanic(x == 1); } test "optional types" { comptime { const opt_type_struct = StructWithOptionalType{ .t = u8 }; - assert(opt_type_struct.t != null and opt_type_struct.t.? == u8); + assertOrPanic(opt_type_struct.t != null and opt_type_struct.t.? == u8); } } @@ -158,5 +158,5 @@ const StructWithOptionalType = struct { test "optional pointer to 0 bit type null value at runtime" { const EmptyStruct = struct {}; var x: ?*EmptyStruct = null; - assert(x == null); + assertOrPanic(x == null); } diff --git a/test/stage1/behavior/optional.zig b/test/stage1/behavior/optional.zig new file mode 100644 index 0000000000..14692cb1ea --- /dev/null +++ b/test/stage1/behavior/optional.zig @@ -0,0 +1,81 @@ +const assertOrPanic = @import("std").debug.assertOrPanic; + +pub const EmptyStruct = struct {}; + +test "optional pointer to size zero struct" { + var e = EmptyStruct{}; + var o: ?*EmptyStruct = &e; + assertOrPanic(o != null); +} + +test "equality compare nullable pointers" { + testNullPtrsEql(); + comptime testNullPtrsEql(); +} + +fn testNullPtrsEql() void { + var number: i32 = 1234; + + var x: ?*i32 = null; + var y: ?*i32 = null; + assertOrPanic(x == y); + y = &number; + assertOrPanic(x != y); + assertOrPanic(x != &number); + assertOrPanic(&number != x); + x = &number; + assertOrPanic(x == y); + assertOrPanic(x == &number); + assertOrPanic(&number == x); +} + +test "address of unwrap optional" { + const S = struct { + const Foo = struct { + a: i32, + }; + + var global: ?Foo = null; + + pub fn getFoo() anyerror!*Foo { + return &global.?; + } + }; + S.global = S.Foo{ .a = 1234 }; + const foo = S.getFoo() catch unreachable; + assertOrPanic(foo.a == 1234); +} + +test "passing an optional integer as a parameter" { + const S = struct { + fn entry() bool { + var x: i32 = 1234; + return foo(x); + } + + fn foo(x: ?i32) bool { + return x.? == 1234; + } + }; + assertOrPanic(S.entry()); + comptime assertOrPanic(S.entry()); +} + +test "unwrap function call with optional pointer return value" { + const S = struct { + fn entry() void { + assertOrPanic(foo().?.* == 1234); + assertOrPanic(bar() == null); + } + const global: i32 = 1234; + fn foo() ?*const i32 { + return &global; + } + fn bar() ?*i32 { + return null; + } + }; + S.entry(); + // TODO https://github.com/ziglang/zig/issues/1901 + //comptime S.entry(); +} diff --git a/test/cases/pointers.zig b/test/stage1/behavior/pointers.zig similarity index 50% rename from test/cases/pointers.zig rename to test/stage1/behavior/pointers.zig index 47afb60a2e..1142d89ab5 100644 --- a/test/cases/pointers.zig +++ b/test/stage1/behavior/pointers.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; test "dereference pointer" { comptime testDerefPtr(); @@ -10,33 +10,33 @@ fn testDerefPtr() void { var x: i32 = 1234; var y = &x; y.* += 1; - assert(x == 1235); + assertOrPanic(x == 1235); } test "pointer arithmetic" { var ptr = c"abcd"; - assert(ptr[0] == 'a'); + assertOrPanic(ptr[0] == 'a'); ptr += 1; - assert(ptr[0] == 'b'); + assertOrPanic(ptr[0] == 'b'); ptr += 1; - assert(ptr[0] == 'c'); + assertOrPanic(ptr[0] == 'c'); ptr += 1; - assert(ptr[0] == 'd'); + assertOrPanic(ptr[0] == 'd'); ptr += 1; - assert(ptr[0] == 0); + assertOrPanic(ptr[0] == 0); ptr -= 1; - assert(ptr[0] == 'd'); + assertOrPanic(ptr[0] == 'd'); ptr -= 1; - assert(ptr[0] == 'c'); + assertOrPanic(ptr[0] == 'c'); ptr -= 1; - assert(ptr[0] == 'b'); + assertOrPanic(ptr[0] == 'b'); ptr -= 1; - assert(ptr[0] == 'a'); + assertOrPanic(ptr[0] == 'a'); } test "double pointer parsing" { - comptime assert(PtrOf(PtrOf(i32)) == **i32); + comptime assertOrPanic(PtrOf(PtrOf(i32)) == **i32); } fn PtrOf(comptime T: type) type { diff --git a/test/stage1/behavior/popcount.zig b/test/stage1/behavior/popcount.zig new file mode 100644 index 0000000000..f7f8bb523b --- /dev/null +++ b/test/stage1/behavior/popcount.zig @@ -0,0 +1,25 @@ +const assertOrPanic = @import("std").debug.assertOrPanic; + +test "@popCount" { + comptime testPopCount(); + testPopCount(); +} + +fn testPopCount() void { + { + var x: u32 = 0xaa; + assertOrPanic(@popCount(x) == 4); + } + { + var x: u32 = 0xaaaaaaaa; + assertOrPanic(@popCount(x) == 16); + } + { + var x: i16 = -1; + assertOrPanic(@popCount(x) == 16); + } + comptime { + assertOrPanic(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24); + } +} + diff --git a/test/cases/ptrcast.zig b/test/stage1/behavior/ptrcast.zig similarity index 100% rename from test/cases/ptrcast.zig rename to test/stage1/behavior/ptrcast.zig diff --git a/test/cases/pub_enum/index.zig b/test/stage1/behavior/pub_enum/index.zig similarity index 54% rename from test/cases/pub_enum/index.zig rename to test/stage1/behavior/pub_enum/index.zig index 7fdd07b8a3..181113f6bf 100644 --- a/test/cases/pub_enum/index.zig +++ b/test/stage1/behavior/pub_enum/index.zig @@ -1,13 +1,13 @@ const other = @import("other.zig"); -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "pub enum" { pubEnumTest(other.APubEnum.Two); } fn pubEnumTest(foo: other.APubEnum) void { - assert(foo == other.APubEnum.Two); + assertOrPanic(foo == other.APubEnum.Two); } test "cast with imported symbol" { - assert(other.size_t(42) == 42); + assertOrPanic(other.size_t(42) == 42); } diff --git a/test/cases/pub_enum/other.zig b/test/stage1/behavior/pub_enum/other.zig similarity index 100% rename from test/cases/pub_enum/other.zig rename to test/stage1/behavior/pub_enum/other.zig diff --git a/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig b/test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig similarity index 77% rename from test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig rename to test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig index 3c94bb0d49..acbe6b2459 100644 --- a/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig +++ b/test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig @@ -1,14 +1,14 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const mem = @import("std").mem; var ok: bool = false; test "reference a variable in an if after an if in the 2nd switch prong" { foo(true, Num.Two, false, "aoeu"); - assert(!ok); + assertOrPanic(!ok); foo(false, Num.One, false, "aoeu"); - assert(!ok); + assertOrPanic(!ok); foo(true, Num.One, false, "aoeu"); - assert(ok); + assertOrPanic(ok); } const Num = enum { @@ -32,6 +32,6 @@ fn foo(c: bool, k: Num, c2: bool, b: []const u8) void { } fn a(x: []const u8) void { - assert(mem.eql(u8, x, "aoeu")); + assertOrPanic(mem.eql(u8, x, "aoeu")); ok = true; } diff --git a/test/stage1/behavior/reflection.zig b/test/stage1/behavior/reflection.zig new file mode 100644 index 0000000000..f4c142e0f7 --- /dev/null +++ b/test/stage1/behavior/reflection.zig @@ -0,0 +1,96 @@ +const assertOrPanic = @import("std").debug.assertOrPanic; +const mem = @import("std").mem; +const reflection = @This(); + +test "reflection: array, pointer, optional, error union type child" { + comptime { + assertOrPanic(([10]u8).Child == u8); + assertOrPanic((*u8).Child == u8); + assertOrPanic((anyerror!u8).Payload == u8); + assertOrPanic((?u8).Child == u8); + } +} + +test "reflection: function return type, var args, and param types" { + comptime { + assertOrPanic(@typeOf(dummy).ReturnType == i32); + assertOrPanic(!@typeOf(dummy).is_var_args); + assertOrPanic(@typeOf(dummy_varargs).is_var_args); + assertOrPanic(@typeOf(dummy).arg_count == 3); + assertOrPanic(@ArgType(@typeOf(dummy), 0) == bool); + assertOrPanic(@ArgType(@typeOf(dummy), 1) == i32); + assertOrPanic(@ArgType(@typeOf(dummy), 2) == f32); + } +} + +fn dummy(a: bool, b: i32, c: f32) i32 { + return 1234; +} +fn dummy_varargs(args: ...) void {} + +test "reflection: struct member types and names" { + comptime { + assertOrPanic(@memberCount(Foo) == 3); + + assertOrPanic(@memberType(Foo, 0) == i32); + assertOrPanic(@memberType(Foo, 1) == bool); + assertOrPanic(@memberType(Foo, 2) == void); + + assertOrPanic(mem.eql(u8, @memberName(Foo, 0), "one")); + assertOrPanic(mem.eql(u8, @memberName(Foo, 1), "two")); + assertOrPanic(mem.eql(u8, @memberName(Foo, 2), "three")); + } +} + +test "reflection: enum member types and names" { + comptime { + assertOrPanic(@memberCount(Bar) == 4); + + assertOrPanic(@memberType(Bar, 0) == void); + assertOrPanic(@memberType(Bar, 1) == i32); + assertOrPanic(@memberType(Bar, 2) == bool); + assertOrPanic(@memberType(Bar, 3) == f64); + + assertOrPanic(mem.eql(u8, @memberName(Bar, 0), "One")); + assertOrPanic(mem.eql(u8, @memberName(Bar, 1), "Two")); + assertOrPanic(mem.eql(u8, @memberName(Bar, 2), "Three")); + assertOrPanic(mem.eql(u8, @memberName(Bar, 3), "Four")); + } +} + +test "reflection: @field" { + var f = Foo{ + .one = 42, + .two = true, + .three = void{}, + }; + + assertOrPanic(f.one == f.one); + assertOrPanic(@field(f, "o" ++ "ne") == f.one); + assertOrPanic(@field(f, "t" ++ "wo") == f.two); + assertOrPanic(@field(f, "th" ++ "ree") == f.three); + assertOrPanic(@field(Foo, "const" ++ "ant") == Foo.constant); + assertOrPanic(@field(Bar, "O" ++ "ne") == Bar.One); + assertOrPanic(@field(Bar, "T" ++ "wo") == Bar.Two); + assertOrPanic(@field(Bar, "Th" ++ "ree") == Bar.Three); + assertOrPanic(@field(Bar, "F" ++ "our") == Bar.Four); + assertOrPanic(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2)); + @field(f, "o" ++ "ne") = 4; + assertOrPanic(f.one == 4); +} + +const Foo = struct { + const constant = 52; + + one: i32, + two: bool, + three: void, +}; + +const Bar = union(enum) { + One: void, + Two: i32, + Three: bool, + Four: f64, +}; + diff --git a/test/stage1/behavior/sizeof_and_typeof.zig b/test/stage1/behavior/sizeof_and_typeof.zig new file mode 100644 index 0000000000..ddaea4c242 --- /dev/null +++ b/test/stage1/behavior/sizeof_and_typeof.zig @@ -0,0 +1,69 @@ +const builtin = @import("builtin"); +const assertOrPanic = @import("std").debug.assertOrPanic; + +test "@sizeOf and @typeOf" { + const y: @typeOf(x) = 120; + assertOrPanic(@sizeOf(@typeOf(y)) == 2); +} +const x: u16 = 13; +const z: @typeOf(x) = 19; + +const A = struct { + a: u8, + b: u32, + c: u8, + d: u3, + e: u5, + f: u16, + g: u16, +}; + +const P = packed struct { + a: u8, + b: u32, + c: u8, + d: u3, + e: u5, + f: u16, + g: u16, +}; + +test "@byteOffsetOf" { + // Packed structs have fixed memory layout + assertOrPanic(@byteOffsetOf(P, "a") == 0); + assertOrPanic(@byteOffsetOf(P, "b") == 1); + assertOrPanic(@byteOffsetOf(P, "c") == 5); + assertOrPanic(@byteOffsetOf(P, "d") == 6); + assertOrPanic(@byteOffsetOf(P, "e") == 6); + assertOrPanic(@byteOffsetOf(P, "f") == 7); + assertOrPanic(@byteOffsetOf(P, "g") == 9); + + // Normal struct fields can be moved/padded + var a: A = undefined; + assertOrPanic(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a")); + assertOrPanic(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b")); + assertOrPanic(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c")); + assertOrPanic(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d")); + assertOrPanic(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e")); + assertOrPanic(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f")); + assertOrPanic(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g")); +} + +test "@bitOffsetOf" { + // Packed structs have fixed memory layout + assertOrPanic(@bitOffsetOf(P, "a") == 0); + assertOrPanic(@bitOffsetOf(P, "b") == 8); + assertOrPanic(@bitOffsetOf(P, "c") == 40); + assertOrPanic(@bitOffsetOf(P, "d") == 48); + assertOrPanic(@bitOffsetOf(P, "e") == 51); + assertOrPanic(@bitOffsetOf(P, "f") == 56); + assertOrPanic(@bitOffsetOf(P, "g") == 72); + + assertOrPanic(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a")); + assertOrPanic(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b")); + assertOrPanic(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c")); + assertOrPanic(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d")); + assertOrPanic(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e")); + assertOrPanic(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); + assertOrPanic(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); +} diff --git a/test/cases/slice.zig b/test/stage1/behavior/slice.zig similarity index 62% rename from test/cases/slice.zig rename to test/stage1/behavior/slice.zig index b4b43bdd19..cc29e43485 100644 --- a/test/cases/slice.zig +++ b/test/stage1/behavior/slice.zig @@ -1,20 +1,20 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const mem = @import("std").mem; const x = @intToPtr([*]i32, 0x1000)[0..0x500]; const y = x[0x100..]; test "compile time slice of pointer to hard coded address" { - assert(@ptrToInt(x.ptr) == 0x1000); - assert(x.len == 0x500); + assertOrPanic(@ptrToInt(x.ptr) == 0x1000); + assertOrPanic(x.len == 0x500); - assert(@ptrToInt(y.ptr) == 0x1100); - assert(y.len == 0x400); + assertOrPanic(@ptrToInt(y.ptr) == 0x1100); + assertOrPanic(y.len == 0x400); } test "slice child property" { var array: [5]i32 = undefined; var slice = array[0..]; - assert(@typeOf(slice).Child == i32); + assertOrPanic(@typeOf(slice).Child == i32); } test "runtime safety lets us slice from len..len" { @@ -23,7 +23,7 @@ test "runtime safety lets us slice from len..len" { 2, 3, }; - assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); + assertOrPanic(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); } fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { @@ -36,5 +36,5 @@ test "implicitly cast array of size 0 to slice" { } fn assertLenIsZero(msg: []const u8) void { - assert(msg.len == 0); + assertOrPanic(msg.len == 0); } diff --git a/test/cases/struct.zig b/test/stage1/behavior/struct.zig similarity index 64% rename from test/cases/struct.zig rename to test/stage1/behavior/struct.zig index bbbd21912c..92ae2baa15 100644 --- a/test/cases/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const builtin = @import("builtin"); const maxInt = std.math.maxInt; @@ -12,7 +12,7 @@ const empty_global_instance = StructWithNoFields{}; test "call struct static method" { const result = StructWithNoFields.add(3, 4); - assert(result == 7); + assertOrPanic(result == 7); } test "return empty struct instance" { @@ -24,8 +24,8 @@ fn returnEmptyStructInstance() StructWithNoFields { const should_be_11 = StructWithNoFields.add(5, 6); -test "invake static method in global scope" { - assert(should_be_11 == 11); +test "invoke static method in global scope" { + assertOrPanic(should_be_11 == 11); } test "void struct fields" { @@ -34,8 +34,8 @@ test "void struct fields" { .b = 1, .c = void{}, }; - assert(foo.b == 1); - assert(@sizeOf(VoidStructFieldsFoo) == 4); + assertOrPanic(foo.b == 1); + assertOrPanic(@sizeOf(VoidStructFieldsFoo) == 4); } const VoidStructFieldsFoo = struct { a: void, @@ -50,7 +50,7 @@ test "structs" { foo.b = foo.a == 1; testFoo(foo); testMutation(&foo); - assert(foo.c == 100); + assertOrPanic(foo.c == 100); } const StructFoo = struct { a: i32, @@ -58,7 +58,7 @@ const StructFoo = struct { c: f32, }; fn testFoo(foo: StructFoo) void { - assert(foo.b); + assertOrPanic(foo.b); } fn testMutation(foo: *StructFoo) void { foo.c = 100; @@ -83,7 +83,7 @@ test "struct point to self" { root.next = &node; - assert(node.next.next.next.val.x == 1); + assertOrPanic(node.next.next.next.val.x == 1); } test "struct byval assign" { @@ -92,18 +92,18 @@ test "struct byval assign" { foo1.a = 1234; foo2.a = 0; - assert(foo2.a == 0); + assertOrPanic(foo2.a == 0); foo2 = foo1; - assert(foo2.a == 1234); + assertOrPanic(foo2.a == 1234); } fn structInitializer() void { const val = Val{ .x = 42 }; - assert(val.x == 42); + assertOrPanic(val.x == 42); } test "fn call of struct field" { - assert(callStructField(Foo{ .ptr = aFunc }) == 13); + assertOrPanic(callStructField(Foo{ .ptr = aFunc }) == 13); } const Foo = struct { @@ -122,7 +122,7 @@ test "store member function in variable" { const instance = MemberFnTestFoo{ .x = 1234 }; const memberFn = MemberFnTestFoo.member; const result = memberFn(instance); - assert(result == 1234); + assertOrPanic(result == 1234); } const MemberFnTestFoo = struct { x: i32, @@ -134,12 +134,12 @@ const MemberFnTestFoo = struct { test "call member function directly" { const instance = MemberFnTestFoo{ .x = 1234 }; const result = MemberFnTestFoo.member(instance); - assert(result == 1234); + assertOrPanic(result == 1234); } test "member functions" { const r = MemberFnRand{ .seed = 1234 }; - assert(r.getSeed() == 1234); + assertOrPanic(r.getSeed() == 1234); } const MemberFnRand = struct { seed: u32, @@ -150,7 +150,7 @@ const MemberFnRand = struct { test "return struct byval from function" { const bar = makeBar(1234, 5678); - assert(bar.y == 5678); + assertOrPanic(bar.y == 5678); } const Bar = struct { x: i32, @@ -165,7 +165,7 @@ fn makeBar(x: i32, y: i32) Bar { test "empty struct method call" { const es = EmptyStruct{}; - assert(es.method() == 1234); + assertOrPanic(es.method() == 1234); } const EmptyStruct = struct { fn method(es: *const EmptyStruct) i32 { @@ -182,7 +182,7 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 { } test "pass slice of empty struct to fn" { - assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1); + assertOrPanic(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1); } fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { return slice.len; @@ -200,7 +200,7 @@ test "packed struct" { }; foo.y += 1; const four = foo.x + foo.y; - assert(four == 4); + assertOrPanic(four == 4); } const BitField1 = packed struct { @@ -217,17 +217,17 @@ const bit_field_1 = BitField1{ test "bit field access" { var data = bit_field_1; - assert(getA(&data) == 1); - assert(getB(&data) == 2); - assert(getC(&data) == 3); - comptime assert(@sizeOf(BitField1) == 1); + assertOrPanic(getA(&data) == 1); + assertOrPanic(getB(&data) == 2); + assertOrPanic(getC(&data) == 3); + comptime assertOrPanic(@sizeOf(BitField1) == 1); data.b += 1; - assert(data.b == 3); + assertOrPanic(data.b == 3); data.a += 1; - assert(data.a == 2); - assert(data.b == 3); + assertOrPanic(data.a == 2); + assertOrPanic(data.b == 3); } fn getA(data: *const BitField1) u3 { @@ -254,8 +254,8 @@ const Foo96Bits = packed struct { test "packed struct 24bits" { comptime { - assert(@sizeOf(Foo24Bits) == 3); - assert(@sizeOf(Foo96Bits) == 12); + assertOrPanic(@sizeOf(Foo24Bits) == 3); + assertOrPanic(@sizeOf(Foo96Bits) == 12); } var value = Foo96Bits{ @@ -265,28 +265,28 @@ test "packed struct 24bits" { .d = 0, }; value.a += 1; - assert(value.a == 1); - assert(value.b == 0); - assert(value.c == 0); - assert(value.d == 0); + assertOrPanic(value.a == 1); + assertOrPanic(value.b == 0); + assertOrPanic(value.c == 0); + assertOrPanic(value.d == 0); value.b += 1; - assert(value.a == 1); - assert(value.b == 1); - assert(value.c == 0); - assert(value.d == 0); + assertOrPanic(value.a == 1); + assertOrPanic(value.b == 1); + assertOrPanic(value.c == 0); + assertOrPanic(value.d == 0); value.c += 1; - assert(value.a == 1); - assert(value.b == 1); - assert(value.c == 1); - assert(value.d == 0); + assertOrPanic(value.a == 1); + assertOrPanic(value.b == 1); + assertOrPanic(value.c == 1); + assertOrPanic(value.d == 0); value.d += 1; - assert(value.a == 1); - assert(value.b == 1); - assert(value.c == 1); - assert(value.d == 1); + assertOrPanic(value.a == 1); + assertOrPanic(value.b == 1); + assertOrPanic(value.c == 1); + assertOrPanic(value.d == 1); } const FooArray24Bits = packed struct { @@ -297,43 +297,43 @@ const FooArray24Bits = packed struct { test "packed array 24bits" { comptime { - assert(@sizeOf([9]Foo24Bits) == 9 * 3); - assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); + assertOrPanic(@sizeOf([9]Foo24Bits) == 9 * 3); + assertOrPanic(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); } var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1); bytes[bytes.len - 1] = 0xaa; const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; - assert(ptr.a == 0); - assert(ptr.b[0].field == 0); - assert(ptr.b[1].field == 0); - assert(ptr.c == 0); + assertOrPanic(ptr.a == 0); + assertOrPanic(ptr.b[0].field == 0); + assertOrPanic(ptr.b[1].field == 0); + assertOrPanic(ptr.c == 0); ptr.a = maxInt(u16); - assert(ptr.a == maxInt(u16)); - assert(ptr.b[0].field == 0); - assert(ptr.b[1].field == 0); - assert(ptr.c == 0); + assertOrPanic(ptr.a == maxInt(u16)); + assertOrPanic(ptr.b[0].field == 0); + assertOrPanic(ptr.b[1].field == 0); + assertOrPanic(ptr.c == 0); ptr.b[0].field = maxInt(u24); - assert(ptr.a == maxInt(u16)); - assert(ptr.b[0].field == maxInt(u24)); - assert(ptr.b[1].field == 0); - assert(ptr.c == 0); + assertOrPanic(ptr.a == maxInt(u16)); + assertOrPanic(ptr.b[0].field == maxInt(u24)); + assertOrPanic(ptr.b[1].field == 0); + assertOrPanic(ptr.c == 0); ptr.b[1].field = maxInt(u24); - assert(ptr.a == maxInt(u16)); - assert(ptr.b[0].field == maxInt(u24)); - assert(ptr.b[1].field == maxInt(u24)); - assert(ptr.c == 0); + assertOrPanic(ptr.a == maxInt(u16)); + assertOrPanic(ptr.b[0].field == maxInt(u24)); + assertOrPanic(ptr.b[1].field == maxInt(u24)); + assertOrPanic(ptr.c == 0); ptr.c = maxInt(u16); - assert(ptr.a == maxInt(u16)); - assert(ptr.b[0].field == maxInt(u24)); - assert(ptr.b[1].field == maxInt(u24)); - assert(ptr.c == maxInt(u16)); + assertOrPanic(ptr.a == maxInt(u16)); + assertOrPanic(ptr.b[0].field == maxInt(u24)); + assertOrPanic(ptr.b[1].field == maxInt(u24)); + assertOrPanic(ptr.c == maxInt(u16)); - assert(bytes[bytes.len - 1] == 0xaa); + assertOrPanic(bytes[bytes.len - 1] == 0xaa); } const FooStructAligned = packed struct { @@ -347,17 +347,17 @@ const FooArrayOfAligned = packed struct { test "aligned array of packed struct" { comptime { - assert(@sizeOf(FooStructAligned) == 2); - assert(@sizeOf(FooArrayOfAligned) == 2 * 2); + assertOrPanic(@sizeOf(FooStructAligned) == 2); + assertOrPanic(@sizeOf(FooArrayOfAligned) == 2 * 2); } var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned); const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0]; - assert(ptr.a[0].a == 0xbb); - assert(ptr.a[0].b == 0xbb); - assert(ptr.a[1].a == 0xbb); - assert(ptr.a[1].b == 0xbb); + assertOrPanic(ptr.a[0].a == 0xbb); + assertOrPanic(ptr.a[0].b == 0xbb); + assertOrPanic(ptr.a[1].a == 0xbb); + assertOrPanic(ptr.a[1].b == 0xbb); } test "runtime struct initialization of bitfield" { @@ -370,10 +370,10 @@ test "runtime struct initialization of bitfield" { .y = @intCast(u4, x2), }; - assert(s1.x == x1); - assert(s1.y == x1); - assert(s2.x == @intCast(u4, x2)); - assert(s2.y == @intCast(u4, x2)); + assertOrPanic(s1.x == x1); + assertOrPanic(s1.y == x1); + assertOrPanic(s2.x == @intCast(u4, x2)); + assertOrPanic(s2.y == @intCast(u4, x2)); } var x1 = u4(1); @@ -400,18 +400,18 @@ test "native bit field understands endianness" { @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8); var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*; - assert(bitfields.f1 == 0x1111); - assert(bitfields.f2 == 0x2222); - assert(bitfields.f3 == 0x33); - assert(bitfields.f4 == 0x44); - assert(bitfields.f5 == 0x5); - assert(bitfields.f6 == 0x6); - assert(bitfields.f7 == 0x77); + assertOrPanic(bitfields.f1 == 0x1111); + assertOrPanic(bitfields.f2 == 0x2222); + assertOrPanic(bitfields.f3 == 0x33); + assertOrPanic(bitfields.f4 == 0x44); + assertOrPanic(bitfields.f5 == 0x5); + assertOrPanic(bitfields.f6 == 0x6); + assertOrPanic(bitfields.f7 == 0x77); } test "align 1 field before self referential align 8 field as slice return type" { const result = alloc(Expr); - assert(result.len == 0); + assertOrPanic(result.len == 0); } const Expr = union(enum) { @@ -434,10 +434,10 @@ test "call method with mutable reference to struct with no fields" { }; var s = S{}; - assert(S.doC(&s)); - assert(s.doC()); - assert(S.do(&s)); - assert(s.do()); + assertOrPanic(S.doC(&s)); + assertOrPanic(s.doC()); + assertOrPanic(S.do(&s)); + assertOrPanic(s.do()); } test "implicit cast packed struct field to const ptr" { @@ -453,7 +453,7 @@ test "implicit cast packed struct field to const ptr" { var lup: LevelUpMove = undefined; lup.level = 12; const res = LevelUpMove.toInt(lup.level); - assert(res == 12); + assertOrPanic(res == 12); } test "pointer to packed struct member in a stack variable" { @@ -464,7 +464,7 @@ test "pointer to packed struct member in a stack variable" { var s = S{ .a = 2, .b = 0 }; var b_ptr = &s.b; - assert(s.b == 0); + assertOrPanic(s.b == 0); b_ptr.* = 2; - assert(s.b == 2); + assertOrPanic(s.b == 2); } diff --git a/test/cases/struct_contains_null_ptr_itself.zig b/test/stage1/behavior/struct_contains_null_ptr_itself.zig similarity index 81% rename from test/cases/struct_contains_null_ptr_itself.zig rename to test/stage1/behavior/struct_contains_null_ptr_itself.zig index 21175974b3..4cc479f31c 100644 --- a/test/cases/struct_contains_null_ptr_itself.zig +++ b/test/stage1/behavior/struct_contains_null_ptr_itself.zig @@ -1,9 +1,9 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; test "struct contains null pointer which contains original struct" { var x: ?*NodeLineComment = null; - assert(x == null); + assertOrPanic(x == null); } pub const Node = struct { diff --git a/test/cases/struct_contains_slice_of_itself.zig b/test/stage1/behavior/struct_contains_slice_of_itself.zig similarity index 68% rename from test/cases/struct_contains_slice_of_itself.zig rename to test/stage1/behavior/struct_contains_slice_of_itself.zig index aa3075312c..15780a7c44 100644 --- a/test/cases/struct_contains_slice_of_itself.zig +++ b/test/stage1/behavior/struct_contains_slice_of_itself.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const Node = struct { payload: i32, @@ -39,12 +39,12 @@ test "struct contains slice of itself" { .payload = 1234, .children = nodes[0..], }; - assert(root.payload == 1234); - assert(root.children[0].payload == 1); - assert(root.children[1].payload == 2); - assert(root.children[2].payload == 3); - assert(root.children[2].children[0].payload == 31); - assert(root.children[2].children[1].payload == 32); + assertOrPanic(root.payload == 1234); + assertOrPanic(root.children[0].payload == 1); + assertOrPanic(root.children[1].payload == 2); + assertOrPanic(root.children[2].payload == 3); + assertOrPanic(root.children[2].children[0].payload == 31); + assertOrPanic(root.children[2].children[1].payload == 32); } test "struct contains aligned slice of itself" { @@ -76,10 +76,10 @@ test "struct contains aligned slice of itself" { .payload = 1234, .children = nodes[0..], }; - assert(root.payload == 1234); - assert(root.children[0].payload == 1); - assert(root.children[1].payload == 2); - assert(root.children[2].payload == 3); - assert(root.children[2].children[0].payload == 31); - assert(root.children[2].children[1].payload == 32); + assertOrPanic(root.payload == 1234); + assertOrPanic(root.children[0].payload == 1); + assertOrPanic(root.children[1].payload == 2); + assertOrPanic(root.children[2].payload == 3); + assertOrPanic(root.children[2].children[0].payload == 31); + assertOrPanic(root.children[2].children[1].payload == 32); } diff --git a/test/cases/switch.zig b/test/stage1/behavior/switch.zig similarity index 72% rename from test/cases/switch.zig rename to test/stage1/behavior/switch.zig index 1162fdd4b2..4ac971397e 100644 --- a/test/cases/switch.zig +++ b/test/stage1/behavior/switch.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "switch with numbers" { testSwitchWithNumbers(13); @@ -10,14 +10,14 @@ fn testSwitchWithNumbers(x: u32) void { 13 => true, else => false, }; - assert(result); + assertOrPanic(result); } test "switch with all ranges" { - assert(testSwitchWithAllRanges(50, 3) == 1); - assert(testSwitchWithAllRanges(101, 0) == 2); - assert(testSwitchWithAllRanges(300, 5) == 3); - assert(testSwitchWithAllRanges(301, 6) == 6); + assertOrPanic(testSwitchWithAllRanges(50, 3) == 1); + assertOrPanic(testSwitchWithAllRanges(101, 0) == 2); + assertOrPanic(testSwitchWithAllRanges(300, 5) == 3); + assertOrPanic(testSwitchWithAllRanges(301, 6) == 6); } fn testSwitchWithAllRanges(x: u32, y: u32) u32 { @@ -40,7 +40,7 @@ test "implicit comptime switch" { }; comptime { - assert(result + 1 == 14); + assertOrPanic(result + 1 == 14); } } @@ -71,7 +71,7 @@ fn nonConstSwitch(foo: SwitchStatmentFoo) void { SwitchStatmentFoo.C => 3, SwitchStatmentFoo.D => 4, }; - assert(val == 3); + assertOrPanic(val == 3); } const SwitchStatmentFoo = enum { A, @@ -93,10 +93,10 @@ const SwitchProngWithVarEnum = union(enum) { fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void { switch (a) { SwitchProngWithVarEnum.One => |x| { - assert(x == 13); + assertOrPanic(x == 13); }, SwitchProngWithVarEnum.Two => |x| { - assert(x == 13.0); + assertOrPanic(x == 13.0); }, SwitchProngWithVarEnum.Meh => |x| { const v: void = x; @@ -116,7 +116,7 @@ fn testSwitchEnumPtrCapture() void { else => unreachable, } switch (value) { - SwitchProngWithVarEnum.One => |x| assert(x == 1235), + SwitchProngWithVarEnum.One => |x| assertOrPanic(x == 1235), else => unreachable, } } @@ -127,7 +127,7 @@ test "switch with multiple expressions" { 4, 5, 6 => 2, else => i32(3), }; - assert(x == 2); + assertOrPanic(x == 2); } fn returnsFive() i32 { return 5; @@ -149,12 +149,12 @@ fn returnsFalse() bool { } } test "switch on const enum with var" { - assert(!returnsFalse()); + assertOrPanic(!returnsFalse()); } test "switch on type" { - assert(trueIfBoolFalseOtherwise(bool)); - assert(!trueIfBoolFalseOtherwise(i32)); + assertOrPanic(trueIfBoolFalseOtherwise(bool)); + assertOrPanic(!trueIfBoolFalseOtherwise(i32)); } fn trueIfBoolFalseOtherwise(comptime T: type) bool { @@ -170,16 +170,16 @@ test "switch handles all cases of number" { } fn testSwitchHandleAllCases() void { - assert(testSwitchHandleAllCasesExhaustive(0) == 3); - assert(testSwitchHandleAllCasesExhaustive(1) == 2); - assert(testSwitchHandleAllCasesExhaustive(2) == 1); - assert(testSwitchHandleAllCasesExhaustive(3) == 0); + assertOrPanic(testSwitchHandleAllCasesExhaustive(0) == 3); + assertOrPanic(testSwitchHandleAllCasesExhaustive(1) == 2); + assertOrPanic(testSwitchHandleAllCasesExhaustive(2) == 1); + assertOrPanic(testSwitchHandleAllCasesExhaustive(3) == 0); - assert(testSwitchHandleAllCasesRange(100) == 0); - assert(testSwitchHandleAllCasesRange(200) == 1); - assert(testSwitchHandleAllCasesRange(201) == 2); - assert(testSwitchHandleAllCasesRange(202) == 4); - assert(testSwitchHandleAllCasesRange(230) == 3); + assertOrPanic(testSwitchHandleAllCasesRange(100) == 0); + assertOrPanic(testSwitchHandleAllCasesRange(200) == 1); + assertOrPanic(testSwitchHandleAllCasesRange(201) == 2); + assertOrPanic(testSwitchHandleAllCasesRange(202) == 4); + assertOrPanic(testSwitchHandleAllCasesRange(230) == 3); } fn testSwitchHandleAllCasesExhaustive(x: u2) u2 { @@ -207,8 +207,8 @@ test "switch all prongs unreachable" { } fn testAllProngsUnreachable() void { - assert(switchWithUnreachable(1) == 2); - assert(switchWithUnreachable(2) == 10); + assertOrPanic(switchWithUnreachable(1) == 2); + assertOrPanic(switchWithUnreachable(2) == 10); } fn switchWithUnreachable(x: i32) i32 { @@ -230,7 +230,7 @@ test "capture value of switch with all unreachable prongs" { const x = return_a_number() catch |err| switch (err) { else => unreachable, }; - assert(x == 1); + assertOrPanic(x == 1); } test "switching on booleans" { @@ -239,14 +239,14 @@ test "switching on booleans" { } fn testSwitchOnBools() void { - assert(testSwitchOnBoolsTrueAndFalse(true) == false); - assert(testSwitchOnBoolsTrueAndFalse(false) == true); + assertOrPanic(testSwitchOnBoolsTrueAndFalse(true) == false); + assertOrPanic(testSwitchOnBoolsTrueAndFalse(false) == true); - assert(testSwitchOnBoolsTrueWithElse(true) == false); - assert(testSwitchOnBoolsTrueWithElse(false) == true); + assertOrPanic(testSwitchOnBoolsTrueWithElse(true) == false); + assertOrPanic(testSwitchOnBoolsTrueWithElse(false) == true); - assert(testSwitchOnBoolsFalseWithElse(true) == false); - assert(testSwitchOnBoolsFalseWithElse(false) == true); + assertOrPanic(testSwitchOnBoolsFalseWithElse(true) == false); + assertOrPanic(testSwitchOnBoolsFalseWithElse(false) == true); } fn testSwitchOnBoolsTrueAndFalse(x: bool) bool { diff --git a/test/cases/switch_prong_err_enum.zig b/test/stage1/behavior/switch_prong_err_enum.zig similarity index 79% rename from test/cases/switch_prong_err_enum.zig rename to test/stage1/behavior/switch_prong_err_enum.zig index 89060690fc..6ac1919f0d 100644 --- a/test/cases/switch_prong_err_enum.zig +++ b/test/stage1/behavior/switch_prong_err_enum.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; var read_count: u64 = 0; @@ -22,9 +22,9 @@ fn doThing(form_id: u64) anyerror!FormValue { test "switch prong returns error enum" { switch (doThing(17) catch unreachable) { FormValue.Address => |payload| { - assert(payload == 1); + assertOrPanic(payload == 1); }, else => unreachable, } - assert(read_count == 1); + assertOrPanic(read_count == 1); } diff --git a/test/cases/switch_prong_implicit_cast.zig b/test/stage1/behavior/switch_prong_implicit_cast.zig similarity index 82% rename from test/cases/switch_prong_implicit_cast.zig rename to test/stage1/behavior/switch_prong_implicit_cast.zig index 56d37e290f..4ca031e2e1 100644 --- a/test/cases/switch_prong_implicit_cast.zig +++ b/test/stage1/behavior/switch_prong_implicit_cast.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const FormValue = union(enum) { One: void, @@ -18,5 +18,5 @@ test "switch prong implicit cast" { FormValue.One => false, FormValue.Two => |x| x, }; - assert(result); + assertOrPanic(result); } diff --git a/test/cases/syntax.zig b/test/stage1/behavior/syntax.zig similarity index 99% rename from test/cases/syntax.zig rename to test/stage1/behavior/syntax.zig index 0c8c3c5ed3..451e396142 100644 --- a/test/cases/syntax.zig +++ b/test/stage1/behavior/syntax.zig @@ -57,3 +57,4 @@ fn asm_lists() void { :::"a","b",); } } + diff --git a/test/cases/this.zig b/test/stage1/behavior/this.zig similarity index 74% rename from test/cases/this.zig rename to test/stage1/behavior/this.zig index c7be074f36..0e3a7a03ae 100644 --- a/test/cases/this.zig +++ b/test/stage1/behavior/this.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const module = @This(); @@ -20,7 +20,7 @@ fn add(x: i32, y: i32) i32 { } test "this refer to module call private fn" { - assert(module.add(1, 2) == 3); + assertOrPanic(module.add(1, 2) == 3); } test "this refer to container" { @@ -29,6 +29,7 @@ test "this refer to container" { .y = 34, }; pt.addOne(); - assert(pt.x == 13); - assert(pt.y == 35); + assertOrPanic(pt.x == 13); + assertOrPanic(pt.y == 35); } + diff --git a/test/cases/truncate.zig b/test/stage1/behavior/truncate.zig similarity index 65% rename from test/cases/truncate.zig rename to test/stage1/behavior/truncate.zig index 02b5085ccd..b7904bc7fb 100644 --- a/test/cases/truncate.zig +++ b/test/stage1/behavior/truncate.zig @@ -1,8 +1,8 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; test "truncate u0 to larger integer allowed and has comptime known result" { var x: u0 = 0; const y = @truncate(u8, x); - comptime assert(y == 0); + comptime assertOrPanic(y == 0); } diff --git a/test/cases/try.zig b/test/stage1/behavior/try.zig similarity index 79% rename from test/cases/try.zig rename to test/stage1/behavior/try.zig index 450a9af6ac..ed48875eb4 100644 --- a/test/cases/try.zig +++ b/test/stage1/behavior/try.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "try on error union" { tryOnErrorUnionImpl(); @@ -11,7 +11,7 @@ fn tryOnErrorUnionImpl() void { error.CrappedOut => i32(2), else => unreachable, }; - assert(x == 11); + assertOrPanic(x == 11); } fn returnsTen() anyerror!i32 { @@ -20,10 +20,10 @@ fn returnsTen() anyerror!i32 { test "try without vars" { const result1 = if (failIfTrue(true)) 1 else |_| i32(2); - assert(result1 == 2); + assertOrPanic(result1 == 2); const result2 = if (failIfTrue(false)) 1 else |_| i32(2); - assert(result2 == 1); + assertOrPanic(result2 == 1); } fn failIfTrue(ok: bool) anyerror!void { @@ -38,6 +38,6 @@ test "try then not executed with assignment" { if (failIfTrue(true)) { unreachable; } else |err| { - assert(err == error.ItBroke); + assertOrPanic(err == error.ItBroke); } } diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig new file mode 100644 index 0000000000..5ad80e06e1 --- /dev/null +++ b/test/stage1/behavior/type_info.zig @@ -0,0 +1,264 @@ +const assertOrPanic = @import("std").debug.assertOrPanic; +const mem = @import("std").mem; +const TypeInfo = @import("builtin").TypeInfo; +const TypeId = @import("builtin").TypeId; + +test "type info: tag type, void info" { + testBasic(); + comptime testBasic(); +} + +fn testBasic() void { + assertOrPanic(@TagType(TypeInfo) == TypeId); + const void_info = @typeInfo(void); + assertOrPanic(TypeId(void_info) == TypeId.Void); + assertOrPanic(void_info.Void == {}); +} + +test "type info: integer, floating point type info" { + testIntFloat(); + comptime testIntFloat(); +} + +fn testIntFloat() void { + const u8_info = @typeInfo(u8); + assertOrPanic(TypeId(u8_info) == TypeId.Int); + assertOrPanic(!u8_info.Int.is_signed); + assertOrPanic(u8_info.Int.bits == 8); + + const f64_info = @typeInfo(f64); + assertOrPanic(TypeId(f64_info) == TypeId.Float); + assertOrPanic(f64_info.Float.bits == 64); +} + +test "type info: pointer type info" { + testPointer(); + comptime testPointer(); +} + +fn testPointer() void { + const u32_ptr_info = @typeInfo(*u32); + assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer); + assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); + assertOrPanic(u32_ptr_info.Pointer.is_const == false); + assertOrPanic(u32_ptr_info.Pointer.is_volatile == false); + assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(u32)); + assertOrPanic(u32_ptr_info.Pointer.child == u32); +} + +test "type info: unknown length pointer type info" { + testUnknownLenPtr(); + comptime testUnknownLenPtr(); +} + +fn testUnknownLenPtr() void { + const u32_ptr_info = @typeInfo([*]const volatile f64); + assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer); + assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); + assertOrPanic(u32_ptr_info.Pointer.is_const == true); + assertOrPanic(u32_ptr_info.Pointer.is_volatile == true); + assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(f64)); + assertOrPanic(u32_ptr_info.Pointer.child == f64); +} + +test "type info: slice type info" { + testSlice(); + comptime testSlice(); +} + +fn testSlice() void { + const u32_slice_info = @typeInfo([]u32); + assertOrPanic(TypeId(u32_slice_info) == TypeId.Pointer); + assertOrPanic(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); + assertOrPanic(u32_slice_info.Pointer.is_const == false); + assertOrPanic(u32_slice_info.Pointer.is_volatile == false); + assertOrPanic(u32_slice_info.Pointer.alignment == 4); + assertOrPanic(u32_slice_info.Pointer.child == u32); +} + +test "type info: array type info" { + testArray(); + comptime testArray(); +} + +fn testArray() void { + const arr_info = @typeInfo([42]bool); + assertOrPanic(TypeId(arr_info) == TypeId.Array); + assertOrPanic(arr_info.Array.len == 42); + assertOrPanic(arr_info.Array.child == bool); +} + +test "type info: optional type info" { + testOptional(); + comptime testOptional(); +} + +fn testOptional() void { + const null_info = @typeInfo(?void); + assertOrPanic(TypeId(null_info) == TypeId.Optional); + assertOrPanic(null_info.Optional.child == void); +} + +test "type info: promise info" { + testPromise(); + comptime testPromise(); +} + +fn testPromise() void { + const null_promise_info = @typeInfo(promise); + assertOrPanic(TypeId(null_promise_info) == TypeId.Promise); + assertOrPanic(null_promise_info.Promise.child == null); + + const promise_info = @typeInfo(promise->usize); + assertOrPanic(TypeId(promise_info) == TypeId.Promise); + assertOrPanic(promise_info.Promise.child.? == usize); +} + +test "type info: error set, error union info" { + testErrorSet(); + comptime testErrorSet(); +} + +fn testErrorSet() void { + const TestErrorSet = error{ + First, + Second, + Third, + }; + + const error_set_info = @typeInfo(TestErrorSet); + assertOrPanic(TypeId(error_set_info) == TypeId.ErrorSet); + assertOrPanic(error_set_info.ErrorSet.errors.len == 3); + assertOrPanic(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); + assertOrPanic(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third)); + + const error_union_info = @typeInfo(TestErrorSet!usize); + assertOrPanic(TypeId(error_union_info) == TypeId.ErrorUnion); + assertOrPanic(error_union_info.ErrorUnion.error_set == TestErrorSet); + assertOrPanic(error_union_info.ErrorUnion.payload == usize); +} + +test "type info: enum info" { + testEnum(); + comptime testEnum(); +} + +fn testEnum() void { + const Os = enum { + Windows, + Macos, + Linux, + FreeBSD, + }; + + const os_info = @typeInfo(Os); + assertOrPanic(TypeId(os_info) == TypeId.Enum); + assertOrPanic(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); + assertOrPanic(os_info.Enum.fields.len == 4); + assertOrPanic(mem.eql(u8, os_info.Enum.fields[1].name, "Macos")); + assertOrPanic(os_info.Enum.fields[3].value == 3); + assertOrPanic(os_info.Enum.tag_type == u2); + assertOrPanic(os_info.Enum.defs.len == 0); +} + +test "type info: union info" { + testUnion(); + comptime testUnion(); +} + +fn testUnion() void { + const typeinfo_info = @typeInfo(TypeInfo); + assertOrPanic(TypeId(typeinfo_info) == TypeId.Union); + assertOrPanic(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); + assertOrPanic(typeinfo_info.Union.tag_type.? == TypeId); + assertOrPanic(typeinfo_info.Union.fields.len == 24); + assertOrPanic(typeinfo_info.Union.fields[4].enum_field != null); + assertOrPanic(typeinfo_info.Union.fields[4].enum_field.?.value == 4); + assertOrPanic(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); + assertOrPanic(typeinfo_info.Union.defs.len == 20); + + const TestNoTagUnion = union { + Foo: void, + Bar: u32, + }; + + const notag_union_info = @typeInfo(TestNoTagUnion); + assertOrPanic(TypeId(notag_union_info) == TypeId.Union); + assertOrPanic(notag_union_info.Union.tag_type == null); + assertOrPanic(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); + assertOrPanic(notag_union_info.Union.fields.len == 2); + assertOrPanic(notag_union_info.Union.fields[0].enum_field == null); + assertOrPanic(notag_union_info.Union.fields[1].field_type == u32); + + const TestExternUnion = extern union { + foo: *c_void, + }; + + const extern_union_info = @typeInfo(TestExternUnion); + assertOrPanic(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); + assertOrPanic(extern_union_info.Union.tag_type == null); + assertOrPanic(extern_union_info.Union.fields[0].enum_field == null); + assertOrPanic(extern_union_info.Union.fields[0].field_type == *c_void); +} + +test "type info: struct info" { + testStruct(); + comptime testStruct(); +} + +fn testStruct() void { + const struct_info = @typeInfo(TestStruct); + assertOrPanic(TypeId(struct_info) == TypeId.Struct); + assertOrPanic(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); + assertOrPanic(struct_info.Struct.fields.len == 3); + assertOrPanic(struct_info.Struct.fields[1].offset == null); + assertOrPanic(struct_info.Struct.fields[2].field_type == *TestStruct); + assertOrPanic(struct_info.Struct.defs.len == 2); + assertOrPanic(struct_info.Struct.defs[0].is_pub); + assertOrPanic(!struct_info.Struct.defs[0].data.Fn.is_extern); + assertOrPanic(struct_info.Struct.defs[0].data.Fn.lib_name == null); + assertOrPanic(struct_info.Struct.defs[0].data.Fn.return_type == void); + assertOrPanic(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void); +} + +const TestStruct = packed struct { + const Self = @This(); + + fieldA: usize, + fieldB: void, + fieldC: *Self, + + pub fn foo(self: *const Self) void {} +}; + +test "type info: function type info" { + testFunction(); + comptime testFunction(); +} + +fn testFunction() void { + const fn_info = @typeInfo(@typeOf(foo)); + assertOrPanic(TypeId(fn_info) == TypeId.Fn); + assertOrPanic(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); + assertOrPanic(fn_info.Fn.is_generic); + assertOrPanic(fn_info.Fn.args.len == 2); + assertOrPanic(fn_info.Fn.is_var_args); + assertOrPanic(fn_info.Fn.return_type == null); + assertOrPanic(fn_info.Fn.async_allocator_type == null); + + const test_instance: TestStruct = undefined; + const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); + assertOrPanic(TypeId(bound_fn_info) == TypeId.BoundFn); + assertOrPanic(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct); +} + +fn foo(comptime a: usize, b: bool, args: ...) usize { + return 0; +} + +test "typeInfo with comptime parameter in struct fn def" { + const S = struct { + pub fn func(comptime x: f32) void {} + }; + comptime var info = @typeInfo(S); +} diff --git a/test/cases/undefined.zig b/test/stage1/behavior/undefined.zig similarity index 59% rename from test/cases/undefined.zig rename to test/stage1/behavior/undefined.zig index 83c620d211..333e217d49 100644 --- a/test/cases/undefined.zig +++ b/test/stage1/behavior/undefined.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const mem = @import("std").mem; fn initStaticArray() [10]i32 { @@ -11,16 +11,16 @@ fn initStaticArray() [10]i32 { } const static_array = initStaticArray(); test "init static array to undefined" { - assert(static_array[0] == 1); - assert(static_array[4] == 2); - assert(static_array[7] == 3); - assert(static_array[9] == 4); + assertOrPanic(static_array[0] == 1); + assertOrPanic(static_array[4] == 2); + assertOrPanic(static_array[7] == 3); + assertOrPanic(static_array[9] == 4); comptime { - assert(static_array[0] == 1); - assert(static_array[4] == 2); - assert(static_array[7] == 3); - assert(static_array[9] == 4); + assertOrPanic(static_array[0] == 1); + assertOrPanic(static_array[4] == 2); + assertOrPanic(static_array[7] == 3); + assertOrPanic(static_array[9] == 4); } } @@ -40,12 +40,12 @@ test "assign undefined to struct" { comptime { var foo: Foo = undefined; setFooX(&foo); - assert(foo.x == 2); + assertOrPanic(foo.x == 2); } { var foo: Foo = undefined; setFooX(&foo); - assert(foo.x == 2); + assertOrPanic(foo.x == 2); } } @@ -53,16 +53,17 @@ test "assign undefined to struct with method" { comptime { var foo: Foo = undefined; foo.setFooXMethod(); - assert(foo.x == 3); + assertOrPanic(foo.x == 3); } { var foo: Foo = undefined; foo.setFooXMethod(); - assert(foo.x == 3); + assertOrPanic(foo.x == 3); } } test "type name of undefined" { const x = undefined; - assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); + assertOrPanic(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); } + diff --git a/test/cases/underscore.zig b/test/stage1/behavior/underscore.zig similarity index 91% rename from test/cases/underscore.zig rename to test/stage1/behavior/underscore.zig index da1c97659c..7443319336 100644 --- a/test/cases/underscore.zig +++ b/test/stage1/behavior/underscore.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; test "ignore lval with underscore" { _ = false; diff --git a/test/cases/union.zig b/test/stage1/behavior/union.zig similarity index 77% rename from test/cases/union.zig rename to test/stage1/behavior/union.zig index 019a7012da..c8e8feb11e 100644 --- a/test/cases/union.zig +++ b/test/stage1/behavior/union.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const Value = union(enum) { Int: u64, @@ -27,11 +27,11 @@ const array = []Value{ test "unions embedded in aggregate types" { switch (array[1]) { - Value.Array => |arr| assert(arr[4] == 3), + Value.Array => |arr| assertOrPanic(arr[4] == 3), else => unreachable, } switch ((err catch unreachable).val1) { - Value.Int => |x| assert(x == 1234), + Value.Int => |x| assertOrPanic(x == 1234), else => unreachable, } } @@ -43,18 +43,18 @@ const Foo = union { test "basic unions" { var foo = Foo{ .int = 1 }; - assert(foo.int == 1); + assertOrPanic(foo.int == 1); foo = Foo{ .float = 12.34 }; - assert(foo.float == 12.34); + assertOrPanic(foo.float == 12.34); } test "comptime union field access" { comptime { var foo = Foo{ .int = 0 }; - assert(foo.int == 0); + assertOrPanic(foo.int == 0); foo = Foo{ .float = 42.42 }; - assert(foo.float == 42.42); + assertOrPanic(foo.float == 42.42); } } @@ -62,10 +62,10 @@ test "init union with runtime value" { var foo: Foo = undefined; setFloat(&foo, 12.34); - assert(foo.float == 12.34); + assertOrPanic(foo.float == 12.34); setInt(&foo, 42); - assert(foo.int == 42); + assertOrPanic(foo.int == 42); } fn setFloat(foo: *Foo, x: f64) void { @@ -83,9 +83,9 @@ const FooExtern = extern union { test "basic extern unions" { var foo = FooExtern{ .int = 1 }; - assert(foo.int == 1); + assertOrPanic(foo.int == 1); foo.float = 12.34; - assert(foo.float == 12.34); + assertOrPanic(foo.float == 12.34); } const Letter = enum { @@ -105,11 +105,11 @@ test "union with specified enum tag" { } fn doTest() void { - assert(bar(Payload{ .A = 1234 }) == -10); + assertOrPanic(bar(Payload{ .A = 1234 }) == -10); } fn bar(value: Payload) i32 { - assert(Letter(value) == Letter.A); + assertOrPanic(Letter(value) == Letter.A); return switch (value) { Payload.A => |x| return x - 1244, Payload.B => |x| if (x == 12.34) i32(20) else 21, @@ -125,8 +125,8 @@ const MultipleChoice = union(enum(u32)) { }; test "simple union(enum(u32))" { var x = MultipleChoice.C; - assert(x == MultipleChoice.C); - assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60); + assertOrPanic(x == MultipleChoice.C); + assertOrPanic(@enumToInt(@TagType(MultipleChoice)(x)) == 60); } const MultipleChoice2 = union(enum(u32)) { @@ -142,14 +142,14 @@ const MultipleChoice2 = union(enum(u32)) { }; test "union(enum(u32)) with specified and unspecified tag values" { - comptime assert(@TagType(@TagType(MultipleChoice2)) == u32); + comptime assertOrPanic(@TagType(@TagType(MultipleChoice2)) == u32); testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); } fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { - assert(@enumToInt(@TagType(MultipleChoice2)(x)) == 60); - assert(1123 == switch (x) { + assertOrPanic(@enumToInt(@TagType(MultipleChoice2)(x)) == 60); + assertOrPanic(1123 == switch (x) { MultipleChoice2.A => 1, MultipleChoice2.B => 2, MultipleChoice2.C => |v| i32(1000) + v, @@ -167,7 +167,7 @@ const ExternPtrOrInt = extern union { int: u64, }; test "extern union size" { - comptime assert(@sizeOf(ExternPtrOrInt) == 8); + comptime assertOrPanic(@sizeOf(ExternPtrOrInt) == 8); } const PackedPtrOrInt = packed union { @@ -175,14 +175,14 @@ const PackedPtrOrInt = packed union { int: u64, }; test "extern union size" { - comptime assert(@sizeOf(PackedPtrOrInt) == 8); + comptime assertOrPanic(@sizeOf(PackedPtrOrInt) == 8); } const ZeroBits = union { OnlyField: void, }; test "union with only 1 field which is void should be zero bits" { - comptime assert(@sizeOf(ZeroBits) == 0); + comptime assertOrPanic(@sizeOf(ZeroBits) == 0); } const TheTag = enum { @@ -196,9 +196,9 @@ const TheUnion = union(TheTag) { C: i32, }; test "union field access gives the enum values" { - assert(TheUnion.A == TheTag.A); - assert(TheUnion.B == TheTag.B); - assert(TheUnion.C == TheTag.C); + assertOrPanic(TheUnion.A == TheTag.A); + assertOrPanic(TheUnion.B == TheTag.B); + assertOrPanic(TheUnion.C == TheTag.C); } test "cast union to tag type of union" { @@ -207,12 +207,12 @@ test "cast union to tag type of union" { } fn testCastUnionToTagType(x: TheUnion) void { - assert(TheTag(x) == TheTag.B); + assertOrPanic(TheTag(x) == TheTag.B); } test "cast tag type of union to union" { var x: Value2 = Letter2.B; - assert(Letter2(x) == Letter2.B); + assertOrPanic(Letter2(x) == Letter2.B); } const Letter2 = enum { A, @@ -227,11 +227,11 @@ const Value2 = union(Letter2) { test "implicit cast union to its tag type" { var x: Value2 = Letter2.B; - assert(x == Letter2.B); + assertOrPanic(x == Letter2.B); giveMeLetterB(x); } fn giveMeLetterB(x: Letter2) void { - assert(x == Value2.B); + assertOrPanic(x == Value2.B); } pub const PackThis = union(enum) { @@ -244,7 +244,7 @@ test "constant packed union" { } fn testConstPackedUnion(expected_tokens: []const PackThis) void { - assert(expected_tokens[0].StringLiteral == 1); + assertOrPanic(expected_tokens[0].StringLiteral == 1); } test "switch on union with only 1 field" { @@ -256,7 +256,7 @@ test "switch on union with only 1 field" { z = PartialInstWithPayload{ .Compiled = 1234 }; switch (z) { PartialInstWithPayload.Compiled => |x| { - assert(x == 1234); + assertOrPanic(x == 1234); return; }, } @@ -282,11 +282,11 @@ test "access a member of tagged union with conflicting enum tag name" { const B = void; }; - comptime assert(Bar.A == u8); + comptime assertOrPanic(Bar.A == u8); } test "tagged union initialization with runtime void" { - assert(testTaggedUnionInit({})); + assertOrPanic(testTaggedUnionInit({})); } const TaggedUnionWithAVoid = union(enum) { @@ -324,9 +324,9 @@ test "union with only 1 field casted to its enum type" { var e = Expr{ .Literal = Literal{ .Bool = true } }; const Tag = @TagType(Expr); - comptime assert(@TagType(Tag) == comptime_int); + comptime assertOrPanic(@TagType(Tag) == comptime_int); var t = Tag(e); - assert(t == Expr.Literal); + assertOrPanic(t == Expr.Literal); } test "union with only 1 field casted to its enum type which has enum value specified" { @@ -344,9 +344,9 @@ test "union with only 1 field casted to its enum type which has enum value speci }; var e = Expr{ .Literal = Literal{ .Bool = true } }; - comptime assert(@TagType(Tag) == comptime_int); + comptime assertOrPanic(@TagType(Tag) == comptime_int); var t = Tag(e); - assert(t == Expr.Literal); - assert(@enumToInt(t) == 33); - comptime assert(@enumToInt(t) == 33); + assertOrPanic(t == Expr.Literal); + assertOrPanic(@enumToInt(t) == 33); + comptime assertOrPanic(@enumToInt(t) == 33); } diff --git a/test/cases/var_args.zig b/test/stage1/behavior/var_args.zig similarity index 56% rename from test/cases/var_args.zig rename to test/stage1/behavior/var_args.zig index 3eb6e30448..1f782a3bb3 100644 --- a/test/cases/var_args.zig +++ b/test/stage1/behavior/var_args.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; fn add(args: ...) i32 { var sum = i32(0); @@ -12,9 +12,9 @@ fn add(args: ...) i32 { } test "add arbitrary args" { - assert(add(i32(1), i32(2), i32(3), i32(4)) == 10); - assert(add(i32(1234)) == 1234); - assert(add() == 0); + assertOrPanic(add(i32(1), i32(2), i32(3), i32(4)) == 10); + assertOrPanic(add(i32(1234)) == 1234); + assertOrPanic(add() == 0); } fn readFirstVarArg(args: ...) void { @@ -26,9 +26,9 @@ test "send void arg to var args" { } test "pass args directly" { - assert(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10); - assert(addSomeStuff(i32(1234)) == 1234); - assert(addSomeStuff() == 0); + assertOrPanic(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10); + assertOrPanic(addSomeStuff(i32(1234)) == 1234); + assertOrPanic(addSomeStuff() == 0); } fn addSomeStuff(args: ...) i32 { @@ -36,24 +36,24 @@ fn addSomeStuff(args: ...) i32 { } test "runtime parameter before var args" { - assert(extraFn(10) == 0); - assert(extraFn(10, false) == 1); - assert(extraFn(10, false, true) == 2); + assertOrPanic(extraFn(10) == 0); + assertOrPanic(extraFn(10, false) == 1); + assertOrPanic(extraFn(10, false, true) == 2); // TODO issue #313 //comptime { - // assert(extraFn(10) == 0); - // assert(extraFn(10, false) == 1); - // assert(extraFn(10, false, true) == 2); + // assertOrPanic(extraFn(10) == 0); + // assertOrPanic(extraFn(10, false) == 1); + // assertOrPanic(extraFn(10, false, true) == 2); //} } fn extraFn(extra: u32, args: ...) usize { if (args.len >= 1) { - assert(args[0] == false); + assertOrPanic(args[0] == false); } if (args.len >= 2) { - assert(args[1] == true); + assertOrPanic(args[1] == true); } return args.len; } @@ -71,8 +71,8 @@ fn foo2(args: ...) bool { } test "array of var args functions" { - assert(foos[0]()); - assert(!foos[1]()); + assertOrPanic(foos[0]()); + assertOrPanic(!foos[1]()); } test "pass zero length array to var args param" { diff --git a/test/cases/void.zig b/test/stage1/behavior/void.zig similarity index 67% rename from test/cases/void.zig rename to test/stage1/behavior/void.zig index 7121ac664b..431d3f4eb1 100644 --- a/test/cases/void.zig +++ b/test/stage1/behavior/void.zig @@ -1,4 +1,4 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; const Foo = struct { a: void, @@ -13,14 +13,14 @@ test "compare void with void compile time known" { .b = 1, .c = {}, }; - assert(foo.a == {}); + assertOrPanic(foo.a == {}); } } test "iterate over a void slice" { var j: usize = 0; for (times(10)) |_, i| { - assert(i == j); + assertOrPanic(i == j); j += 1; } } @@ -28,3 +28,8 @@ test "iterate over a void slice" { fn times(n: usize) []const void { return ([*]void)(undefined)[0..n]; } + +test "void optional" { + var x: ?void = {}; + assertOrPanic(x != null); +} diff --git a/test/cases/while.zig b/test/stage1/behavior/while.zig similarity index 83% rename from test/cases/while.zig rename to test/stage1/behavior/while.zig index f774e0ec6b..579b4e4db8 100644 --- a/test/cases/while.zig +++ b/test/stage1/behavior/while.zig @@ -1,12 +1,12 @@ -const assert = @import("std").debug.assert; +const assertOrPanic = @import("std").debug.assertOrPanic; test "while loop" { var i: i32 = 0; while (i < 4) { i += 1; } - assert(i == 4); - assert(whileLoop1() == 1); + assertOrPanic(i == 4); + assertOrPanic(whileLoop1() == 1); } fn whileLoop1() i32 { return whileLoop2(); @@ -16,8 +16,9 @@ fn whileLoop2() i32 { return 1; } } + test "static eval while" { - assert(static_eval_while_number == 1); + assertOrPanic(static_eval_while_number == 1); } const static_eval_while_number = staticWhileLoop1(); fn staticWhileLoop1() i32 { @@ -31,7 +32,7 @@ fn staticWhileLoop2() i32 { test "continue and break" { runContinueAndBreakTest(); - assert(continue_and_break_counter == 8); + assertOrPanic(continue_and_break_counter == 8); } var continue_and_break_counter: i32 = 0; fn runContinueAndBreakTest() void { @@ -44,7 +45,7 @@ fn runContinueAndBreakTest() void { } break; } - assert(i == 4); + assertOrPanic(i == 4); } test "return with implicit cast from while loop" { @@ -65,7 +66,7 @@ test "while with continue expression" { sum += i; } } - assert(sum == 40); + assertOrPanic(sum == 40); } test "while with else" { @@ -77,8 +78,8 @@ test "while with else" { } else { got_else += 1; } - assert(sum == 10); - assert(got_else == 1); + assertOrPanic(sum == 10); + assertOrPanic(got_else == 1); } test "while with optional as condition" { @@ -87,7 +88,7 @@ test "while with optional as condition" { while (getNumberOrNull()) |value| { sum += value; } - assert(sum == 45); + assertOrPanic(sum == 45); } test "while with optional as condition with else" { @@ -96,12 +97,12 @@ test "while with optional as condition with else" { var got_else: i32 = 0; while (getNumberOrNull()) |value| { sum += value; - assert(got_else == 0); + assertOrPanic(got_else == 0); } else { got_else += 1; } - assert(sum == 45); - assert(got_else == 1); + assertOrPanic(sum == 45); + assertOrPanic(got_else == 1); } test "while with error union condition" { @@ -111,11 +112,11 @@ test "while with error union condition" { while (getNumberOrErr()) |value| { sum += value; } else |err| { - assert(err == error.OutOfNumbers); + assertOrPanic(err == error.OutOfNumbers); got_else += 1; } - assert(sum == 45); - assert(got_else == 1); + assertOrPanic(sum == 45); + assertOrPanic(got_else == 1); } var numbers_left: i32 = undefined; @@ -137,7 +138,7 @@ test "while on optional with else result follow else prong" { break value; } else i32(2); - assert(result == 2); + assertOrPanic(result == 2); } test "while on optional with else result follow break prong" { @@ -145,7 +146,7 @@ test "while on optional with else result follow break prong" { break value; } else i32(2); - assert(result == 10); + assertOrPanic(result == 10); } test "while on error union with else result follow else prong" { @@ -153,7 +154,7 @@ test "while on error union with else result follow else prong" { break value; } else |err| i32(2); - assert(result == 2); + assertOrPanic(result == 2); } test "while on error union with else result follow break prong" { @@ -161,7 +162,7 @@ test "while on error union with else result follow break prong" { break value; } else |err| i32(2); - assert(result == 10); + assertOrPanic(result == 10); } test "while on bool with else result follow else prong" { @@ -169,7 +170,7 @@ test "while on bool with else result follow else prong" { break i32(10); } else i32(2); - assert(result == 2); + assertOrPanic(result == 2); } test "while on bool with else result follow break prong" { @@ -177,7 +178,7 @@ test "while on bool with else result follow break prong" { break i32(10); } else i32(2); - assert(result == 10); + assertOrPanic(result == 10); } test "break from outer while loop" { diff --git a/test/cases/widening.zig b/test/stage1/behavior/widening.zig similarity index 75% rename from test/cases/widening.zig rename to test/stage1/behavior/widening.zig index cf6ab4ca0f..7577868aff 100644 --- a/test/cases/widening.zig +++ b/test/stage1/behavior/widening.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const assert = std.debug.assert; +const assertOrPanic = std.debug.assertOrPanic; const mem = std.mem; test "integer widening" { @@ -9,13 +9,13 @@ test "integer widening" { var d: u64 = c; var e: u64 = d; var f: u128 = e; - assert(f == a); + assertOrPanic(f == a); } test "implicit unsigned integer to signed integer" { var a: u8 = 250; var b: i16 = a; - assert(b == 250); + assertOrPanic(b == 250); } test "float widening" { @@ -23,5 +23,6 @@ test "float widening" { var b: f32 = a; var c: f64 = b; var d: f128 = c; - assert(d == a); + assertOrPanic(d == a); } +