IR: add more instructions
* MaybeWrap * TestErr * UnwrapErrCode * UnwrapErrPayload * ErrUnionTypeChild * ErrWrapCode * ErrWrapPayloadmaster
parent
3a3cc7bf76
commit
12fcbecbf8
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
288
src/codegen.cpp
288
src/codegen.cpp
|
@ -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();
|
||||
}
|
||||
|
|
17
src/eval.cpp
17
src/eval.cpp
|
@ -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;
|
||||
|
|
890
src/ir.cpp
890
src/ir.cpp
File diff suppressed because it is too large
Load Diff
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue