IR: add more instructions

* MaybeWrap
 * TestErr
 * UnwrapErrCode
 * UnwrapErrPayload
 * ErrUnionTypeChild
 * ErrWrapCode
 * ErrWrapPayload
master
Andrew Kelley 2016-12-17 16:06:48 -05:00
parent 3a3cc7bf76
commit 12fcbecbf8
8 changed files with 863 additions and 520 deletions

View File

@ -115,14 +115,26 @@ enum ConstValSpecial {
ConstValSpecialZeroes,
};
enum RuntimeHintErrorUnion {
RuntimeHintErrorUnionUnknown,
RuntimeHintErrorUnionError,
RuntimeHintErrorUnionNonError,
};
enum RuntimeHintMaybe {
RuntimeHintMaybeUnknown,
RuntimeHintMaybeNull, // TODO is this value even possible? if this is the case it might mean the const value is compile time known.
RuntimeHintMaybeNonNull,
};
struct ConstExprValue {
ConstValSpecial special;
bool depends_on_compile_var;
LLVMValueRef llvm_value;
LLVMValueRef llvm_global;
// populated if val_type == ConstValTypeOk
union {
// populated if special == ConstValSpecialStatic
BigNum x_bignum;
bool x_bool;
FnTableEntry *x_fn;
@ -137,6 +149,10 @@ struct ConstExprValue {
ConstPtrValue x_ptr;
ImportTableEntry *x_import;
Scope *x_block;
// populated if special == ConstValSpecialRuntime
RuntimeHintErrorUnion rh_error_union;
RuntimeHintMaybe rh_maybe;
} data;
};
@ -412,10 +428,6 @@ enum CastOp {
CastOpIntToPtr,
CastOpWidenOrShorten,
CastOpToUnknownSizeArray,
CastOpMaybeWrap,
CastOpNullToMaybe,
CastOpErrorWrap,
CastOpPureErrorWrap,
CastOpPointerReinterpret,
CastOpErrToInt,
CastOpIntToFloat,
@ -1394,6 +1406,7 @@ enum IrInstructionId {
IrInstructionIdSizeOf,
IrInstructionIdTestNull,
IrInstructionIdUnwrapMaybe,
IrInstructionIdMaybeWrap,
IrInstructionIdEnumTag,
IrInstructionIdClz,
IrInstructionIdCtz,
@ -1426,6 +1439,12 @@ enum IrInstructionId {
IrInstructionIdFrameAddress,
IrInstructionIdAlignOf,
IrInstructionIdOverflowOp,
IrInstructionIdTestErr,
IrInstructionIdUnwrapErrCode,
IrInstructionIdUnwrapErrPayload,
IrInstructionIdErrUnionTypeChild,
IrInstructionIdErrWrapCode,
IrInstructionIdErrWrapPayload,
};
struct IrInstruction {
@ -1439,7 +1458,6 @@ struct IrInstruction {
// if ref_count is zero, instruction can be omitted in codegen
size_t ref_count;
IrInstruction *other;
ReturnKnowledge return_knowledge;
};
struct IrInstructionCondBr {
@ -1504,10 +1522,6 @@ enum IrUnOp {
IrUnOpDereference,
IrUnOpError,
IrUnOpMaybe,
IrUnOpUnwrapError,
IrUnOpUnwrapMaybe,
IrUnOpErrorReturn,
IrUnOpMaybeReturn,
};
struct IrInstructionUnOp {
@ -2004,6 +2018,53 @@ struct IrInstructionAlignOf {
IrInstruction *type_value;
};
// returns true if error, returns false if not error
struct IrInstructionTestErr {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionUnwrapErrCode {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionUnwrapErrPayload {
IrInstruction base;
IrInstruction *value;
bool safety_check_on;
};
struct IrInstructionErrUnionTypeChild {
IrInstruction base;
IrInstruction *type_value;
};
struct IrInstructionMaybeWrap {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
};
struct IrInstructionErrWrapPayload {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
};
struct IrInstructionErrWrapCode {
IrInstruction base;
IrInstruction *value;
LLVMValueRef tmp_ptr;
};
enum LValPurpose {
LValPurposeNone,
LValPurposeAssign,
@ -2019,4 +2080,7 @@ static const size_t maybe_null_index = 1;
static const size_t enum_gen_tag_index = 0;
static const size_t enum_gen_union_index = 1;
static const size_t err_union_err_index = 0;
static const size_t err_union_payload_index = 1;
#endif

View File

@ -862,10 +862,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, "const");
break;
}
case NodeTypeUnwrapErrorExpr:
{
render_node_ungrouped(ar, node->data.unwrap_err_expr.op1);
fprintf(ar->f, " %%%% ");
if (node->data.unwrap_err_expr.symbol) {
Buf *var_name = node->data.unwrap_err_expr.symbol->data.symbol_expr.symbol;
fprintf(ar->f, "|%s| ", buf_ptr(var_name));
}
render_node_ungrouped(ar, node->data.unwrap_err_expr.op2);
break;
}
case NodeTypeFnDecl:
case NodeTypeParamDecl:
case NodeTypeErrorValueDecl:
case NodeTypeUnwrapErrorExpr:
case NodeTypeStructField:
case NodeTypeUse:
case NodeTypeZeroesLiteral:

View File

@ -969,63 +969,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
} else {
zig_panic("TODO");
}
case CastOpMaybeWrap:
{
assert(cast_instruction->tmp_ptr);
assert(wanted_type->id == TypeTableEntryIdMaybe);
assert(actual_type);
TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
if (child_type->id == TypeTableEntryIdPointer ||
child_type->id == TypeTableEntryIdFn)
{
return expr_val;
} else {
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, "");
gen_assign_raw(g, cast_instruction->base.source_node,
val_ptr, expr_val, child_type, actual_type);
LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, "");
LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
}
return cast_instruction->tmp_ptr;
}
case CastOpNullToMaybe:
// handled by constant expression evaluator
zig_unreachable();
case CastOpErrorWrap:
{
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
TypeTableEntry *child_type = wanted_type->data.error.child_type;
LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
if (!type_has_bits(child_type)) {
return ok_err_val;
} else {
assert(cast_instruction->tmp_ptr);
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
assert(actual_type);
LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, "");
LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, "");
gen_assign_raw(g, cast_instruction->base.source_node,
payload_ptr, expr_val, child_type, actual_type);
return cast_instruction->tmp_ptr;
}
}
case CastOpPureErrorWrap:
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
if (!type_has_bits(wanted_type->data.error.child_type)) {
return expr_val;
} else {
zig_panic("TODO");
}
case CastOpPtrToInt:
return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
case CastOpIntToPtr:
@ -1257,78 +1200,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
{
zig_panic("TODO codegen PrefixOpMaybe");
}
case IrUnOpUnwrapError:
{
assert(expr_type->id == TypeTableEntryIdErrorUnion);
TypeTableEntry *child_type = expr_type->data.error.child_type;
if (ir_want_debug_safety(g, &un_op_instruction->base)) {
LLVMValueRef err_val;
if (type_has_bits(child_type)) {
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr, 0, "");
err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
} else {
err_val = expr;
}
LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrError");
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrOk");
LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
LLVMPositionBuilderAtEnd(g->builder, err_block);
gen_debug_safety_crash(g);
LLVMPositionBuilderAtEnd(g->builder, ok_block);
}
if (type_has_bits(child_type)) {
LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr, 1, "");
return get_handle_value(g, child_val_ptr, child_type);
} else {
return nullptr;
}
}
case IrUnOpUnwrapMaybe:
{
assert(expr_type->id == TypeTableEntryIdMaybe);
TypeTableEntry *child_type = expr_type->data.maybe.child_type;
if (ir_want_debug_safety(g, &un_op_instruction->base)) {
LLVMValueRef cond_val;
if (child_type->id == TypeTableEntryIdPointer ||
child_type->id == TypeTableEntryIdFn)
{
cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, expr,
LLVMConstNull(child_type->type_ref), "");
} else {
LLVMValueRef maybe_null_ptr = LLVMBuildStructGEP(g->builder, expr, 1, "");
cond_val = LLVMBuildLoad(g->builder, maybe_null_ptr, "");
}
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeOk");
LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeNull");
LLVMBuildCondBr(g->builder, cond_val, ok_block, null_block);
LLVMPositionBuilderAtEnd(g->builder, null_block);
gen_debug_safety_crash(g);
LLVMPositionBuilderAtEnd(g->builder, ok_block);
}
if (child_type->id == TypeTableEntryIdPointer ||
child_type->id == TypeTableEntryIdFn)
{
return expr;
} else {
LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr, 0, "");
return get_handle_value(g, maybe_field_ptr, child_type);
}
}
case IrUnOpErrorReturn:
case IrUnOpMaybeReturn:
zig_panic("TODO codegen more un ops");
}
zig_unreachable();
@ -2132,6 +2003,143 @@ 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) {
TypeTableEntry *ptr_type = get_underlying_type(instruction->value->type_entry);
TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type);
TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type);
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type);
LLVMValueRef err_val;
if (type_has_bits(child_type)) {
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
} else {
err_val = err_union_handle;
}
LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
}
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
TypeTableEntry *ptr_type = get_underlying_type(instruction->value->type_entry);
TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type);
TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type);
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type);
if (type_has_bits(child_type)) {
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
return LLVMBuildLoad(g->builder, err_val_ptr, "");
} else {
return err_union_handle;
}
}
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {
TypeTableEntry *ptr_type = get_underlying_type(instruction->value->type_entry);
TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type);
TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type);
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type);
if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) {
LLVMValueRef err_val;
if (type_has_bits(child_type)) {
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
} else {
err_val = err_union_handle;
}
LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrError");
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrOk");
LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
LLVMPositionBuilderAtEnd(g->builder, err_block);
gen_debug_safety_crash(g);
LLVMPositionBuilderAtEnd(g->builder, ok_block);
}
if (type_has_bits(child_type)) {
return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, "");
} else {
return nullptr;
}
}
static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, IrInstructionMaybeWrap *instruction) {
TypeTableEntry *wanted_type = instruction->base.type_entry;
assert(wanted_type->id == TypeTableEntryIdMaybe);
TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
if (child_type->id == TypeTableEntryIdPointer ||
child_type->id == TypeTableEntryIdFn)
{
return payload_val;
}
assert(instruction->tmp_ptr);
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
gen_assign_raw(g, instruction->base.source_node, val_ptr, payload_val, child_type, instruction->value->type_entry);
LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");
LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
return instruction->tmp_ptr;
}
static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapCode *instruction) {
TypeTableEntry *wanted_type = instruction->base.type_entry;
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
TypeTableEntry *child_type = wanted_type->data.error.child_type;
LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
if (!type_has_bits(child_type))
return err_val;
assert(instruction->tmp_ptr);
LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
LLVMBuildStore(g->builder, err_val, err_tag_ptr);
return instruction->tmp_ptr;
}
static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapPayload *instruction) {
TypeTableEntry *wanted_type = instruction->base.type_entry;
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
TypeTableEntry *child_type = wanted_type->data.error.child_type;
LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
if (!type_has_bits(child_type))
return ok_err_val;
assert(instruction->tmp_ptr);
LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
gen_assign_raw(g, instruction->base.source_node, payload_ptr, payload_val, child_type, instruction->value->type_entry);
return instruction->tmp_ptr;
}
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
AstNode *source_node = instruction->source_node;
Scope *scope = instruction->scope;
@ -2175,6 +2183,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdIntType:
case IrInstructionIdMemberCount:
case IrInstructionIdAlignOf:
case IrInstructionIdErrUnionTypeChild:
zig_unreachable();
case IrInstructionIdReturn:
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
@ -2250,6 +2259,18 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction);
case IrInstructionIdOverflowOp:
return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
case IrInstructionIdTestErr:
return ir_render_test_err(g, executable, (IrInstructionTestErr *)instruction);
case IrInstructionIdUnwrapErrCode:
return ir_render_unwrap_err_code(g, executable, (IrInstructionUnwrapErrCode *)instruction);
case IrInstructionIdUnwrapErrPayload:
return ir_render_unwrap_err_payload(g, executable, (IrInstructionUnwrapErrPayload *)instruction);
case IrInstructionIdMaybeWrap:
return ir_render_maybe_wrap(g, executable, (IrInstructionMaybeWrap *)instruction);
case IrInstructionIdErrWrapCode:
return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);
case IrInstructionIdErrWrapPayload:
return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
case IrInstructionIdSwitchVar:
case IrInstructionIdContainerInitList:
case IrInstructionIdStructInit:
@ -2835,6 +2856,15 @@ static void do_code_gen(CodeGen *g) {
} else if (instruction->id == IrInstructionIdSlice) {
IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;
slot = &slice_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdMaybeWrap) {
IrInstructionMaybeWrap *maybe_wrap_instruction = (IrInstructionMaybeWrap *)instruction;
slot = &maybe_wrap_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdErrWrapPayload) {
IrInstructionErrWrapPayload *err_wrap_payload_instruction = (IrInstructionErrWrapPayload *)instruction;
slot = &err_wrap_payload_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdErrWrapCode) {
IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
slot = &err_wrap_code_instruction->tmp_ptr;
} else {
zig_unreachable();
}

View File

@ -342,23 +342,6 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
const_val->special = ConstValSpecialStatic;
break;
}
case CastOpMaybeWrap:
const_val->data.x_maybe = other_val;
const_val->special = ConstValSpecialStatic;
break;
case CastOpNullToMaybe:
const_val->data.x_maybe = nullptr;
const_val->special = ConstValSpecialStatic;
break;
case CastOpErrorWrap:
const_val->data.x_err_union.err = nullptr;
const_val->data.x_err_union.payload = other_val;
const_val->special = ConstValSpecialStatic;
break;
case CastOpPureErrorWrap:
const_val->data.x_err_union.err = other_val->data.x_pure_err;
const_val->special = ConstValSpecialStatic;
break;
case CastOpErrToInt:
{
uint64_t value;

File diff suppressed because it is too large Load Diff

View File

@ -295,14 +295,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
return "?";
case IrUnOpError:
return "%";
case IrUnOpUnwrapError:
return "%%";
case IrUnOpUnwrapMaybe:
return "??";
case IrUnOpMaybeReturn:
return "?return";
case IrUnOpErrorReturn:
return "%return";
}
zig_unreachable();
}
@ -855,6 +847,51 @@ static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruct
fprintf(irp->f, ")");
}
static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
fprintf(irp->f, "@testError(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
}
static void ir_print_err_union_type_child(IrPrint *irp, IrInstructionErrUnionTypeChild *instruction) {
fprintf(irp->f, "@errorUnionTypeChild(");
ir_print_other_instruction(irp, instruction->type_value);
fprintf(irp->f, ")");
}
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, ")");
}
static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
fprintf(irp->f, "@unwrapErrorPayload(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
if (!instruction->safety_check_on) {
fprintf(irp->f, " // no safety");
}
}
static void ir_print_maybe_wrap(IrPrint *irp, IrInstructionMaybeWrap *instruction) {
fprintf(irp->f, "@maybeWrap(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
}
static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instruction) {
fprintf(irp->f, "@errWrapCode(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
}
static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload *instruction) {
fprintf(irp->f, "@errWrapPayload(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
}
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@ -1067,6 +1104,27 @@ 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);
break;
case IrInstructionIdUnwrapErrCode:
ir_print_unwrap_err_code(irp, (IrInstructionUnwrapErrCode *)instruction);
break;
case IrInstructionIdUnwrapErrPayload:
ir_print_unwrap_err_payload(irp, (IrInstructionUnwrapErrPayload *)instruction);
break;
case IrInstructionIdErrUnionTypeChild:
ir_print_err_union_type_child(irp, (IrInstructionErrUnionTypeChild *)instruction);
break;
case IrInstructionIdMaybeWrap:
ir_print_maybe_wrap(irp, (IrInstructionMaybeWrap *)instruction);
break;
case IrInstructionIdErrWrapCode:
ir_print_err_wrap_code(irp, (IrInstructionErrWrapCode *)instruction);
break;
case IrInstructionIdErrWrapPayload:
ir_print_err_wrap_payload(irp, (IrInstructionErrWrapPayload *)instruction);
break;
}
fprintf(irp->f, "\n");
}

View File

@ -0,0 +1,13 @@
pub fn foo() -> %i32 {
const x = %return bar();
return x + 1
}
pub fn bar() -> %i32 {
return 13;
}
pub fn baz() -> %i32 {
const y = foo() %% 1234;
return y + 1;
}

View File

@ -1,4 +1,5 @@
const case_namespace_fn_call = @import("cases/namespace_fn_call.zig");
const case_err_wrapping = @import("cases/err_wrapping.zig");
pub const SYS_write = 1;
pub const SYS_exit = 60;
@ -354,6 +355,9 @@ fn assignToIfVarPtr() {
assert(??maybe_bool == false);
}
fn errorWrapping() {
assert(%%case_err_wrapping.baz() == 15);
}
fn assert(ok: bool) {
if (!ok)
@ -390,6 +394,7 @@ fn runAllTests() {
overflowIntrinsics();
shlWithOverflow();
assignToIfVarPtr();
errorWrapping();
}
export nakedcc fn _start() -> unreachable {