better result location semantics with optionals and return locations
somewhere along this branch, #1901 has been fixed.
This commit is contained in:
parent
60025a3704
commit
6bf193af19
|
@ -4,10 +4,7 @@ Scratch pad for stuff to do before merging master
|
|||
uncomment all the behavior tests
|
||||
diff master branch to make sure
|
||||
|
||||
restore test_runner.zig to master branch
|
||||
- also the default panic function and unexpected_error_tracing. see the commit
|
||||
that adds this text to BRANCH_TODO file.
|
||||
- and std/specia/bootstrap.zig
|
||||
restore bootstrap.zig to master
|
||||
|
||||
get an empty file compiling successfully (with no panic fn override)
|
||||
|
||||
|
|
|
@ -2257,7 +2257,8 @@ enum IrInstructionId {
|
|||
IrInstructionIdHandle,
|
||||
IrInstructionIdAlignOf,
|
||||
IrInstructionIdOverflowOp,
|
||||
IrInstructionIdTestErr,
|
||||
IrInstructionIdTestErrSrc,
|
||||
IrInstructionIdTestErrGen,
|
||||
IrInstructionIdUnwrapErrCode,
|
||||
IrInstructionIdUnwrapErrPayload,
|
||||
IrInstructionIdErrWrapCode,
|
||||
|
@ -2292,6 +2293,7 @@ enum IrInstructionId {
|
|||
IrInstructionIdAlignCast,
|
||||
IrInstructionIdImplicitCast,
|
||||
IrInstructionIdResolveResult,
|
||||
IrInstructionIdResultPtr,
|
||||
IrInstructionIdOpaqueType,
|
||||
IrInstructionIdSetAlignStack,
|
||||
IrInstructionIdArgType,
|
||||
|
@ -3082,10 +3084,16 @@ struct IrInstructionAlignOf {
|
|||
};
|
||||
|
||||
// returns true if error, returns false if not error
|
||||
struct IrInstructionTestErr {
|
||||
struct IrInstructionTestErrSrc {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
IrInstruction *base_ptr;
|
||||
};
|
||||
|
||||
struct IrInstructionTestErrGen {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *err_union;
|
||||
};
|
||||
|
||||
// Takes an error union pointer, returns a pointer to the error code.
|
||||
|
@ -3596,6 +3604,7 @@ struct IrInstructionImplicitCast {
|
|||
ResultLoc *result_loc;
|
||||
};
|
||||
|
||||
// This one is for writing through the result pointer.
|
||||
struct IrInstructionResolveResult {
|
||||
IrInstruction base;
|
||||
|
||||
|
@ -3603,6 +3612,15 @@ struct IrInstructionResolveResult {
|
|||
IrInstruction *ty;
|
||||
};
|
||||
|
||||
// This one is when you want to read the value of the result.
|
||||
// You have to give the value in case it is comptime.
|
||||
struct IrInstructionResultPtr {
|
||||
IrInstruction base;
|
||||
|
||||
ResultLoc *result_loc;
|
||||
IrInstruction *result;
|
||||
};
|
||||
|
||||
struct IrInstructionPtrOfArrayToSlice {
|
||||
IrInstruction base;
|
||||
|
||||
|
|
|
@ -1323,7 +1323,9 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
|
|||
LLVMBuildRetVoid(g->builder);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, prev_block);
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
if (!g->strip_debug_symbols) {
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
}
|
||||
|
||||
g->add_error_return_trace_addr_fn_val = fn_val;
|
||||
return fn_val;
|
||||
|
@ -1454,7 +1456,9 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
|
|||
LLVMBuildBr(g->builder, loop_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, prev_block);
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
if (!g->strip_debug_symbols) {
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
}
|
||||
|
||||
g->merge_err_ret_traces_fn_val = fn_val;
|
||||
return fn_val;
|
||||
|
@ -1510,7 +1514,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
|
|||
LLVMBuildRetVoid(g->builder);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, prev_block);
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
if (!g->strip_debug_symbols) {
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
}
|
||||
|
||||
g->return_err_fn = fn_val;
|
||||
return fn_val;
|
||||
|
@ -1638,7 +1644,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
|
|||
gen_panic(g, msg_slice, err_ret_trace_arg);
|
||||
|
||||
LLVMPositionBuilderAtEnd(g->builder, prev_block);
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
if (!g->strip_debug_symbols) {
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
}
|
||||
|
||||
g->safety_crash_err_fn = fn_val;
|
||||
return fn_val;
|
||||
|
@ -4353,7 +4361,9 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
|
|||
g->cur_fn = prev_cur_fn;
|
||||
g->cur_fn_val = prev_cur_fn_val;
|
||||
LLVMPositionBuilderAtEnd(g->builder, prev_block);
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
if (!g->strip_debug_symbols) {
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
}
|
||||
|
||||
enum_type->data.enumeration.name_function = fn_val;
|
||||
return fn_val;
|
||||
|
@ -4880,10 +4890,10 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
|
|||
return overflow_bit;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) {
|
||||
ZigType *err_union_type = instruction->value->value.type;
|
||||
static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErrGen *instruction) {
|
||||
ZigType *err_union_type = instruction->err_union->value.type;
|
||||
ZigType *payload_type = err_union_type->data.error_union.payload_type;
|
||||
LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union);
|
||||
|
||||
LLVMValueRef err_val;
|
||||
if (type_has_bits(payload_type)) {
|
||||
|
@ -5276,7 +5286,9 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f
|
|||
g->cur_fn = prev_cur_fn;
|
||||
g->cur_fn_val = prev_cur_fn_val;
|
||||
LLVMPositionBuilderAtEnd(g->builder, prev_block);
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
if (!g->strip_debug_symbols) {
|
||||
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
|
||||
}
|
||||
|
||||
g->coro_alloc_helper_fn_val = fn_val;
|
||||
return fn_val;
|
||||
|
@ -5549,10 +5561,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
case IrInstructionIdAllocaGen:
|
||||
case IrInstructionIdImplicitCast:
|
||||
case IrInstructionIdResolveResult:
|
||||
case IrInstructionIdResultPtr:
|
||||
case IrInstructionIdContainerInitList:
|
||||
case IrInstructionIdSliceSrc:
|
||||
case IrInstructionIdRef:
|
||||
case IrInstructionIdBitCastSrc:
|
||||
case IrInstructionIdTestErrSrc:
|
||||
zig_unreachable();
|
||||
|
||||
case IrInstructionIdDeclVarGen:
|
||||
|
@ -5635,8 +5649,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
return ir_render_handle(g, executable, (IrInstructionHandle *)instruction);
|
||||
case IrInstructionIdOverflowOp:
|
||||
return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
|
||||
case IrInstructionIdTestErr:
|
||||
return ir_render_test_err(g, executable, (IrInstructionTestErr *)instruction);
|
||||
case IrInstructionIdTestErrGen:
|
||||
return ir_render_test_err(g, executable, (IrInstructionTestErrGen *)instruction);
|
||||
case IrInstructionIdUnwrapErrCode:
|
||||
return ir_render_unwrap_err_code(g, executable, (IrInstructionUnwrapErrCode *)instruction);
|
||||
case IrInstructionIdUnwrapErrPayload:
|
||||
|
|
114
src/ir.cpp
114
src/ir.cpp
|
@ -756,8 +756,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {
|
|||
return IrInstructionIdOverflowOp;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErr *) {
|
||||
return IrInstructionIdTestErr;
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrSrc *) {
|
||||
return IrInstructionIdTestErrSrc;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrGen *) {
|
||||
return IrInstructionIdTestErrGen;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrCode *) {
|
||||
|
@ -900,6 +904,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *)
|
|||
return IrInstructionIdResolveResult;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionResultPtr *) {
|
||||
return IrInstructionIdResultPtr;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrOfArrayToSlice *) {
|
||||
return IrInstructionIdPtrOfArrayToSlice;
|
||||
}
|
||||
|
@ -2418,13 +2426,26 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *value)
|
||||
static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *base_ptr)
|
||||
{
|
||||
IrInstructionTestErr *instruction = ir_build_instruction<IrInstructionTestErr>(irb, scope, source_node);
|
||||
instruction->value = value;
|
||||
IrInstructionTestErrSrc *instruction = ir_build_instruction<IrInstructionTestErrSrc>(irb, scope, source_node);
|
||||
instruction->base_ptr = base_ptr;
|
||||
|
||||
ir_ref_instruction(value, irb->current_basic_block);
|
||||
ir_ref_instruction(base_ptr, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_test_err_gen(IrAnalyze *ira, IrInstruction *source_instruction,
|
||||
IrInstruction *err_union)
|
||||
{
|
||||
IrInstructionTestErrGen *instruction = ir_build_instruction<IrInstructionTestErrGen>(
|
||||
&ira->new_irb, source_instruction->scope, source_instruction->source_node);
|
||||
instruction->base.value.type = ira->codegen->builtin_types.entry_bool;
|
||||
instruction->err_union = err_union;
|
||||
|
||||
ir_ref_instruction(err_union, ira->new_irb.current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
@ -2844,6 +2865,18 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_result_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
ResultLoc *result_loc, IrInstruction *result)
|
||||
{
|
||||
IrInstructionResultPtr *instruction = ir_build_instruction<IrInstructionResultPtr>(irb, scope, source_node);
|
||||
instruction->result_loc = result_loc;
|
||||
instruction->result = result;
|
||||
|
||||
ir_ref_instruction(result, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||
IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);
|
||||
|
||||
|
@ -3531,7 +3564,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
|
|||
ir_gen_defers_for_block(irb, scope, outer_scope, false);
|
||||
}
|
||||
|
||||
IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);
|
||||
IrInstruction *ret_ptr = ir_build_result_ptr(irb, scope, node, &result_loc_ret->base,
|
||||
return_value);
|
||||
IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, ret_ptr);
|
||||
|
||||
bool should_inline = ir_should_inline(irb->exec, scope);
|
||||
IrInstruction *is_comptime;
|
||||
|
@ -3577,8 +3612,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
|
|||
IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
|
||||
if (err_union_ptr == irb->codegen->invalid_instruction)
|
||||
return irb->codegen->invalid_instruction;
|
||||
IrInstruction *err_union_val = ir_build_load_ptr(irb, scope, node, err_union_ptr);
|
||||
IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_val);
|
||||
IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr);
|
||||
|
||||
IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");
|
||||
IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");
|
||||
|
@ -5940,8 +5974,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
|
|||
LValPtr, nullptr);
|
||||
if (err_val_ptr == irb->codegen->invalid_instruction)
|
||||
return err_val_ptr;
|
||||
IrInstruction *err_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, err_val_ptr);
|
||||
IrInstruction *is_err = ir_build_test_err(irb, scope, node->data.while_expr.condition, err_val);
|
||||
IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr);
|
||||
IrBasicBlock *after_cond_block = irb->current_basic_block;
|
||||
IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
|
||||
IrInstruction *cond_br_inst;
|
||||
|
@ -6722,7 +6755,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
|
|||
return err_val_ptr;
|
||||
|
||||
IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
|
||||
IrInstruction *is_err = ir_build_test_err(irb, scope, node, err_val);
|
||||
IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr);
|
||||
|
||||
IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");
|
||||
IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");
|
||||
|
@ -7330,8 +7363,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
|
|||
if (err_union_ptr == irb->codegen->invalid_instruction)
|
||||
return irb->codegen->invalid_instruction;
|
||||
|
||||
IrInstruction *err_union_val = ir_build_load_ptr(irb, parent_scope, node, err_union_ptr);
|
||||
IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_val);
|
||||
IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr);
|
||||
|
||||
IrInstruction *is_comptime;
|
||||
if (ir_should_inline(irb->exec, parent_scope)) {
|
||||
|
@ -15010,7 +15042,9 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
|
|||
return result_loc;
|
||||
ir_assert(result_loc->value.type->id == ZigTypeIdPointer, suspend_source_instr);
|
||||
ZigType *actual_elem_type = result_loc->value.type->data.pointer.child_type;
|
||||
if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional) {
|
||||
if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
|
||||
value_type->id != ZigTypeIdNull)
|
||||
{
|
||||
return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
|
||||
} else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {
|
||||
if (value_type->id == ZigTypeIdErrorSet) {
|
||||
|
@ -22190,15 +22224,34 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
|
|||
return result;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErr *instruction) {
|
||||
IrInstruction *value = instruction->value->child;
|
||||
if (type_is_invalid(value->value.type))
|
||||
static IrInstruction *ir_analyze_instruction_result_ptr(IrAnalyze *ira, IrInstructionResultPtr *instruction) {
|
||||
IrInstruction *result = instruction->result->child;
|
||||
if (type_is_invalid(result->value.type))
|
||||
return result;
|
||||
|
||||
if (instruction->result_loc->written && instruction->result_loc->resolved_loc != nullptr &&
|
||||
!instr_is_comptime(result))
|
||||
{
|
||||
IrInstruction *result_ptr = instruction->result_loc->resolved_loc;
|
||||
// Convert the pointer to the result type. They should be the same, except this will resolve
|
||||
// inferred error sets.
|
||||
ZigType *new_ptr_type = get_pointer_to_type(ira->codegen, result->value.type, true);
|
||||
return ir_analyze_ptr_cast(ira, &instruction->base, result_ptr, new_ptr_type, &instruction->base, false);
|
||||
}
|
||||
return ir_get_ref(ira, &instruction->base, result, true, false);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErrSrc *instruction) {
|
||||
IrInstruction *base_ptr = instruction->base_ptr->child;
|
||||
if (type_is_invalid(base_ptr->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
IrInstruction *value = ir_get_deref(ira, &instruction->base, base_ptr, nullptr);
|
||||
ZigType *type_entry = value->value.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 (type_entry->id == ZigTypeIdErrorUnion) {
|
||||
if (instr_is_comptime(value)) {
|
||||
ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
|
||||
if (!err_union_val)
|
||||
|
@ -22221,10 +22274,7 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
|
|||
return ir_const_bool(ira, &instruction->base, false);
|
||||
}
|
||||
|
||||
IrInstruction *result = ir_build_test_err(&ira->new_irb,
|
||||
instruction->base.scope, instruction->base.source_node, value);
|
||||
result->value.type = ira->codegen->builtin_types.entry_bool;
|
||||
return result;
|
||||
return ir_build_test_err_gen(ira, &instruction->base, value);
|
||||
} else if (type_entry->id == ZigTypeIdErrorSet) {
|
||||
return ir_const_bool(ira, &instruction->base, true);
|
||||
} else {
|
||||
|
@ -24343,6 +24393,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
|
|||
case IrInstructionIdAllocaGen:
|
||||
case IrInstructionIdSliceGen:
|
||||
case IrInstructionIdRefGen:
|
||||
case IrInstructionIdTestErrGen:
|
||||
zig_unreachable();
|
||||
|
||||
case IrInstructionIdReturn:
|
||||
|
@ -24497,8 +24548,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
|
|||
return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
|
||||
case IrInstructionIdOverflowOp:
|
||||
return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction);
|
||||
case IrInstructionIdTestErr:
|
||||
return ir_analyze_instruction_test_err(ira, (IrInstructionTestErr *)instruction);
|
||||
case IrInstructionIdTestErrSrc:
|
||||
return ir_analyze_instruction_test_err(ira, (IrInstructionTestErrSrc *)instruction);
|
||||
case IrInstructionIdUnwrapErrCode:
|
||||
return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction);
|
||||
case IrInstructionIdUnwrapErrPayload:
|
||||
|
@ -24543,6 +24594,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
|
|||
return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction);
|
||||
case IrInstructionIdResolveResult:
|
||||
return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);
|
||||
case IrInstructionIdResultPtr:
|
||||
return ir_analyze_instruction_result_ptr(ira, (IrInstructionResultPtr *)instruction);
|
||||
case IrInstructionIdOpaqueType:
|
||||
return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
|
||||
case IrInstructionIdSetAlignStack:
|
||||
|
@ -24672,6 +24725,9 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ira->codegen->verbose_ir) {
|
||||
fprintf(stderr, "analyze #%zu\n", old_instruction->debug_id);
|
||||
}
|
||||
IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);
|
||||
if (new_instruction != nullptr) {
|
||||
ir_assert(new_instruction->value.type != nullptr || new_instruction->value.type != nullptr, old_instruction);
|
||||
|
@ -24808,7 +24864,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
case IrInstructionIdReturnAddress:
|
||||
case IrInstructionIdFrameAddress:
|
||||
case IrInstructionIdHandle:
|
||||
case IrInstructionIdTestErr:
|
||||
case IrInstructionIdTestErrSrc:
|
||||
case IrInstructionIdTestErrGen:
|
||||
case IrInstructionIdFnProto:
|
||||
case IrInstructionIdTestComptime:
|
||||
case IrInstructionIdPtrCastSrc:
|
||||
|
@ -24860,6 +24917,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
case IrInstructionIdHasDecl:
|
||||
case IrInstructionIdAllocaSrc:
|
||||
case IrInstructionIdAllocaGen:
|
||||
case IrInstructionIdResultPtr:
|
||||
return false;
|
||||
|
||||
case IrInstructionIdAsm:
|
||||
|
|
|
@ -961,9 +961,15 @@ static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruct
|
|||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
|
||||
static void ir_print_test_err_src(IrPrint *irp, IrInstructionTestErrSrc *instruction) {
|
||||
fprintf(irp->f, "@testError(");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
ir_print_other_instruction(irp, instruction->base_ptr);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_test_err_gen(IrPrint *irp, IrInstructionTestErrGen *instruction) {
|
||||
fprintf(irp->f, "@testError(");
|
||||
ir_print_other_instruction(irp, instruction->err_union);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
|
@ -976,10 +982,7 @@ static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *i
|
|||
static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
|
||||
fprintf(irp->f, "ErrorUnionFieldPayload(");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
fprintf(irp->f, ")");
|
||||
if (!instruction->safety_check_on) {
|
||||
fprintf(irp->f, " // no safety");
|
||||
}
|
||||
fprintf(irp->f, ")safety=%d,init=%d",instruction->safety_check_on, instruction->initializing);
|
||||
}
|
||||
|
||||
static void ir_print_optional_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) {
|
||||
|
@ -1301,6 +1304,14 @@ static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *in
|
|||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_result_ptr(IrPrint *irp, IrInstructionResultPtr *instruction) {
|
||||
fprintf(irp->f, "ResultPtr(");
|
||||
ir_print_result_loc(irp, instruction->result_loc);
|
||||
fprintf(irp->f, ",");
|
||||
ir_print_other_instruction(irp, instruction->result);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
|
||||
fprintf(irp->f, "@OpaqueType()");
|
||||
}
|
||||
|
@ -1837,8 +1848,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdOverflowOp:
|
||||
ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction);
|
||||
break;
|
||||
case IrInstructionIdTestErr:
|
||||
ir_print_test_err(irp, (IrInstructionTestErr *)instruction);
|
||||
case IrInstructionIdTestErrSrc:
|
||||
ir_print_test_err_src(irp, (IrInstructionTestErrSrc *)instruction);
|
||||
break;
|
||||
case IrInstructionIdTestErrGen:
|
||||
ir_print_test_err_gen(irp, (IrInstructionTestErrGen *)instruction);
|
||||
break;
|
||||
case IrInstructionIdUnwrapErrCode:
|
||||
ir_print_unwrap_err_code(irp, (IrInstructionUnwrapErrCode *)instruction);
|
||||
|
@ -1939,6 +1953,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdResolveResult:
|
||||
ir_print_resolve_result(irp, (IrInstructionResolveResult *)instruction);
|
||||
break;
|
||||
case IrInstructionIdResultPtr:
|
||||
ir_print_result_ptr(irp, (IrInstructionResultPtr *)instruction);
|
||||
break;
|
||||
case IrInstructionIdOpaqueType:
|
||||
ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
|
||||
break;
|
||||
|
|
|
@ -2487,7 +2487,7 @@ pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {
|
|||
/// if this happens the fix is to add the error code to the corresponding
|
||||
/// switch expression, possibly introduce a new error in the error set, and
|
||||
/// send a patch to Zig.
|
||||
pub const unexpected_error_tracing = false;
|
||||
pub const unexpected_error_tracing = builtin.mode == .Debug;
|
||||
|
||||
pub const UnexpectedError = error{
|
||||
/// The Operating System returned an undocumented error code.
|
||||
|
|
|
@ -7,8 +7,23 @@ const builtin = @import("builtin");
|
|||
const std = @import("std");
|
||||
|
||||
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
|
||||
const stderr = std.io.getStdErr() catch std.process.abort();
|
||||
stderr.write("panic: ") catch std.process.abort();
|
||||
stderr.write(msg) catch std.process.abort();
|
||||
std.process.abort();
|
||||
@setCold(true);
|
||||
switch (builtin.os) {
|
||||
.freestanding => {
|
||||
while (true) {}
|
||||
},
|
||||
.wasi => {
|
||||
std.debug.warn("{}", msg);
|
||||
_ = std.os.wasi.proc_raise(std.os.wasi.SIGABRT);
|
||||
unreachable;
|
||||
},
|
||||
.uefi => {
|
||||
// TODO look into using the debug info and logging helpful messages
|
||||
std.os.abort();
|
||||
},
|
||||
else => {
|
||||
const first_trace_addr = @returnAddress();
|
||||
std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,34 +2,28 @@ const std = @import("std");
|
|||
const io = std.io;
|
||||
const builtin = @import("builtin");
|
||||
const test_fn_list = builtin.test_functions;
|
||||
const warn = std.debug.warn;
|
||||
|
||||
pub fn main() void {
|
||||
const stderr = io.getStdErr() catch std.process.abort();
|
||||
|
||||
pub fn main() !void {
|
||||
var ok_count: usize = 0;
|
||||
var skip_count: usize = 0;
|
||||
for (test_fn_list) |test_fn, i| {
|
||||
stderr.write("test ") catch std.process.abort();
|
||||
stderr.write(test_fn.name) catch std.process.abort();
|
||||
warn("{}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
|
||||
|
||||
if (test_fn.func()) |_| {
|
||||
ok_count += 1;
|
||||
stderr.write("...OK\n") catch std.process.abort();
|
||||
warn("OK\n");
|
||||
} else |err| switch (err) {
|
||||
error.SkipZigTest => {
|
||||
skip_count += 1;
|
||||
stderr.write("...SKIP\n") catch std.process.abort();
|
||||
},
|
||||
else => {
|
||||
stderr.write("error: ") catch std.process.abort();
|
||||
stderr.write(@errorName(err)) catch std.process.abort();
|
||||
std.process.abort();
|
||||
warn("SKIP\n");
|
||||
},
|
||||
else => return err,
|
||||
}
|
||||
}
|
||||
if (ok_count == test_fn_list.len) {
|
||||
stderr.write("All tests passed.\n") catch std.process.abort();
|
||||
warn("All tests passed.\n");
|
||||
} else {
|
||||
stderr.write("Some tests skipped.\n") catch std.process.abort();
|
||||
warn("{} passed; {} skipped.\n", ok_count, skip_count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,46 +40,46 @@ comptime {
|
|||
//_ = @import("behavior/bugs/920.zig");
|
||||
_ = @import("behavior/byval_arg_var.zig");
|
||||
//_ = @import("behavior/cancel.zig");
|
||||
_ = @import("behavior/cast.zig"); // TODO
|
||||
_ = @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/error.zig"); // TODO
|
||||
_ = @import("behavior/eval.zig"); // TODO
|
||||
_ = @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"); // TODO
|
||||
_ = @import("behavior/generics.zig");
|
||||
_ = @import("behavior/hasdecl.zig");
|
||||
_ = @import("behavior/if.zig");
|
||||
//_ = @import("behavior/import.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/math.zig");
|
||||
_ = @import("behavior/merge_error_sets.zig");
|
||||
_ = @import("behavior/misc.zig"); // TODO
|
||||
_ = @import("behavior/namespace_depends_on_compile_var.zig");
|
||||
_ = @import("behavior/new_stack_call.zig");
|
||||
_ = @import("behavior/null.zig");
|
||||
_ = @import("behavior/optional.zig"); // TODO
|
||||
//_ = @import("behavior/pointers.zig");
|
||||
_ = @import("behavior/pointers.zig");
|
||||
_ = @import("behavior/popcount.zig");
|
||||
_ = @import("behavior/ptrcast.zig"); // TODO
|
||||
_ = @import("behavior/pub_enum.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/slice.zig");
|
||||
_ = @import("behavior/slicetobytes.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.zig");
|
||||
//_ = @import("behavior/switch_prong_err_enum.zig");
|
||||
_ = @import("behavior/switch_prong_implicit_cast.zig");
|
||||
_ = @import("behavior/syntax.zig");
|
||||
|
@ -87,7 +87,7 @@ comptime {
|
|||
_ = @import("behavior/truncate.zig");
|
||||
_ = @import("behavior/try.zig");
|
||||
_ = @import("behavior/type_info.zig");
|
||||
//_ = @import("behavior/typename.zig");
|
||||
_ = @import("behavior/typename.zig");
|
||||
_ = @import("behavior/undefined.zig");
|
||||
_ = @import("behavior/underscore.zig");
|
||||
_ = @import("behavior/union.zig");
|
||||
|
|
|
@ -124,14 +124,14 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
|
|||
return null;
|
||||
}
|
||||
|
||||
//test "peer type resolution: ?T and T" {
|
||||
// expect(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
// expect(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
// comptime {
|
||||
// expect(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
// expect(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
// }
|
||||
//}
|
||||
test "peer type resolution: ?T and T" {
|
||||
expect(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
expect(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
comptime {
|
||||
expect(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
expect(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
}
|
||||
}
|
||||
fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
|
||||
if (c) {
|
||||
return if (b) null else usize(0);
|
||||
|
|
|
@ -249,48 +249,48 @@ 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;
|
||||
}
|
||||
};
|
||||
expect((try S.errorable()) == 1234);
|
||||
expectError(error.Failure, S.errorable2());
|
||||
expectError(error.Other, S.errorable3());
|
||||
comptime {
|
||||
expect((try S.errorable()) == 1234);
|
||||
expectError(error.Failure, S.errorable2());
|
||||
expectError(error.Other, S.errorable3());
|
||||
}
|
||||
}
|
||||
//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;
|
||||
// }
|
||||
// };
|
||||
// expect((try S.errorable()) == 1234);
|
||||
// expectError(error.Failure, S.errorable2());
|
||||
// expectError(error.Other, S.errorable3());
|
||||
// comptime {
|
||||
// expect((try S.errorable()) == 1234);
|
||||
// expectError(error.Failure, S.errorable2());
|
||||
// expectError(error.Other, S.errorable3());
|
||||
// }
|
||||
//}
|
||||
|
||||
test "widen cast integer payload of error union function call" {
|
||||
const S = struct {
|
||||
|
|
|
@ -80,19 +80,19 @@ test "function with return type type" {
|
|||
expect(list2.prealloc_items.len == 8);
|
||||
}
|
||||
|
||||
//test "generic struct" {
|
||||
// var a1 = GenNode(i32){
|
||||
// .value = 13,
|
||||
// .next = null,
|
||||
// };
|
||||
// var b1 = GenNode(bool){
|
||||
// .value = true,
|
||||
// .next = null,
|
||||
// };
|
||||
// expect(a1.value == 13);
|
||||
// expect(a1.value == a1.getVal());
|
||||
// expect(b1.getVal());
|
||||
//}
|
||||
test "generic struct" {
|
||||
var a1 = GenNode(i32){
|
||||
.value = 13,
|
||||
.next = null,
|
||||
};
|
||||
var b1 = GenNode(bool){
|
||||
.value = true,
|
||||
.next = null,
|
||||
};
|
||||
expect(a1.value == 13);
|
||||
expect(a1.value == a1.getVal());
|
||||
expect(b1.getVal());
|
||||
}
|
||||
fn GenNode(comptime T: type) type {
|
||||
return struct {
|
||||
value: T,
|
||||
|
|
|
@ -76,6 +76,5 @@ test "unwrap function call with optional pointer return value" {
|
|||
}
|
||||
};
|
||||
S.entry();
|
||||
// TODO https://github.com/ziglang/zig/issues/1901
|
||||
//comptime S.entry();
|
||||
comptime S.entry();
|
||||
}
|
||||
|
|
|
@ -82,28 +82,28 @@ test "while with else" {
|
|||
expect(got_else == 1);
|
||||
}
|
||||
|
||||
//test "while with optional as condition" {
|
||||
// numbers_left = 10;
|
||||
// var sum: i32 = 0;
|
||||
// while (getNumberOrNull()) |value| {
|
||||
// sum += value;
|
||||
// }
|
||||
// expect(sum == 45);
|
||||
//}
|
||||
//
|
||||
//test "while with optional as condition with else" {
|
||||
// numbers_left = 10;
|
||||
// var sum: i32 = 0;
|
||||
// var got_else: i32 = 0;
|
||||
// while (getNumberOrNull()) |value| {
|
||||
// sum += value;
|
||||
// expect(got_else == 0);
|
||||
// } else {
|
||||
// got_else += 1;
|
||||
// }
|
||||
// expect(sum == 45);
|
||||
// expect(got_else == 1);
|
||||
//}
|
||||
test "while with optional as condition" {
|
||||
numbers_left = 10;
|
||||
var sum: i32 = 0;
|
||||
while (getNumberOrNull()) |value| {
|
||||
sum += value;
|
||||
}
|
||||
expect(sum == 45);
|
||||
}
|
||||
|
||||
test "while with optional as condition with else" {
|
||||
numbers_left = 10;
|
||||
var sum: i32 = 0;
|
||||
var got_else: i32 = 0;
|
||||
while (getNumberOrNull()) |value| {
|
||||
sum += value;
|
||||
expect(got_else == 0);
|
||||
} else {
|
||||
got_else += 1;
|
||||
}
|
||||
expect(sum == 45);
|
||||
expect(got_else == 1);
|
||||
}
|
||||
|
||||
test "while with error union condition" {
|
||||
numbers_left = 10;
|
||||
|
|
Loading…
Reference in New Issue
Block a user