authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-17 16:06:48-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-17 16:16:17-05:00
log12fcbecbf8a1c8496354b909e0de2a69600115a9
tree4c625d36661db5860196763f8d952753f12d1fd4
parent3a3cc7bf76eab3ef239991e686c114baeaf4672e

IR: add more instructions

* MaybeWrap * TestErr * UnwrapErrCode * UnwrapErrPayload * ErrUnionTypeChild * ErrWrapCode * ErrWrapPayload

8 files changed, 863 insertions(+), 520 deletions(-)

src/all_types.hpp+74-10
...@@ -115,14 +115,26 @@ enum ConstValSpecial {...@@ -115,14 +115,26 @@ enum ConstValSpecial {
115 ConstValSpecialZeroes,115 ConstValSpecialZeroes,
116};116};
117117
118enum RuntimeHintErrorUnion {
119 RuntimeHintErrorUnionUnknown,
120 RuntimeHintErrorUnionError,
121 RuntimeHintErrorUnionNonError,
122};
123
124enum RuntimeHintMaybe {
125 RuntimeHintMaybeUnknown,
126 RuntimeHintMaybeNull, // TODO is this value even possible? if this is the case it might mean the const value is compile time known.
127 RuntimeHintMaybeNonNull,
128};
129
118struct ConstExprValue {130struct ConstExprValue {
119 ConstValSpecial special;131 ConstValSpecial special;
120 bool depends_on_compile_var;132 bool depends_on_compile_var;
121 LLVMValueRef llvm_value;133 LLVMValueRef llvm_value;
122 LLVMValueRef llvm_global;134 LLVMValueRef llvm_global;
123135
124 // populated if val_type == ConstValTypeOk
125 union {136 union {
137 // populated if special == ConstValSpecialStatic
126 BigNum x_bignum;138 BigNum x_bignum;
127 bool x_bool;139 bool x_bool;
128 FnTableEntry *x_fn;140 FnTableEntry *x_fn;
...@@ -137,6 +149,10 @@ struct ConstExprValue {...@@ -137,6 +149,10 @@ struct ConstExprValue {
137 ConstPtrValue x_ptr;149 ConstPtrValue x_ptr;
138 ImportTableEntry *x_import;150 ImportTableEntry *x_import;
139 Scope *x_block;151 Scope *x_block;
152
153 // populated if special == ConstValSpecialRuntime
154 RuntimeHintErrorUnion rh_error_union;
155 RuntimeHintMaybe rh_maybe;
140 } data;156 } data;
141};157};
142158
...@@ -412,10 +428,6 @@ enum CastOp {...@@ -412,10 +428,6 @@ enum CastOp {
412 CastOpIntToPtr,428 CastOpIntToPtr,
413 CastOpWidenOrShorten,429 CastOpWidenOrShorten,
414 CastOpToUnknownSizeArray,430 CastOpToUnknownSizeArray,
415 CastOpMaybeWrap,
416 CastOpNullToMaybe,
417 CastOpErrorWrap,
418 CastOpPureErrorWrap,
419 CastOpPointerReinterpret,431 CastOpPointerReinterpret,
420 CastOpErrToInt,432 CastOpErrToInt,
421 CastOpIntToFloat,433 CastOpIntToFloat,
...@@ -1394,6 +1406,7 @@ enum IrInstructionId {...@@ -1394,6 +1406,7 @@ enum IrInstructionId {
1394 IrInstructionIdSizeOf,1406 IrInstructionIdSizeOf,
1395 IrInstructionIdTestNull,1407 IrInstructionIdTestNull,
1396 IrInstructionIdUnwrapMaybe,1408 IrInstructionIdUnwrapMaybe,
1409 IrInstructionIdMaybeWrap,
1397 IrInstructionIdEnumTag,1410 IrInstructionIdEnumTag,
1398 IrInstructionIdClz,1411 IrInstructionIdClz,
1399 IrInstructionIdCtz,1412 IrInstructionIdCtz,
...@@ -1426,6 +1439,12 @@ enum IrInstructionId {...@@ -1426,6 +1439,12 @@ enum IrInstructionId {
1426 IrInstructionIdFrameAddress,1439 IrInstructionIdFrameAddress,
1427 IrInstructionIdAlignOf,1440 IrInstructionIdAlignOf,
1428 IrInstructionIdOverflowOp,1441 IrInstructionIdOverflowOp,
1442 IrInstructionIdTestErr,
1443 IrInstructionIdUnwrapErrCode,
1444 IrInstructionIdUnwrapErrPayload,
1445 IrInstructionIdErrUnionTypeChild,
1446 IrInstructionIdErrWrapCode,
1447 IrInstructionIdErrWrapPayload,
1429};1448};
14301449
1431struct IrInstruction {1450struct IrInstruction {
...@@ -1439,7 +1458,6 @@ struct IrInstruction {...@@ -1439,7 +1458,6 @@ struct IrInstruction {
1439 // if ref_count is zero, instruction can be omitted in codegen1458 // if ref_count is zero, instruction can be omitted in codegen
1440 size_t ref_count;1459 size_t ref_count;
1441 IrInstruction *other;1460 IrInstruction *other;
1442 ReturnKnowledge return_knowledge;
1443};1461};
14441462
1445struct IrInstructionCondBr {1463struct IrInstructionCondBr {
...@@ -1504,10 +1522,6 @@ enum IrUnOp {...@@ -1504,10 +1522,6 @@ enum IrUnOp {
1504 IrUnOpDereference,1522 IrUnOpDereference,
1505 IrUnOpError,1523 IrUnOpError,
1506 IrUnOpMaybe,1524 IrUnOpMaybe,
1507 IrUnOpUnwrapError,
1508 IrUnOpUnwrapMaybe,
1509 IrUnOpErrorReturn,
1510 IrUnOpMaybeReturn,
1511};1525};
15121526
1513struct IrInstructionUnOp {1527struct IrInstructionUnOp {
...@@ -2004,6 +2018,53 @@ struct IrInstructionAlignOf {...@@ -2004,6 +2018,53 @@ struct IrInstructionAlignOf {
2004 IrInstruction *type_value;2018 IrInstruction *type_value;
2005};2019};
20062020
2021// returns true if error, returns false if not error
2022struct IrInstructionTestErr {
2023 IrInstruction base;
2024
2025 IrInstruction *value;
2026};
2027
2028struct IrInstructionUnwrapErrCode {
2029 IrInstruction base;
2030
2031 IrInstruction *value;
2032};
2033
2034struct IrInstructionUnwrapErrPayload {
2035 IrInstruction base;
2036
2037 IrInstruction *value;
2038 bool safety_check_on;
2039};
2040
2041struct IrInstructionErrUnionTypeChild {
2042 IrInstruction base;
2043
2044 IrInstruction *type_value;
2045};
2046
2047struct IrInstructionMaybeWrap {
2048 IrInstruction base;
2049
2050 IrInstruction *value;
2051 LLVMValueRef tmp_ptr;
2052};
2053
2054struct IrInstructionErrWrapPayload {
2055 IrInstruction base;
2056
2057 IrInstruction *value;
2058 LLVMValueRef tmp_ptr;
2059};
2060
2061struct IrInstructionErrWrapCode {
2062 IrInstruction base;
2063
2064 IrInstruction *value;
2065 LLVMValueRef tmp_ptr;
2066};
2067
2007enum LValPurpose {2068enum LValPurpose {
2008 LValPurposeNone,2069 LValPurposeNone,
2009 LValPurposeAssign,2070 LValPurposeAssign,
...@@ -2019,4 +2080,7 @@ static const size_t maybe_null_index = 1;...@@ -2019,4 +2080,7 @@ static const size_t maybe_null_index = 1;
2019static const size_t enum_gen_tag_index = 0;2080static const size_t enum_gen_tag_index = 0;
2020static const size_t enum_gen_union_index = 1;2081static const size_t enum_gen_union_index = 1;
20212082
2083static const size_t err_union_err_index = 0;
2084static const size_t err_union_payload_index = 1;
2085
2022#endif2086#endif
src/ast_render.cpp+11-1
...@@ -862,10 +862,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -862,10 +862,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
862 fprintf(ar->f, "const");862 fprintf(ar->f, "const");
863 break;863 break;
864 }864 }
865 case NodeTypeUnwrapErrorExpr:
866 {
867 render_node_ungrouped(ar, node->data.unwrap_err_expr.op1);
868 fprintf(ar->f, " %%%% ");
869 if (node->data.unwrap_err_expr.symbol) {
870 Buf *var_name = node->data.unwrap_err_expr.symbol->data.symbol_expr.symbol;
871 fprintf(ar->f, "|%s| ", buf_ptr(var_name));
872 }
873 render_node_ungrouped(ar, node->data.unwrap_err_expr.op2);
874 break;
875 }
865 case NodeTypeFnDecl:876 case NodeTypeFnDecl:
866 case NodeTypeParamDecl:877 case NodeTypeParamDecl:
867 case NodeTypeErrorValueDecl:878 case NodeTypeErrorValueDecl:
868 case NodeTypeUnwrapErrorExpr:
869 case NodeTypeStructField:879 case NodeTypeStructField:
870 case NodeTypeUse:880 case NodeTypeUse:
871 case NodeTypeZeroesLiteral:881 case NodeTypeZeroesLiteral:
src/codegen.cpp+159-129
...@@ -969,63 +969,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -969,63 +969,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
969 } else {969 } else {
970 zig_panic("TODO");970 zig_panic("TODO");
971 }971 }
972 case CastOpMaybeWrap:
973 {
974 assert(cast_instruction->tmp_ptr);
975 assert(wanted_type->id == TypeTableEntryIdMaybe);
976 assert(actual_type);
977
978 TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
979
980 if (child_type->id == TypeTableEntryIdPointer ||
981 child_type->id == TypeTableEntryIdFn)
982 {
983 return expr_val;
984 } else {
985 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, "");
986 gen_assign_raw(g, cast_instruction->base.source_node,
987 val_ptr, expr_val, child_type, actual_type);
988
989 LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, "");
990 LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
991 }
992
993 return cast_instruction->tmp_ptr;
994 }
995 case CastOpNullToMaybe:
996 // handled by constant expression evaluator
997 zig_unreachable();
998 case CastOpErrorWrap:
999 {
1000 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
1001 TypeTableEntry *child_type = wanted_type->data.error.child_type;
1002 LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
1003
1004 if (!type_has_bits(child_type)) {
1005 return ok_err_val;
1006 } else {
1007 assert(cast_instruction->tmp_ptr);
1008 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
1009 assert(actual_type);
1010
1011 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, "");
1012 LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
1013
1014 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, "");
1015 gen_assign_raw(g, cast_instruction->base.source_node,
1016 payload_ptr, expr_val, child_type, actual_type);
1017
1018 return cast_instruction->tmp_ptr;
1019 }
1020 }
1021 case CastOpPureErrorWrap:
1022 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
1023
1024 if (!type_has_bits(wanted_type->data.error.child_type)) {
1025 return expr_val;
1026 } else {
1027 zig_panic("TODO");
1028 }
1029 case CastOpPtrToInt:972 case CastOpPtrToInt:
1030 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");973 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
1031 case CastOpIntToPtr:974 case CastOpIntToPtr:
...@@ -1257,78 +1200,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst...@@ -1257,78 +1200,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
1257 {1200 {
1258 zig_panic("TODO codegen PrefixOpMaybe");1201 zig_panic("TODO codegen PrefixOpMaybe");
1259 }1202 }
1260 case IrUnOpUnwrapError:
1261 {
1262 assert(expr_type->id == TypeTableEntryIdErrorUnion);
1263 TypeTableEntry *child_type = expr_type->data.error.child_type;
1264
1265 if (ir_want_debug_safety(g, &un_op_instruction->base)) {
1266 LLVMValueRef err_val;
1267 if (type_has_bits(child_type)) {
1268 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr, 0, "");
1269 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
1270 } else {
1271 err_val = expr;
1272 }
1273 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
1274 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
1275 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrError");
1276 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrOk");
1277 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
1278
1279 LLVMPositionBuilderAtEnd(g->builder, err_block);
1280 gen_debug_safety_crash(g);
1281
1282 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1283 }
1284
1285 if (type_has_bits(child_type)) {
1286 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr, 1, "");
1287 return get_handle_value(g, child_val_ptr, child_type);
1288 } else {
1289 return nullptr;
1290 }
1291 }
1292 case IrUnOpUnwrapMaybe:
1293 {
1294 assert(expr_type->id == TypeTableEntryIdMaybe);
1295 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
1296
1297 if (ir_want_debug_safety(g, &un_op_instruction->base)) {
1298 LLVMValueRef cond_val;
1299 if (child_type->id == TypeTableEntryIdPointer ||
1300 child_type->id == TypeTableEntryIdFn)
1301 {
1302 cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, expr,
1303 LLVMConstNull(child_type->type_ref), "");
1304 } else {
1305 LLVMValueRef maybe_null_ptr = LLVMBuildStructGEP(g->builder, expr, 1, "");
1306 cond_val = LLVMBuildLoad(g->builder, maybe_null_ptr, "");
1307 }
1308
1309 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeOk");
1310 LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeNull");
1311 LLVMBuildCondBr(g->builder, cond_val, ok_block, null_block);
1312
1313 LLVMPositionBuilderAtEnd(g->builder, null_block);
1314 gen_debug_safety_crash(g);
1315
1316 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1317 }
1318
1319
1320 if (child_type->id == TypeTableEntryIdPointer ||
1321 child_type->id == TypeTableEntryIdFn)
1322 {
1323 return expr;
1324 } else {
1325 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr, 0, "");
1326 return get_handle_value(g, maybe_field_ptr, child_type);
1327 }
1328 }
1329 case IrUnOpErrorReturn:
1330 case IrUnOpMaybeReturn:
1331 zig_panic("TODO codegen more un ops");
1332 }1203 }
13331204
1334 zig_unreachable();1205 zig_unreachable();
...@@ -2132,6 +2003,143 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,...@@ -2132,6 +2003,143 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
2132 return overflow_bit;2003 return overflow_bit;
2133}2004}
21342005
2006static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) {
2007 TypeTableEntry *ptr_type = get_underlying_type(instruction->value->type_entry);
2008 TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type);
2009 TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type);
2010 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
2011 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type);
2012
2013 LLVMValueRef err_val;
2014 if (type_has_bits(child_type)) {
2015 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
2016 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
2017 } else {
2018 err_val = err_union_handle;
2019 }
2020
2021 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
2022 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
2023}
2024
2025static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
2026 TypeTableEntry *ptr_type = get_underlying_type(instruction->value->type_entry);
2027 TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type);
2028 TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type);
2029 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
2030 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type);
2031
2032 if (type_has_bits(child_type)) {
2033 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
2034 return LLVMBuildLoad(g->builder, err_val_ptr, "");
2035 } else {
2036 return err_union_handle;
2037 }
2038}
2039
2040static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {
2041 TypeTableEntry *ptr_type = get_underlying_type(instruction->value->type_entry);
2042 TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type);
2043 TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type);
2044 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
2045 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type);
2046
2047 if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) {
2048 LLVMValueRef err_val;
2049 if (type_has_bits(child_type)) {
2050 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
2051 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
2052 } else {
2053 err_val = err_union_handle;
2054 }
2055 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
2056 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
2057 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrError");
2058 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrOk");
2059 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
2060
2061 LLVMPositionBuilderAtEnd(g->builder, err_block);
2062 gen_debug_safety_crash(g);
2063
2064 LLVMPositionBuilderAtEnd(g->builder, ok_block);
2065 }
2066
2067 if (type_has_bits(child_type)) {
2068 return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, "");
2069 } else {
2070 return nullptr;
2071 }
2072}
2073
2074static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, IrInstructionMaybeWrap *instruction) {
2075 TypeTableEntry *wanted_type = instruction->base.type_entry;
2076
2077 assert(wanted_type->id == TypeTableEntryIdMaybe);
2078
2079 TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
2080
2081 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
2082 if (child_type->id == TypeTableEntryIdPointer ||
2083 child_type->id == TypeTableEntryIdFn)
2084 {
2085 return payload_val;
2086 }
2087
2088 assert(instruction->tmp_ptr);
2089
2090 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
2091 gen_assign_raw(g, instruction->base.source_node, val_ptr, payload_val, child_type, instruction->value->type_entry);
2092
2093 LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");
2094 LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
2095
2096 return instruction->tmp_ptr;
2097}
2098
2099static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapCode *instruction) {
2100 TypeTableEntry *wanted_type = instruction->base.type_entry;
2101
2102 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
2103
2104 TypeTableEntry *child_type = wanted_type->data.error.child_type;
2105 LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
2106
2107 if (!type_has_bits(child_type))
2108 return err_val;
2109
2110 assert(instruction->tmp_ptr);
2111
2112 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
2113 LLVMBuildStore(g->builder, err_val, err_tag_ptr);
2114
2115 return instruction->tmp_ptr;
2116}
2117
2118static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapPayload *instruction) {
2119 TypeTableEntry *wanted_type = instruction->base.type_entry;
2120
2121 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
2122
2123 TypeTableEntry *child_type = wanted_type->data.error.child_type;
2124
2125 LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
2126
2127 if (!type_has_bits(child_type))
2128 return ok_err_val;
2129
2130 assert(instruction->tmp_ptr);
2131
2132 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
2133
2134 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
2135 LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
2136
2137 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
2138 gen_assign_raw(g, instruction->base.source_node, payload_ptr, payload_val, child_type, instruction->value->type_entry);
2139
2140 return instruction->tmp_ptr;
2141}
2142
2135static void set_debug_location(CodeGen *g, IrInstruction *instruction) {2143static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
2136 AstNode *source_node = instruction->source_node;2144 AstNode *source_node = instruction->source_node;
2137 Scope *scope = instruction->scope;2145 Scope *scope = instruction->scope;
...@@ -2175,6 +2183,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2175,6 +2183,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2175 case IrInstructionIdIntType:2183 case IrInstructionIdIntType:
2176 case IrInstructionIdMemberCount:2184 case IrInstructionIdMemberCount:
2177 case IrInstructionIdAlignOf:2185 case IrInstructionIdAlignOf:
2186 case IrInstructionIdErrUnionTypeChild:
2178 zig_unreachable();2187 zig_unreachable();
2179 case IrInstructionIdReturn:2188 case IrInstructionIdReturn:
2180 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);2189 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
...@@ -2250,6 +2259,18 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2250,6 +2259,18 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2250 return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction);2259 return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction);
2251 case IrInstructionIdOverflowOp:2260 case IrInstructionIdOverflowOp:
2252 return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);2261 return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
2262 case IrInstructionIdTestErr:
2263 return ir_render_test_err(g, executable, (IrInstructionTestErr *)instruction);
2264 case IrInstructionIdUnwrapErrCode:
2265 return ir_render_unwrap_err_code(g, executable, (IrInstructionUnwrapErrCode *)instruction);
2266 case IrInstructionIdUnwrapErrPayload:
2267 return ir_render_unwrap_err_payload(g, executable, (IrInstructionUnwrapErrPayload *)instruction);
2268 case IrInstructionIdMaybeWrap:
2269 return ir_render_maybe_wrap(g, executable, (IrInstructionMaybeWrap *)instruction);
2270 case IrInstructionIdErrWrapCode:
2271 return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);
2272 case IrInstructionIdErrWrapPayload:
2273 return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
2253 case IrInstructionIdSwitchVar:2274 case IrInstructionIdSwitchVar:
2254 case IrInstructionIdContainerInitList:2275 case IrInstructionIdContainerInitList:
2255 case IrInstructionIdStructInit:2276 case IrInstructionIdStructInit:
...@@ -2835,6 +2856,15 @@ static void do_code_gen(CodeGen *g) {...@@ -2835,6 +2856,15 @@ static void do_code_gen(CodeGen *g) {
2835 } else if (instruction->id == IrInstructionIdSlice) {2856 } else if (instruction->id == IrInstructionIdSlice) {
2836 IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;2857 IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;
2837 slot = &slice_instruction->tmp_ptr;2858 slot = &slice_instruction->tmp_ptr;
2859 } else if (instruction->id == IrInstructionIdMaybeWrap) {
2860 IrInstructionMaybeWrap *maybe_wrap_instruction = (IrInstructionMaybeWrap *)instruction;
2861 slot = &maybe_wrap_instruction->tmp_ptr;
2862 } else if (instruction->id == IrInstructionIdErrWrapPayload) {
2863 IrInstructionErrWrapPayload *err_wrap_payload_instruction = (IrInstructionErrWrapPayload *)instruction;
2864 slot = &err_wrap_payload_instruction->tmp_ptr;
2865 } else if (instruction->id == IrInstructionIdErrWrapCode) {
2866 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
2867 slot = &err_wrap_code_instruction->tmp_ptr;
2838 } else {2868 } else {
2839 zig_unreachable();2869 zig_unreachable();
2840 }2870 }
src/eval.cpp-17
...@@ -342,23 +342,6 @@ void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -342,23 +342,6 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
342 const_val->special = ConstValSpecialStatic;342 const_val->special = ConstValSpecialStatic;
343 break;343 break;
344 }344 }
345 case CastOpMaybeWrap:
346 const_val->data.x_maybe = other_val;
347 const_val->special = ConstValSpecialStatic;
348 break;
349 case CastOpNullToMaybe:
350 const_val->data.x_maybe = nullptr;
351 const_val->special = ConstValSpecialStatic;
352 break;
353 case CastOpErrorWrap:
354 const_val->data.x_err_union.err = nullptr;
355 const_val->data.x_err_union.payload = other_val;
356 const_val->special = ConstValSpecialStatic;
357 break;
358 case CastOpPureErrorWrap:
359 const_val->data.x_err_union.err = other_val->data.x_pure_err;
360 const_val->special = ConstValSpecialStatic;
361 break;
362 case CastOpErrToInt:345 case CastOpErrToInt:
363 {346 {
364 uint64_t value;347 uint64_t value;
src/ir.cpp+535-355
...@@ -93,6 +93,10 @@ static Buf *exec_c_import_buf(IrExecutable *exec) {...@@ -93,6 +93,10 @@ static Buf *exec_c_import_buf(IrExecutable *exec) {
93 return exec->c_import_buf;93 return exec->c_import_buf;
94}94}
9595
96static bool instr_is_comptime(IrInstruction *instruction) {
97 return instruction->static_value.special != ConstValSpecialRuntime;
98}
99
96static void ir_link_new_instruction(IrInstruction *new_instruction, IrInstruction *old_instruction) {100static void ir_link_new_instruction(IrInstruction *new_instruction, IrInstruction *old_instruction) {
97 new_instruction->other = old_instruction;101 new_instruction->other = old_instruction;
98 old_instruction->other = new_instruction;102 old_instruction->other = new_instruction;
...@@ -411,6 +415,34 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {...@@ -411,6 +415,34 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {
411 return IrInstructionIdOverflowOp;415 return IrInstructionIdOverflowOp;
412}416}
413417
418static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErr *) {
419 return IrInstructionIdTestErr;
420}
421
422static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrCode *) {
423 return IrInstructionIdUnwrapErrCode;
424}
425
426static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrPayload *) {
427 return IrInstructionIdUnwrapErrPayload;
428}
429
430static constexpr IrInstructionId ir_instruction_id(IrInstructionErrUnionTypeChild *) {
431 return IrInstructionIdErrUnionTypeChild;
432}
433
434static constexpr IrInstructionId ir_instruction_id(IrInstructionMaybeWrap *) {
435 return IrInstructionIdMaybeWrap;
436}
437
438static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapPayload *) {
439 return IrInstructionIdErrWrapPayload;
440}
441
442static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapCode *) {
443 return IrInstructionIdErrWrapCode;
444}
445
414template<typename T>446template<typename T>
415static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {447static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
416 T *special_instruction = allocate<T>(1);448 T *special_instruction = allocate<T>(1);
...@@ -1037,8 +1069,11 @@ static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode...@@ -1037,8 +1069,11 @@ static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode
1037 return &instruction->base;1069 return &instruction->base;
1038}1070}
10391071
1040static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1072static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node,
1041 IrInstructionPtrTypeChild *instruction = ir_build_instruction<IrInstructionPtrTypeChild>(irb, scope, source_node);1073 IrInstruction *value)
1074{
1075 IrInstructionPtrTypeChild *instruction = ir_build_instruction<IrInstructionPtrTypeChild>(
1076 irb, scope, source_node);
1042 instruction->value = value;1077 instruction->value = value;
10431078
1044 ir_ref_instruction(value);1079 ir_ref_instruction(value);
...@@ -1198,6 +1233,33 @@ static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction *...@@ -1198,6 +1233,33 @@ static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction *
1198 return new_instruction;1233 return new_instruction;
1199}1234}
12001235
1236static IrInstruction *ir_build_maybe_wrap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1237 IrInstructionMaybeWrap *instruction = ir_build_instruction<IrInstructionMaybeWrap>(irb, scope, source_node);
1238 instruction->value = value;
1239
1240 ir_ref_instruction(value);
1241
1242 return &instruction->base;
1243}
1244
1245static IrInstruction *ir_build_err_wrap_payload(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1246 IrInstructionErrWrapPayload *instruction = ir_build_instruction<IrInstructionErrWrapPayload>(irb, scope, source_node);
1247 instruction->value = value;
1248
1249 ir_ref_instruction(value);
1250
1251 return &instruction->base;
1252}
1253
1254static IrInstruction *ir_build_err_wrap_code(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1255 IrInstructionErrWrapCode *instruction = ir_build_instruction<IrInstructionErrWrapCode>(irb, scope, source_node);
1256 instruction->value = value;
1257
1258 ir_ref_instruction(value);
1259
1260 return &instruction->base;
1261}
1262
1201static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1263static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1202 IrInstructionClz *instruction = ir_build_instruction<IrInstructionClz>(irb, scope, source_node);1264 IrInstructionClz *instruction = ir_build_instruction<IrInstructionClz>(irb, scope, source_node);
1203 instruction->value = value;1265 instruction->value = value;
...@@ -1709,6 +1771,76 @@ static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *so...@@ -1709,6 +1771,76 @@ static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *so
1709 return &instruction->base;1771 return &instruction->base;
1710}1772}
17111773
1774static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *source_node,
1775 IrInstruction *value)
1776{
1777 IrInstructionTestErr *instruction = ir_build_instruction<IrInstructionTestErr>(irb, scope, source_node);
1778 instruction->value = value;
1779
1780 ir_ref_instruction(value);
1781
1782 return &instruction->base;
1783}
1784
1785static IrInstruction *ir_build_test_err_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
1786 IrInstruction *new_instruction = ir_build_test_err(irb, old_instruction->scope, old_instruction->source_node,
1787 value);
1788 ir_link_new_instruction(new_instruction, old_instruction);
1789 return new_instruction;
1790}
1791
1792static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
1793 IrInstruction *value)
1794{
1795 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);
1796 instruction->value = value;
1797
1798 ir_ref_instruction(value);
1799
1800 return &instruction->base;
1801}
1802
1803static IrInstruction *ir_build_unwrap_err_code_from(IrBuilder *irb, IrInstruction *old_instruction,
1804 IrInstruction *value)
1805{
1806 IrInstruction *new_instruction = ir_build_unwrap_err_code(irb, old_instruction->scope,
1807 old_instruction->source_node, value);
1808 ir_link_new_instruction(new_instruction, old_instruction);
1809 return new_instruction;
1810}
1811
1812static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope, AstNode *source_node,
1813 IrInstruction *value, bool safety_check_on)
1814{
1815 IrInstructionUnwrapErrPayload *instruction = ir_build_instruction<IrInstructionUnwrapErrPayload>(irb, scope, source_node);
1816 instruction->value = value;
1817 instruction->safety_check_on = safety_check_on;
1818
1819 ir_ref_instruction(value);
1820
1821 return &instruction->base;
1822}
1823
1824static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruction *old_instruction,
1825 IrInstruction *value, bool safety_check_on)
1826{
1827 IrInstruction *new_instruction = ir_build_unwrap_err_payload(irb, old_instruction->scope,
1828 old_instruction->source_node, value, safety_check_on);
1829 ir_link_new_instruction(new_instruction, old_instruction);
1830 return new_instruction;
1831}
1832
1833static IrInstruction *ir_build_err_union_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node,
1834 IrInstruction *type_value)
1835{
1836 IrInstructionErrUnionTypeChild *instruction = ir_build_instruction<IrInstructionErrUnionTypeChild>(irb, scope, source_node);
1837 instruction->type_value = type_value;
1838
1839 ir_ref_instruction(type_value);
1840
1841 return &instruction->base;
1842}
1843
1712static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {1844static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
1713 results[ReturnKindUnconditional] = 0;1845 results[ReturnKindUnconditional] = 0;
1714 results[ReturnKindError] = 0;1846 results[ReturnKindError] = 0;
...@@ -1799,7 +1931,29 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -1799,7 +1931,29 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
1799 return ir_build_return(irb, scope, node, return_value);1931 return ir_build_return(irb, scope, node, return_value);
1800 }1932 }
1801 case ReturnKindError:1933 case ReturnKindError:
1802 zig_panic("TODO gen IR for %%return");1934 {
1935 assert(expr_node);
1936 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf);
1937 if (err_union_ptr == irb->codegen->invalid_instruction)
1938 return irb->codegen->invalid_instruction;
1939 IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_ptr);
1940
1941 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn");
1942 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "ErrRetContinue");
1943 ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_inline);
1944
1945 ir_set_cursor_at_end(irb, return_block);
1946 ir_gen_defers_for_block(irb, scope, outer_scope, true, false);
1947 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
1948 ir_build_return(irb, scope, node, err_val);
1949
1950 ir_set_cursor_at_end(irb, continue_block);
1951 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);
1952 if (lval != LValPurposeNone)
1953 return unwrapped_ptr;
1954 else
1955 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
1956 }
1803 case ReturnKindMaybe:1957 case ReturnKindMaybe:
1804 {1958 {
1805 assert(expr_node);1959 assert(expr_node);
...@@ -2798,13 +2952,33 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode...@@ -2798,13 +2952,33 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode
2798 return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone);2952 return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone);
2799}2953}
28002954
2801static IrInstruction *ir_gen_prefix_op_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {2955static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {
2802 AstNode *expr = node->data.prefix_op_expr.primary_expr;2956 assert(node->type == NodeTypePrefixOpExpr);
2803 IrInstruction *value = ir_gen_node_extra(irb, expr, scope, LValPurposeAddressOf);2957 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
2804 if (value == irb->codegen->invalid_instruction)2958
2805 return value;2959 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf);
2960 if (err_union_ptr == irb->codegen->invalid_instruction)
2961 return irb->codegen->invalid_instruction;
2962
2963 IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, true);
2964 if (payload_ptr == irb->codegen->invalid_instruction)
2965 return irb->codegen->invalid_instruction;
28062966
2807 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, value, true);2967 if (lval == LValPurposeNone)
2968 return ir_build_load_ptr(irb, scope, node, payload_ptr);
2969 else
2970 return payload_ptr;
2971}
2972
2973static IrInstruction *ir_gen_maybe_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {
2974 assert(node->type == NodeTypePrefixOpExpr);
2975 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
2976
2977 IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf);
2978 if (maybe_ptr == irb->codegen->invalid_instruction)
2979 return irb->codegen->invalid_instruction;
2980
2981 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true);
2808 if (lval == LValPurposeNone)2982 if (lval == LValPurposeNone)
2809 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);2983 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
2810 else2984 else
...@@ -2860,9 +3034,9 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod...@@ -2860,9 +3034,9 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
2860 case PrefixOpError:3034 case PrefixOpError:
2861 return ir_gen_prefix_op_id(irb, scope, node, IrUnOpError);3035 return ir_gen_prefix_op_id(irb, scope, node, IrUnOpError);
2862 case PrefixOpUnwrapError:3036 case PrefixOpUnwrapError:
2863 return ir_gen_prefix_op_id(irb, scope, node, IrUnOpUnwrapError);3037 return ir_gen_err_assert_ok(irb, scope, node, lval);
2864 case PrefixOpUnwrapMaybe:3038 case PrefixOpUnwrapMaybe:
2865 return ir_gen_prefix_op_unwrap_maybe(irb, scope, node, lval);3039 return ir_gen_maybe_assert_ok(irb, scope, node, lval);
2866 }3040 }
2867 zig_unreachable();3041 zig_unreachable();
2868}3042}
...@@ -3626,6 +3800,66 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3626,6 +3800,66 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
3626 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, slice_expr->is_const);3800 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, slice_expr->is_const);
3627}3801}
36283802
3803static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
3804 assert(node->type == NodeTypeUnwrapErrorExpr);
3805
3806 AstNode *op1_node = node->data.unwrap_err_expr.op1;
3807 AstNode *op2_node = node->data.unwrap_err_expr.op2;
3808 AstNode *var_node = node->data.unwrap_err_expr.symbol;
3809
3810 bool is_inline = ir_should_inline(irb);
3811
3812 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf);
3813 if (err_union_ptr == irb->codegen->invalid_instruction)
3814 return irb->codegen->invalid_instruction;
3815
3816 IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_ptr);
3817
3818 IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrOk");
3819 IrBasicBlock *err_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrError");
3820 IrBasicBlock *end_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrEnd");
3821 ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_inline);
3822
3823 ir_set_cursor_at_end(irb, err_block);
3824 Scope *err_scope;
3825 if (var_node) {
3826 assert(var_node->type == NodeTypeSymbol);
3827 IrInstruction *err_union_ptr_type = ir_build_typeof(irb, parent_scope, var_node, err_union_ptr);
3828 IrInstruction *err_union_type = ir_build_ptr_type_child(irb, parent_scope, var_node, err_union_ptr_type);
3829 IrInstruction *var_type = ir_build_err_union_type_child(irb, parent_scope, var_node, err_union_type);
3830 Buf *var_name = var_node->data.symbol_expr.symbol;
3831 bool is_const = true;
3832 bool is_shadowable = false;
3833 VariableTableEntry *var = ir_create_var(irb, node, parent_scope, var_name,
3834 is_const, is_const, is_shadowable, is_inline);
3835 err_scope = var->child_scope;
3836 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
3837 ir_build_var_decl(irb, err_scope, var_node, var, var_type, err_val);
3838 } else {
3839 err_scope = parent_scope;
3840 }
3841 IrInstruction *err_result = ir_gen_node(irb, op2_node, err_scope);
3842 if (err_result == irb->codegen->invalid_instruction)
3843 return irb->codegen->invalid_instruction;
3844 IrBasicBlock *after_err_block = irb->current_basic_block;
3845 ir_build_br(irb, err_scope, node, end_block, is_inline);
3846
3847 ir_set_cursor_at_end(irb, ok_block);
3848 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false);
3849 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
3850 IrBasicBlock *after_ok_block = irb->current_basic_block;
3851 ir_build_br(irb, parent_scope, node, end_block, is_inline);
3852
3853 ir_set_cursor_at_end(irb, end_block);
3854 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
3855 incoming_values[0] = err_result;
3856 incoming_values[1] = unwrapped_payload;
3857 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
3858 incoming_blocks[0] = after_err_block;
3859 incoming_blocks[1] = after_ok_block;
3860 return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
3861}
3862
3629static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,3863static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
3630 LValPurpose lval)3864 LValPurpose lval)
3631{3865{
...@@ -3703,6 +3937,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -3703,6 +3937,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
3703 case NodeTypeSliceExpr:3937 case NodeTypeSliceExpr:
3704 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);3938 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
3705 case NodeTypeUnwrapErrorExpr:3939 case NodeTypeUnwrapErrorExpr:
3940 return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval);
3706 case NodeTypeZeroesLiteral:3941 case NodeTypeZeroesLiteral:
3707 case NodeTypeVarLiteral:3942 case NodeTypeVarLiteral:
3708 case NodeTypeFnProto:3943 case NodeTypeFnProto:
...@@ -4279,11 +4514,20 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins...@@ -4279,11 +4514,20 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins
4279}4514}
42804515
4281static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) {4516static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) {
4282 if (value->static_value.special != ConstValSpecialStatic) {4517 switch (value->static_value.special) {
4283 ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression"));4518 case ConstValSpecialStatic:
4284 return nullptr;4519 return &value->static_value;
4520 case ConstValSpecialRuntime:
4521 ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression"));
4522 return nullptr;
4523 case ConstValSpecialUndef:
4524 ir_add_error(ira, value, buf_sprintf("use of undefined value"));
4525 return nullptr;
4526 case ConstValSpecialZeroes:
4527 ir_add_error(ira, value, buf_sprintf("zeroes is deprecated"));
4528 return nullptr;
4285 }4529 }
4286 return &value->static_value;4530 zig_unreachable();
4287}4531}
42884532
4289IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,4533IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
...@@ -4375,6 +4619,95 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {...@@ -4375,6 +4619,95 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
4375 return const_val->data.x_fn;4619 return const_val->data.x_fn;
4376}4620}
43774621
4622static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
4623 assert(wanted_type->id == TypeTableEntryIdMaybe);
4624
4625 if (instr_is_comptime(value)) {
4626 ConstExprValue *val = ir_resolve_const(ira, value);
4627 if (!val)
4628 return ira->codegen->invalid_instruction;
4629
4630 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec,
4631 source_instr->scope, source_instr->source_node);
4632 const_instruction->base.type_entry = wanted_type;
4633 const_instruction->base.static_value.special = ConstValSpecialStatic;
4634 const_instruction->base.static_value.depends_on_compile_var = val->depends_on_compile_var;
4635 const_instruction->base.static_value.data.x_maybe = &value->static_value;
4636 return &const_instruction->base;
4637 }
4638
4639 IrInstruction *result = ir_build_maybe_wrap(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
4640 result->type_entry = wanted_type;
4641 result->static_value.data.rh_maybe = RuntimeHintMaybeNonNull;
4642 ir_add_alloca(ira, result, wanted_type);
4643 return result;
4644}
4645
4646static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
4647 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
4648
4649 if (instr_is_comptime(value)) {
4650 ConstExprValue *val = ir_resolve_const(ira, value);
4651 if (!val)
4652 return ira->codegen->invalid_instruction;
4653
4654 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec,
4655 source_instr->scope, source_instr->source_node);
4656 const_instruction->base.type_entry = wanted_type;
4657 const_instruction->base.static_value.special = ConstValSpecialStatic;
4658 const_instruction->base.static_value.depends_on_compile_var = val->depends_on_compile_var;
4659 const_instruction->base.static_value.data.x_err_union.err = nullptr;
4660 const_instruction->base.static_value.data.x_err_union.payload = val;
4661 return &const_instruction->base;
4662 }
4663
4664 IrInstruction *result = ir_build_err_wrap_payload(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
4665 result->type_entry = wanted_type;
4666 result->static_value.data.rh_error_union = RuntimeHintErrorUnionNonError;
4667 ir_add_alloca(ira, result, wanted_type);
4668 return result;
4669}
4670
4671static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
4672 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
4673
4674 if (instr_is_comptime(value)) {
4675 ConstExprValue *val = ir_resolve_const(ira, value);
4676 if (!val)
4677 return ira->codegen->invalid_instruction;
4678
4679 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec,
4680 source_instr->scope, source_instr->source_node);
4681 const_instruction->base.type_entry = wanted_type;
4682 const_instruction->base.static_value.special = ConstValSpecialStatic;
4683 const_instruction->base.static_value.depends_on_compile_var = val->depends_on_compile_var;
4684 const_instruction->base.static_value.data.x_err_union.err = val->data.x_pure_err;
4685 const_instruction->base.static_value.data.x_err_union.payload = nullptr;
4686 return &const_instruction->base;
4687 }
4688
4689 IrInstruction *result = ir_build_err_wrap_code(&ira->new_irb, source_instr->scope, source_instr->source_node, value);
4690 result->type_entry = wanted_type;
4691 result->static_value.data.rh_error_union = RuntimeHintErrorUnionError;
4692 ir_add_alloca(ira, result, wanted_type);
4693 return result;
4694}
4695
4696static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {
4697 assert(wanted_type->id == TypeTableEntryIdMaybe);
4698 assert(instr_is_comptime(value));
4699
4700 ConstExprValue *val = ir_resolve_const(ira, value);
4701 assert(val);
4702
4703 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec, source_instr->scope, source_instr->source_node);
4704 const_instruction->base.type_entry = wanted_type;
4705 const_instruction->base.static_value.special = ConstValSpecialStatic;
4706 const_instruction->base.static_value.depends_on_compile_var = val->depends_on_compile_var;
4707 const_instruction->base.static_value.data.x_maybe = nullptr;
4708 return &const_instruction->base;
4709}
4710
4378static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,4711static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
4379 TypeTableEntry *wanted_type, IrInstruction *value)4712 TypeTableEntry *wanted_type, IrInstruction *value)
4380{4713{
...@@ -4503,18 +4836,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -4503,18 +4836,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
4503 // explicit cast from child type of maybe type to maybe type4836 // explicit cast from child type of maybe type to maybe type
4504 if (wanted_type->id == TypeTableEntryIdMaybe) {4837 if (wanted_type->id == TypeTableEntryIdMaybe) {
4505 if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) {4838 if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) {
4506 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type,4839 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
4507 CastOpMaybeWrap, true);
4508 cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull;
4509 return cast_instruction;
4510 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||4840 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
4511 actual_type->id == TypeTableEntryIdNumLitFloat)4841 actual_type->id == TypeTableEntryIdNumLitFloat)
4512 {4842 {
4513 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type)) {4843 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type)) {
4514 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type,4844 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
4515 CastOpMaybeWrap, true);
4516 cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull;
4517 return cast_instruction;
4518 } else {4845 } else {
4519 return ira->codegen->invalid_instruction;4846 return ira->codegen->invalid_instruction;
4520 }4847 }
...@@ -4525,27 +4852,18 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -4525,27 +4852,18 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
4525 if (wanted_type->id == TypeTableEntryIdMaybe &&4852 if (wanted_type->id == TypeTableEntryIdMaybe &&
4526 actual_type->id == TypeTableEntryIdNullLit)4853 actual_type->id == TypeTableEntryIdNullLit)
4527 {4854 {
4528 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type,4855 return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
4529 CastOpNullToMaybe, true);
4530 cast_instruction->return_knowledge = ReturnKnowledgeKnownNull;
4531 return cast_instruction;
4532 }4856 }
45334857
4534 // explicit cast from child type of error type to error type4858 // explicit cast from child type of error type to error type
4535 if (wanted_type->id == TypeTableEntryIdErrorUnion) {4859 if (wanted_type->id == TypeTableEntryIdErrorUnion) {
4536 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {4860 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
4537 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type,4861 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
4538 CastOpErrorWrap, true);
4539 cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError;
4540 return cast_instruction;
4541 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||4862 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
4542 actual_type->id == TypeTableEntryIdNumLitFloat)4863 actual_type->id == TypeTableEntryIdNumLitFloat)
4543 {4864 {
4544 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type)) {4865 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type)) {
4545 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type,4866 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
4546 CastOpErrorWrap, true);
4547 cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError;
4548 return cast_instruction;
4549 } else {4867 } else {
4550 return ira->codegen->invalid_instruction;4868 return ira->codegen->invalid_instruction;
4551 }4869 }
...@@ -4556,10 +4874,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -4556,10 +4874,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
4556 if (wanted_type->id == TypeTableEntryIdErrorUnion &&4874 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
4557 actual_type->id == TypeTableEntryIdPureError)4875 actual_type->id == TypeTableEntryIdPureError)
4558 {4876 {
4559 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type,4877 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
4560 CastOpPureErrorWrap, false);
4561 cast_instruction->return_knowledge = ReturnKnowledgeKnownError;
4562 return cast_instruction;
4563 }4878 }
45644879
4565 // explicit cast from number literal to another type4880 // explicit cast from number literal to another type
...@@ -5997,33 +6312,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op...@@ -5997,33 +6312,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
5997 zig_unreachable();6312 zig_unreachable();
5998}6313}
59996314
6000static TypeTableEntry *ir_analyze_unwrap_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
6001 IrInstruction *value = un_op_instruction->value->other;
6002 TypeTableEntry *type_entry = value->type_entry;
6003 if (type_entry->id == TypeTableEntryIdInvalid) {
6004 return type_entry;
6005 } else if (type_entry->id == TypeTableEntryIdMaybe) {
6006 if (value->static_value.special != ConstValSpecialRuntime) {
6007 bool depends_on_compile_var = value->static_value.depends_on_compile_var;
6008 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, depends_on_compile_var);
6009 ConstExprValue *child_val = value->static_value.data.x_maybe;
6010 if (!child_val) {
6011 ir_add_error(ira, &un_op_instruction->base,
6012 buf_sprintf("unable to unwrap null"));
6013 return ira->codegen->builtin_types.entry_invalid;
6014 }
6015 *out_val = *child_val;
6016 return type_entry->data.maybe.child_type;
6017 }
6018 ir_build_un_op_from(&ira->new_irb, &un_op_instruction->base, IrUnOpUnwrapMaybe, value);
6019 return type_entry->data.maybe.child_type;
6020 } else {
6021 add_node_error(ira->codegen, un_op_instruction->base.source_node,
6022 buf_sprintf("expected maybe type, found '%s'", buf_ptr(&type_entry->name)));
6023 return ira->codegen->builtin_types.entry_invalid;
6024 }
6025}
6026
6027static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {6315static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
6028 IrInstruction *value = un_op_instruction->value->other;6316 IrInstruction *value = un_op_instruction->value->other;
6029 TypeTableEntry *expr_type = value->type_entry;6317 TypeTableEntry *expr_type = value->type_entry;
...@@ -6099,27 +6387,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -6099,27 +6387,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
6099 return ir_analyze_maybe(ira, un_op_instruction);6387 return ir_analyze_maybe(ira, un_op_instruction);
6100 case IrUnOpError:6388 case IrUnOpError:
6101 return ir_analyze_unary_prefix_op_err(ira, un_op_instruction);6389 return ir_analyze_unary_prefix_op_err(ira, un_op_instruction);
6102 case IrUnOpUnwrapError:
6103 zig_panic("TODO analyze PrefixOpUnwrapError");
6104 //{
6105 // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
6106
6107 // if (type_entry->id == TypeTableEntryIdInvalid) {
6108 // return type_entry;
6109 // } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
6110 // return type_entry->data.error.child_type;
6111 // } else {
6112 // add_node_error(g, *expr_node,
6113 // buf_sprintf("expected error type, found '%s'", buf_ptr(&type_entry->name)));
6114 // return g->builtin_types.entry_invalid;
6115 // }
6116 //}
6117 case IrUnOpUnwrapMaybe:
6118 return ir_analyze_unwrap_maybe(ira, un_op_instruction);
6119 case IrUnOpErrorReturn:
6120 zig_panic("TODO analyze IrUnOpErrorReturn");
6121 case IrUnOpMaybeReturn:
6122 zig_panic("TODO analyze IrUnOpMaybeReturn");
6123 }6390 }
6124 zig_unreachable();6391 zig_unreachable();
6125}6392}
...@@ -6835,6 +7102,7 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,...@@ -6835,6 +7102,7 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
6835 if (type_entry->id == TypeTableEntryIdInvalid)7102 if (type_entry->id == TypeTableEntryIdInvalid)
6836 return type_entry;7103 return type_entry;
68377104
7105 // TODO handle typedefs
6838 if (type_entry->id != TypeTableEntryIdPointer) {7106 if (type_entry->id != TypeTableEntryIdPointer) {
6839 add_node_error(ira->codegen, ptr_type_child_instruction->base.source_node,7107 add_node_error(ira->codegen, ptr_type_child_instruction->base.source_node,
6840 buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name)));7108 buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name)));
...@@ -7243,6 +7511,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,...@@ -7243,6 +7511,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
7243 assert(ptr_type->id == TypeTableEntryIdPointer);7511 assert(ptr_type->id == TypeTableEntryIdPointer);
72447512
7245 TypeTableEntry *type_entry = ptr_type->data.pointer.child_type;7513 TypeTableEntry *type_entry = ptr_type->data.pointer.child_type;
7514 // TODO handle typedef
7246 if (type_entry->id == TypeTableEntryIdInvalid) {7515 if (type_entry->id == TypeTableEntryIdInvalid) {
7247 return ira->codegen->builtin_types.entry_invalid;7516 return ira->codegen->builtin_types.entry_invalid;
7248 } else if (type_entry->id != TypeTableEntryIdMaybe) {7517 } else if (type_entry->id != TypeTableEntryIdMaybe) {
...@@ -7253,9 +7522,12 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,...@@ -7253,9 +7522,12 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
7253 TypeTableEntry *child_type = type_entry->data.maybe.child_type;7522 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
7254 TypeTableEntry *result_type = get_pointer_to_type(ira->codegen, child_type, false);7523 TypeTableEntry *result_type = get_pointer_to_type(ira->codegen, child_type, false);
72557524
7256 if (value->static_value.special != ConstValSpecialRuntime) {7525 if (instr_is_comptime(value)) {
7257 ConstExprValue *maybe_val = value->static_value.data.x_ptr.base_ptr;7526 ConstExprValue *val = ir_resolve_const(ira, value);
7258 assert(value->static_value.data.x_ptr.index == SIZE_MAX);7527 if (!val)
7528 return ira->codegen->builtin_types.entry_invalid;
7529 ConstExprValue *maybe_val = val->data.x_ptr.base_ptr;
7530 assert(val->data.x_ptr.index == SIZE_MAX);
72597531
7260 if (maybe_val->special != ConstValSpecialRuntime) {7532 if (maybe_val->special != ConstValSpecialRuntime) {
7261 if (!maybe_val->data.x_maybe) {7533 if (!maybe_val->data.x_maybe) {
...@@ -8837,6 +9109,161 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst...@@ -8837,6 +9109,161 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst
8837 return ira->codegen->builtin_types.entry_bool;9109 return ira->codegen->builtin_types.entry_bool;
8838}9110}
88399111
9112static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErr *instruction) {
9113 IrInstruction *value = instruction->value->other;
9114 if (value->type_entry->id == TypeTableEntryIdInvalid)
9115 return ira->codegen->builtin_types.entry_invalid;
9116
9117 TypeTableEntry *ptr_type = value->type_entry;
9118
9119 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
9120 assert(ptr_type->id == TypeTableEntryIdPointer);
9121
9122 TypeTableEntry *non_canon_type = ptr_type->data.pointer.child_type;
9123 TypeTableEntry *canon_type = get_underlying_type(non_canon_type);
9124 if (canon_type->id == TypeTableEntryIdInvalid) {
9125 return ira->codegen->builtin_types.entry_invalid;
9126 } else if (canon_type->id == TypeTableEntryIdErrorUnion) {
9127 if (instr_is_comptime(value)) {
9128 ConstExprValue *ptr_val = ir_resolve_const(ira, value);
9129 if (!ptr_val)
9130 return ira->codegen->builtin_types.entry_invalid;
9131 ConstExprValue *err_union_val = ptr_val->data.x_ptr.base_ptr;
9132 assert(ptr_val->data.x_ptr.index == SIZE_MAX);
9133
9134 if (err_union_val->special != ConstValSpecialRuntime) {
9135 bool depends_on_compile_var = ptr_val->depends_on_compile_var || err_union_val->depends_on_compile_var;
9136 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
9137 out_val->data.x_bool = (err_union_val->data.x_err_union.err != nullptr);
9138 return ira->codegen->builtin_types.entry_bool;
9139 }
9140 }
9141
9142 ir_build_test_err_from(&ira->new_irb, &instruction->base, value);
9143 return ira->codegen->builtin_types.entry_bool;
9144 } else {
9145 ir_add_error(ira, value,
9146 buf_sprintf("expected error union type, found '%s'", buf_ptr(&non_canon_type->name)));
9147 // TODO if this is a typedecl, add error note showing the declaration of the type decl
9148 return ira->codegen->builtin_types.entry_invalid;
9149 }
9150}
9151
9152static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
9153 IrInstructionUnwrapErrCode *instruction)
9154{
9155 IrInstruction *value = instruction->value->other;
9156 if (value->type_entry->id == TypeTableEntryIdInvalid)
9157 return ira->codegen->builtin_types.entry_invalid;
9158 TypeTableEntry *ptr_type = value->type_entry;
9159
9160 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
9161 assert(ptr_type->id == TypeTableEntryIdPointer);
9162
9163 TypeTableEntry *non_canon_type = ptr_type->data.pointer.child_type;
9164 TypeTableEntry *canon_type = get_underlying_type(non_canon_type);
9165 if (canon_type->id == TypeTableEntryIdInvalid) {
9166 return ira->codegen->builtin_types.entry_invalid;
9167 } else if (canon_type->id == TypeTableEntryIdErrorUnion) {
9168 if (instr_is_comptime(value)) {
9169 ConstExprValue *ptr_val = ir_resolve_const(ira, value);
9170 if (!ptr_val)
9171 return ira->codegen->builtin_types.entry_invalid;
9172 ConstExprValue *err_union_val = ptr_val->data.x_ptr.base_ptr;
9173 assert(ptr_val->data.x_ptr.index == SIZE_MAX);
9174 if (err_union_val->special != ConstValSpecialRuntime) {
9175 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
9176 assert(err);
9177
9178 bool depends_on_compile_var = ptr_val->depends_on_compile_var || err_union_val->depends_on_compile_var;
9179 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
9180 out_val->data.x_pure_err = err;
9181 return ira->codegen->builtin_types.entry_pure_error;
9182 }
9183 }
9184
9185 ir_build_unwrap_err_code_from(&ira->new_irb, &instruction->base, value);
9186 return ira->codegen->builtin_types.entry_pure_error;
9187 } else {
9188 ir_add_error(ira, value,
9189 buf_sprintf("expected error union type, found '%s'", buf_ptr(&non_canon_type->name)));
9190 // TODO if this is a typedecl, add error note showing the declaration of the type decl
9191 return ira->codegen->builtin_types.entry_invalid;
9192 }
9193}
9194
9195static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
9196 IrInstructionUnwrapErrPayload *instruction)
9197{
9198 IrInstruction *value = instruction->value->other;
9199 if (value->type_entry->id == TypeTableEntryIdInvalid)
9200 return ira->codegen->builtin_types.entry_invalid;
9201 TypeTableEntry *ptr_type = value->type_entry;
9202
9203 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
9204 assert(ptr_type->id == TypeTableEntryIdPointer);
9205
9206 TypeTableEntry *non_canon_type = ptr_type->data.pointer.child_type;
9207 TypeTableEntry *canon_type = get_underlying_type(non_canon_type);
9208 if (canon_type->id == TypeTableEntryIdInvalid) {
9209 return ira->codegen->builtin_types.entry_invalid;
9210 } else if (canon_type->id == TypeTableEntryIdErrorUnion) {
9211 TypeTableEntry *child_type = canon_type->data.error.child_type;
9212 TypeTableEntry *result_type = get_pointer_to_type(ira->codegen, child_type, false);
9213 if (instr_is_comptime(value)) {
9214 ConstExprValue *ptr_val = ir_resolve_const(ira, value);
9215 if (!ptr_val)
9216 return ira->codegen->builtin_types.entry_invalid;
9217 ConstExprValue *err_union_val = ptr_val->data.x_ptr.base_ptr;
9218 assert(ptr_val->data.x_ptr.index == SIZE_MAX);
9219 if (err_union_val->special != ConstValSpecialRuntime) {
9220 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
9221 if (err != nullptr) {
9222 ir_add_error(ira, &instruction->base,
9223 buf_sprintf("unable to unwrap error '%s'", buf_ptr(&err->name)));
9224 return ira->codegen->builtin_types.entry_invalid;
9225 }
9226
9227 bool depends_on_compile_var = ptr_val->depends_on_compile_var || err_union_val->depends_on_compile_var;
9228 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
9229 out_val->data.x_ptr.base_ptr = err_union_val->data.x_err_union.payload;
9230 out_val->data.x_ptr.index = SIZE_MAX;
9231 return result_type;
9232 }
9233 }
9234
9235 ir_build_unwrap_err_payload_from(&ira->new_irb, &instruction->base, value, instruction->safety_check_on);
9236 return result_type;
9237 } else {
9238 ir_add_error(ira, value,
9239 buf_sprintf("expected error union type, found '%s'", buf_ptr(&non_canon_type->name)));
9240 // TODO if this is a typedecl, add error note showing the declaration of the type decl
9241 return ira->codegen->builtin_types.entry_invalid;
9242 }
9243
9244}
9245
9246static TypeTableEntry *ir_analyze_instruction_err_union_type_child(IrAnalyze *ira,
9247 IrInstructionErrUnionTypeChild *instruction)
9248{
9249 IrInstruction *type_value = instruction->type_value->other;
9250 TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
9251 if (type_entry->id == TypeTableEntryIdInvalid)
9252 return type_entry;
9253
9254 // TODO handle typedefs
9255 if (type_entry->id != TypeTableEntryIdErrorUnion) {
9256 add_node_error(ira->codegen, instruction->base.source_node,
9257 buf_sprintf("expected error type, found '%s'", buf_ptr(&type_entry->name)));
9258 return ira->codegen->builtin_types.entry_invalid;
9259 }
9260
9261 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base,
9262 type_value->static_value.depends_on_compile_var);
9263 out_val->data.x_type = type_entry->data.error.child_type;
9264 return ira->codegen->builtin_types.entry_type;
9265}
9266
8840static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {9267static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
8841 switch (instruction->id) {9268 switch (instruction->id) {
8842 case IrInstructionIdInvalid:9269 case IrInstructionIdInvalid:
...@@ -8971,6 +9398,17 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -8971,6 +9398,17 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
8971 return ir_analyze_instruction_alignof(ira, (IrInstructionAlignOf *)instruction);9398 return ir_analyze_instruction_alignof(ira, (IrInstructionAlignOf *)instruction);
8972 case IrInstructionIdOverflowOp:9399 case IrInstructionIdOverflowOp:
8973 return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction);9400 return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction);
9401 case IrInstructionIdTestErr:
9402 return ir_analyze_instruction_test_err(ira, (IrInstructionTestErr *)instruction);
9403 case IrInstructionIdUnwrapErrCode:
9404 return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction);
9405 case IrInstructionIdUnwrapErrPayload:
9406 return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction);
9407 case IrInstructionIdErrUnionTypeChild:
9408 return ir_analyze_instruction_err_union_type_child(ira, (IrInstructionErrUnionTypeChild *)instruction);
9409 case IrInstructionIdMaybeWrap:
9410 case IrInstructionIdErrWrapCode:
9411 case IrInstructionIdErrWrapPayload:
8974 case IrInstructionIdCast:9412 case IrInstructionIdCast:
8975 case IrInstructionIdStructFieldPtr:9413 case IrInstructionIdStructFieldPtr:
8976 case IrInstructionIdEnumFieldPtr:9414 case IrInstructionIdEnumFieldPtr:
...@@ -9122,6 +9560,13 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -9122,6 +9560,13 @@ bool ir_has_side_effects(IrInstruction *instruction) {
9122 case IrInstructionIdAlignOf:9560 case IrInstructionIdAlignOf:
9123 case IrInstructionIdReturnAddress:9561 case IrInstructionIdReturnAddress:
9124 case IrInstructionIdFrameAddress:9562 case IrInstructionIdFrameAddress:
9563 case IrInstructionIdTestErr:
9564 case IrInstructionIdUnwrapErrCode:
9565 case IrInstructionIdUnwrapErrPayload:
9566 case IrInstructionIdErrUnionTypeChild:
9567 case IrInstructionIdMaybeWrap:
9568 case IrInstructionIdErrWrapCode:
9569 case IrInstructionIdErrWrapPayload:
9125 return false;9570 return false;
9126 case IrInstructionIdAsm:9571 case IrInstructionIdAsm:
9127 {9572 {
...@@ -9131,268 +9576,3 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -9131,268 +9576,3 @@ bool ir_has_side_effects(IrInstruction *instruction) {
9131 }9576 }
9132 zig_unreachable();9577 zig_unreachable();
9133}9578}
9134
9135// TODO port over all this commented out code into new IR way of doing things
9136
9137//static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
9138// TypeTableEntry *expected_type, AstNode *node)
9139//{
9140// TypeTableEntry *expected_return_type = get_return_type(context);
9141//
9142// switch (node->data.return_expr.kind) {
9143// case ReturnKindError:
9144// {
9145// TypeTableEntry *expected_err_type;
9146// if (expected_type) {
9147// expected_err_type = get_error_type(g, expected_type);
9148// } else {
9149// expected_err_type = nullptr;
9150// }
9151// TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_err_type,
9152// node->data.return_expr.expr);
9153// if (resolved_type->id == TypeTableEntryIdInvalid) {
9154// return resolved_type;
9155// } else if (resolved_type->id == TypeTableEntryIdErrorUnion) {
9156// if (expected_return_type->id != TypeTableEntryIdErrorUnion &&
9157// expected_return_type->id != TypeTableEntryIdPureError)
9158// {
9159// ErrorMsg *msg = add_node_error(g, node,
9160// buf_sprintf("%%return statement in function with return type '%s'",
9161// buf_ptr(&expected_return_type->name)));
9162// AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
9163// add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
9164// }
9165//
9166// return resolved_type->data.error.child_type;
9167// } else {
9168// add_node_error(g, node->data.return_expr.expr,
9169// buf_sprintf("expected error type, found '%s'", buf_ptr(&resolved_type->name)));
9170// return g->builtin_types.entry_invalid;
9171// }
9172// }
9173// }
9174// zig_unreachable();
9175//}
9176//static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *import,
9177// BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *node)
9178//{
9179// AstNode *op1 = node->data.unwrap_err_expr.op1;
9180// AstNode *op2 = node->data.unwrap_err_expr.op2;
9181// AstNode *var_node = node->data.unwrap_err_expr.symbol;
9182//
9183// TypeTableEntry *lhs_type = analyze_expression(g, import, parent_context, nullptr, op1);
9184// if (lhs_type->id == TypeTableEntryIdInvalid) {
9185// return lhs_type;
9186// } else if (lhs_type->id == TypeTableEntryIdErrorUnion) {
9187// TypeTableEntry *child_type = lhs_type->data.error.child_type;
9188// BlockContext *child_context;
9189// if (var_node) {
9190// child_context = new_block_context(node, parent_context);
9191// var_node->block_context = child_context;
9192// Buf *var_name = var_node->data.symbol_expr.symbol;
9193// node->data.unwrap_err_expr.var = add_local_var(g, var_node, import, child_context, var_name,
9194// g->builtin_types.entry_pure_error, true, nullptr);
9195// } else {
9196// child_context = parent_context;
9197// }
9198//
9199// analyze_expression(g, import, child_context, child_type, op2);
9200// return child_type;
9201// } else {
9202// add_node_error(g, op1,
9203// buf_sprintf("expected error type, found '%s'", buf_ptr(&lhs_type->name)));
9204// return g->builtin_types.entry_invalid;
9205// }
9206//}
9207//
9208//static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {
9209// if (type_entry->id == TypeTableEntryIdMetaType) {
9210// add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type"));
9211// } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
9212// add_node_error(g, first_executing_node(source_node), buf_sprintf("statement ignores error value"));
9213// }
9214//}
9215//
9216//static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type,
9217// AstNode *arg_node)
9218//{
9219// assert(node->type == NodeTypeFieldAccessExpr);
9220//
9221// uint64_t value = node->data.field_access_expr.type_enum_field->value;
9222// LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;
9223// LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false);
9224//
9225// if (enum_type->data.enumeration.gen_field_count == 0) {
9226// return tag_value;
9227// } else {
9228// TypeTableEntry *arg_node_type = nullptr;
9229// LLVMValueRef new_union_val = gen_expr(g, arg_node);
9230// if (arg_node) {
9231// arg_node_type = get_expr_type(arg_node);
9232// } else {
9233// arg_node_type = g->builtin_types.entry_void;
9234// }
9235//
9236// LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr;
9237//
9238// // populate the new tag value
9239// LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
9240// LLVMBuildStore(g->builder, tag_value, tag_field_ptr);
9241//
9242// if (arg_node_type->id != TypeTableEntryIdVoid) {
9243// // populate the union value
9244// TypeTableEntry *union_val_type = get_expr_type(arg_node);
9245// LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
9246// LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
9247// LLVMPointerType(union_val_type->type_ref, 0), "");
9248//
9249// gen_assign_raw(g, arg_node, BinOpTypeAssign, bitcasted_union_field_ptr, new_union_val,
9250// union_val_type, union_val_type);
9251//
9252// }
9253//
9254// return tmp_struct_ptr;
9255// }
9256//}
9257//
9258//static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
9259// assert(node->type == NodeTypeUnwrapErrorExpr);
9260//
9261// AstNode *op1 = node->data.unwrap_err_expr.op1;
9262// AstNode *op2 = node->data.unwrap_err_expr.op2;
9263// VariableTableEntry *var = node->data.unwrap_err_expr.var;
9264//
9265// LLVMValueRef expr_val = gen_expr(g, op1);
9266// TypeTableEntry *expr_type = get_expr_type(op1);
9267// TypeTableEntry *op2_type = get_expr_type(op2);
9268// assert(expr_type->id == TypeTableEntryIdErrorUnion);
9269// TypeTableEntry *child_type = expr_type->data.error.child_type;
9270// LLVMValueRef err_val;
9271// if (handle_is_ptr(expr_type)) {
9272// LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
9273// err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
9274// } else {
9275// err_val = expr_val;
9276// }
9277// LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
9278// LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
9279//
9280// LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
9281// LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
9282// LLVMBasicBlockRef end_block;
9283// bool err_reachable = op2_type->id != TypeTableEntryIdUnreachable;
9284// bool have_end_block = err_reachable && type_has_bits(child_type);
9285// if (have_end_block) {
9286// end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrEnd");
9287// }
9288//
9289// LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
9290//
9291// LLVMPositionBuilderAtEnd(g->builder, err_block);
9292// if (var) {
9293// LLVMBuildStore(g->builder, err_val, var->value_ref);
9294// }
9295// LLVMValueRef err_result = gen_expr(g, op2);
9296// if (have_end_block) {
9297// LLVMBuildBr(g->builder, end_block);
9298// } else if (err_reachable) {
9299// LLVMBuildBr(g->builder, ok_block);
9300// }
9301//
9302// LLVMPositionBuilderAtEnd(g->builder, ok_block);
9303// if (!type_has_bits(child_type)) {
9304// return nullptr;
9305// }
9306// LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
9307// LLVMValueRef child_val = get_handle_value(g, child_val_ptr, child_type);
9308//
9309// if (!have_end_block) {
9310// return child_val;
9311// }
9312//
9313// LLVMBuildBr(g->builder, end_block);
9314//
9315// LLVMPositionBuilderAtEnd(g->builder, end_block);
9316// LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(err_result), "");
9317// LLVMValueRef incoming_values[2] = {child_val, err_result};
9318// LLVMBasicBlockRef incoming_blocks[2] = {ok_block, err_block};
9319// LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
9320// return phi;
9321//}
9322//
9323//static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
9324// assert(node->type == NodeTypeReturnExpr);
9325// AstNode *param_node = node->data.return_expr.expr;
9326// assert(param_node);
9327// LLVMValueRef value = gen_expr(g, param_node);
9328// TypeTableEntry *value_type = get_expr_type(param_node);
9329//
9330// switch (node->data.return_expr.kind) {
9331// case ReturnKindUnconditional:
9332// {
9333// Expr *expr = get_resolved_expr(param_node);
9334// if (expr->const_val.ok) {
9335// if (value_type->id == TypeTableEntryIdErrorUnion) {
9336// if (expr->const_val.data.x_err.err) {
9337// expr->return_knowledge = ReturnKnowledgeKnownError;
9338// } else {
9339// expr->return_knowledge = ReturnKnowledgeKnownNonError;
9340// }
9341// } else if (value_type->id == TypeTableEntryIdMaybe) {
9342// if (expr->const_val.data.x_maybe) {
9343// expr->return_knowledge = ReturnKnowledgeKnownNonNull;
9344// } else {
9345// expr->return_knowledge = ReturnKnowledgeKnownNull;
9346// }
9347// }
9348// }
9349// return gen_return(g, node, value, expr->return_knowledge);
9350// }
9351// case ReturnKindError:
9352// {
9353// assert(value_type->id == TypeTableEntryIdErrorUnion);
9354// TypeTableEntry *child_type = value_type->data.error.child_type;
9355//
9356// LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetReturn");
9357// LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetContinue");
9358//
9359// LLVMValueRef err_val;
9360// if (type_has_bits(child_type)) {
9361// LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
9362// err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
9363// } else {
9364// err_val = value;
9365// }
9366// LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
9367// LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
9368// LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);
9369//
9370// LLVMPositionBuilderAtEnd(g->builder, return_block);
9371// TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
9372// if (return_type->id == TypeTableEntryIdPureError) {
9373// gen_return(g, node, err_val, ReturnKnowledgeKnownError);
9374// } else if (return_type->id == TypeTableEntryIdErrorUnion) {
9375// if (type_has_bits(return_type->data.error.child_type)) {
9376// assert(g->cur_ret_ptr);
9377//
9378// LLVMValueRef tag_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 0, "");
9379// LLVMBuildStore(g->builder, err_val, tag_ptr);
9380// LLVMBuildRetVoid(g->builder);
9381// } else {
9382// gen_return(g, node, err_val, ReturnKnowledgeKnownError);
9383// }
9384// } else {
9385// zig_unreachable();
9386// }
9387//
9388// LLVMPositionBuilderAtEnd(g->builder, continue_block);
9389// if (type_has_bits(child_type)) {
9390// LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
9391// return get_handle_value(g, val_ptr, child_type);
9392// } else {
9393// return nullptr;
9394// }
9395// }
9396// }
9397// zig_unreachable();
9398//}
src/ir_print.cpp+66-8
...@@ -295,14 +295,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {...@@ -295,14 +295,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
295 return "?";295 return "?";
296 case IrUnOpError:296 case IrUnOpError:
297 return "%";297 return "%";
298 case IrUnOpUnwrapError:
299 return "%%";
300 case IrUnOpUnwrapMaybe:
301 return "??";
302 case IrUnOpMaybeReturn:
303 return "?return";
304 case IrUnOpErrorReturn:
305 return "%return";
306 }298 }
307 zig_unreachable();299 zig_unreachable();
308}300}
...@@ -855,6 +847,51 @@ static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruct...@@ -855,6 +847,51 @@ static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruct
855 fprintf(irp->f, ")");847 fprintf(irp->f, ")");
856}848}
857849
850static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
851 fprintf(irp->f, "@testError(");
852 ir_print_other_instruction(irp, instruction->value);
853 fprintf(irp->f, ")");
854}
855
856static void ir_print_err_union_type_child(IrPrint *irp, IrInstructionErrUnionTypeChild *instruction) {
857 fprintf(irp->f, "@errorUnionTypeChild(");
858 ir_print_other_instruction(irp, instruction->type_value);
859 fprintf(irp->f, ")");
860}
861
862static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
863 fprintf(irp->f, "@unwrapErrorCode(");
864 ir_print_other_instruction(irp, instruction->value);
865 fprintf(irp->f, ")");
866}
867
868static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
869 fprintf(irp->f, "@unwrapErrorPayload(");
870 ir_print_other_instruction(irp, instruction->value);
871 fprintf(irp->f, ")");
872 if (!instruction->safety_check_on) {
873 fprintf(irp->f, " // no safety");
874 }
875}
876
877static void ir_print_maybe_wrap(IrPrint *irp, IrInstructionMaybeWrap *instruction) {
878 fprintf(irp->f, "@maybeWrap(");
879 ir_print_other_instruction(irp, instruction->value);
880 fprintf(irp->f, ")");
881}
882
883static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instruction) {
884 fprintf(irp->f, "@errWrapCode(");
885 ir_print_other_instruction(irp, instruction->value);
886 fprintf(irp->f, ")");
887}
888
889static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload *instruction) {
890 fprintf(irp->f, "@errWrapPayload(");
891 ir_print_other_instruction(irp, instruction->value);
892 fprintf(irp->f, ")");
893}
894
858static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {895static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
859 ir_print_prefix(irp, instruction);896 ir_print_prefix(irp, instruction);
860 switch (instruction->id) {897 switch (instruction->id) {
...@@ -1067,6 +1104,27 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1067,6 +1104,27 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1067 case IrInstructionIdOverflowOp:1104 case IrInstructionIdOverflowOp:
1068 ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction);1105 ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction);
1069 break;1106 break;
1107 case IrInstructionIdTestErr:
1108 ir_print_test_err(irp, (IrInstructionTestErr *)instruction);
1109 break;
1110 case IrInstructionIdUnwrapErrCode:
1111 ir_print_unwrap_err_code(irp, (IrInstructionUnwrapErrCode *)instruction);
1112 break;
1113 case IrInstructionIdUnwrapErrPayload:
1114 ir_print_unwrap_err_payload(irp, (IrInstructionUnwrapErrPayload *)instruction);
1115 break;
1116 case IrInstructionIdErrUnionTypeChild:
1117 ir_print_err_union_type_child(irp, (IrInstructionErrUnionTypeChild *)instruction);
1118 break;
1119 case IrInstructionIdMaybeWrap:
1120 ir_print_maybe_wrap(irp, (IrInstructionMaybeWrap *)instruction);
1121 break;
1122 case IrInstructionIdErrWrapCode:
1123 ir_print_err_wrap_code(irp, (IrInstructionErrWrapCode *)instruction);
1124 break;
1125 case IrInstructionIdErrWrapPayload:
1126 ir_print_err_wrap_payload(irp, (IrInstructionErrWrapPayload *)instruction);
1127 break;
1070 }1128 }
1071 fprintf(irp->f, "\n");1129 fprintf(irp->f, "\n");
1072}1130}
test/cases/err_wrapping.zig created+13
...@@ -0,0 +1,13 @@
1pub fn foo() -> %i32 {
2 const x = %return bar();
3 return x + 1
4}
5
6pub fn bar() -> %i32 {
7 return 13;
8}
9
10pub fn baz() -> %i32 {
11 const y = foo() %% 1234;
12 return y + 1;
13}
test/self_hosted2.zig+5
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const case_namespace_fn_call = @import("cases/namespace_fn_call.zig");1const case_namespace_fn_call = @import("cases/namespace_fn_call.zig");
2const case_err_wrapping = @import("cases/err_wrapping.zig");
23
3pub const SYS_write = 1;4pub const SYS_write = 1;
4pub const SYS_exit = 60;5pub const SYS_exit = 60;
...@@ -354,6 +355,9 @@ fn assignToIfVarPtr() {...@@ -354,6 +355,9 @@ fn assignToIfVarPtr() {
354 assert(??maybe_bool == false);355 assert(??maybe_bool == false);
355}356}
356357
358fn errorWrapping() {
359 assert(%%case_err_wrapping.baz() == 15);
360}
357361
358fn assert(ok: bool) {362fn assert(ok: bool) {
359 if (!ok)363 if (!ok)
...@@ -390,6 +394,7 @@ fn runAllTests() {...@@ -390,6 +394,7 @@ fn runAllTests() {
390 overflowIntrinsics();394 overflowIntrinsics();
391 shlWithOverflow();395 shlWithOverflow();
392 assignToIfVarPtr();396 assignToIfVarPtr();
397 errorWrapping();
393}398}
394399
395export nakedcc fn _start() -> unreachable {400export nakedcc fn _start() -> unreachable {