authorgravatar for codroid@gmail.comhryx <codroid@gmail.com> 2019-06-27 22:12:34-07:00
committergravatar for codroid@gmail.comhryx <codroid@gmail.com> 2019-06-27 22:12:34-07:00
log2060c7c39b5c33fd6379a785b9beb921a22d1a6a
tree706903c47f96ea2b3b2e66b2ae62d05acf078f72
parent3e0ff32bd84102e4ea892bfdab6cd20daab83897
parentae72a982242fbd46f389f933c18b036e919093bc
signature Commit is signed but in an unrecognized format.

Merge branch 'master' into translate-c-userland


63 files changed, 6649 insertions(+), 2716 deletions(-)

CMakeLists.txt+12-3
...@@ -389,6 +389,8 @@ set(EMBEDDED_SOFTFLOAT_SOURCES...@@ -389,6 +389,8 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
389 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF32.c"389 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF32.c"
390 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF64.c"390 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF64.c"
391 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c"391 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c"
392 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mulAdd.c"
393 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mulAdd.c"
392 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/softfloat_state.c"394 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/softfloat_state.c"
393 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_f128M.c"395 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_f128M.c"
394 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_f128M.c"396 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_f128M.c"
...@@ -522,6 +524,9 @@ set(ZIG_STD_FILES...@@ -522,6 +524,9 @@ set(ZIG_STD_FILES
522 "hash/siphash.zig"524 "hash/siphash.zig"
523 "hash_map.zig"525 "hash_map.zig"
524 "heap.zig"526 "heap.zig"
527 "heap/logging_allocator.zig"
528 "http.zig"
529 "http/headers.zig"
525 "io.zig"530 "io.zig"
526 "io/c_out_stream.zig"531 "io/c_out_stream.zig"
527 "io/seekable_stream.zig"532 "io/seekable_stream.zig"
...@@ -6653,15 +6658,18 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3")...@@ -6653,15 +6658,18 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3")
6653set(EXE_LDFLAGS " ")6658set(EXE_LDFLAGS " ")
6654if(MSVC)6659if(MSVC)
6655 set(EXE_LDFLAGS "/STACK:16777216")6660 set(EXE_LDFLAGS "/STACK:16777216")
6656elseif(ZIG_STATIC)6661elseif(MINGW)
6662 set(EXE_LDFLAGS "${EXE_LDFLAGS} -Wl,--stack,16777216")
6663endif()
6664
6665if(ZIG_STATIC)
6657 if(APPLE)6666 if(APPLE)
6658 set(EXE_LDFLAGS "-static-libgcc -static-libstdc++")6667 set(EXE_LDFLAGS "-static-libgcc -static-libstdc++")
6659 else()6668 else()
6660 set(EXE_LDFLAGS "-static")6669 set(EXE_LDFLAGS "-static")
6661 endif()6670 endif()
6662else()
6663 set(EXE_LDFLAGS " ")
6664endif()6671endif()
6672
6665if(ZIG_TEST_COVERAGE)6673if(ZIG_TEST_COVERAGE)
6666 set(EXE_CFLAGS "${EXE_CFLAGS} -fprofile-arcs -ftest-coverage")6674 set(EXE_CFLAGS "${EXE_CFLAGS} -fprofile-arcs -ftest-coverage")
6667 set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage")6675 set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage")
...@@ -6729,6 +6737,7 @@ add_custom_command(...@@ -6729,6 +6737,7 @@ add_custom_command(
6729 "-Doutput-dir=${CMAKE_BINARY_DIR}"6737 "-Doutput-dir=${CMAKE_BINARY_DIR}"
6730 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"6738 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
6731 DEPENDS6739 DEPENDS
6740 zig0
6732 "${CMAKE_SOURCE_DIR}/src-self-hosted/dep_tokenizer.zig"6741 "${CMAKE_SOURCE_DIR}/src-self-hosted/dep_tokenizer.zig"
6733 "${CMAKE_SOURCE_DIR}/src-self-hosted/stage1.zig"6742 "${CMAKE_SOURCE_DIR}/src-self-hosted/stage1.zig"
6734 "${CMAKE_SOURCE_DIR}/src-self-hosted/translate_c.zig"6743 "${CMAKE_SOURCE_DIR}/src-self-hosted/translate_c.zig"
build.zig+2-1
...@@ -74,7 +74,8 @@ pub fn build(b: *Builder) !void {...@@ -74,7 +74,8 @@ pub fn build(b: *Builder) !void {
74 const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;74 const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;
75 const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;75 const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;
76 if (!skip_self_hosted) {76 if (!skip_self_hosted) {
77 test_step.dependOn(&exe.step);77 // TODO re-enable this after https://github.com/ziglang/zig/issues/2377
78 //test_step.dependOn(&exe.step);
78 }79 }
79 const verbose_link_exe = b.option(bool, "verbose-link", "Print link command for self hosted compiler") orelse false;80 const verbose_link_exe = b.option(bool, "verbose-link", "Print link command for self hosted compiler") orelse false;
80 exe.setVerboseLink(verbose_link_exe);81 exe.setVerboseLink(verbose_link_exe);
doc/langref.html.in+91-3
...@@ -5096,7 +5096,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {...@@ -5096,7 +5096,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
5096 <p>5096 <p>
5097 For example, if we were to introduce another function to the above snippet:5097 For example, if we were to introduce another function to the above snippet:
5098 </p>5098 </p>
5099 {#code_begin|test_err|values of type 'type' must be comptime known#}5099 {#code_begin|test_err|cannot store runtime value in type 'type'#}
5100fn max(comptime T: type, a: T, b: T) T {5100fn max(comptime T: type, a: T, b: T) T {
5101 return if (a > b) a else b;5101 return if (a > b) a else b;
5102}5102}
...@@ -6259,6 +6259,13 @@ comptime {...@@ -6259,6 +6259,13 @@ comptime {
6259 This function is only valid within function scope.6259 This function is only valid within function scope.
6260 </p>6260 </p>
62616261
6262 {#header_close#}
6263 {#header_open|@mulAdd#}
6264 <pre>{#syntax#}@mulAdd(comptime T: type, a: T, b: T, c: T) T{#endsyntax#}</pre>
6265 <p>
6266 Fused multiply add (for floats), similar to {#syntax#}(a * b) + c{#endsyntax#}, except
6267 only rounds once, and is thus more accurate.
6268 </p>
6262 {#header_close#}6269 {#header_close#}
62636270
6264 {#header_open|@byteSwap#}6271 {#header_open|@byteSwap#}
...@@ -7347,10 +7354,91 @@ test "@setRuntimeSafety" {...@@ -7347,10 +7354,91 @@ test "@setRuntimeSafety" {
7347 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>7354 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>
7348 <p>7355 <p>
7349 Performs the square root of a floating point number. Uses a dedicated hardware instruction7356 Performs the square root of a floating point number. Uses a dedicated hardware instruction
7350 when available. Currently only supports f32 and f64 at runtime. f128 at runtime is TODO.7357 when available. Supports f16, f32, f64, and f128, as well as vectors.
7358 </p>
7359 {#header_close#}
7360 {#header_open|@sin#}
7361 <pre>{#syntax#}@sin(comptime T: type, value: T) T{#endsyntax#}</pre>
7362 <p>
7363 Sine trigometric function on a floating point number. Uses a dedicated hardware instruction
7364 when available. Currently supports f32 and f64.
7351 </p>7365 </p>
7366 {#header_close#}
7367 {#header_open|@cos#}
7368 <pre>{#syntax#}@cos(comptime T: type, value: T) T{#endsyntax#}</pre>
7369 <p>
7370 Cosine trigometric function on a floating point number. Uses a dedicated hardware instruction
7371 when available. Currently supports f32 and f64.
7372 </p>
7373 {#header_close#}
7374 {#header_open|@exp#}
7375 <pre>{#syntax#}@exp(comptime T: type, value: T) T{#endsyntax#}</pre>
7376 <p>
7377 Base-e exponential function on a floating point number. Uses a dedicated hardware instruction
7378 when available. Currently supports f32 and f64.
7379 </p>
7380 {#header_close#}
7381 {#header_open|@exp2#}
7382 <pre>{#syntax#}@exp2(comptime T: type, value: T) T{#endsyntax#}</pre>
7383 <p>
7384 Base-2 exponential function on a floating point number. Uses a dedicated hardware instruction
7385 when available. Currently supports f32 and f64.
7386 </p>
7387 {#header_close#}
7388 {#header_open|@ln#}
7389 <pre>{#syntax#}@ln(comptime T: type, value: T) T{#endsyntax#}</pre>
7390 <p>
7391 Returns the natural logarithm of a floating point number. Uses a dedicated hardware instruction
7392 when available. Currently supports f32 and f64.
7393 </p>
7394 {#header_close#}
7395 {#header_open|@log2#}
7396 <pre>{#syntax#}@log2(comptime T: type, value: T) T{#endsyntax#}</pre>
7397 <p>
7398 Returns the logarithm to the base 2 of a floating point number. Uses a dedicated hardware instruction
7399 when available. Currently supports f32 and f64.
7400 </p>
7401 {#header_close#}
7402 {#header_open|@log10#}
7403 <pre>{#syntax#}@log10(comptime T: type, value: T) T{#endsyntax#}</pre>
7404 <p>
7405 Returns the logarithm to the base 10 of a floating point number. Uses a dedicated hardware instruction
7406 when available. Currently supports f32 and f64.
7407 </p>
7408 {#header_close#}
7409 {#header_open|@fabs#}
7410 <pre>{#syntax#}@fabs(comptime T: type, value: T) T{#endsyntax#}</pre>
7411 <p>
7412 Returns the absolute value of a floating point number. Uses a dedicated hardware instruction
7413 when available. Currently supports f32 and f64.
7414 </p>
7415 {#header_close#}
7416 {#header_open|@floor#}
7417 <pre>{#syntax#}@floor(comptime T: type, value: T) T{#endsyntax#}</pre>
7418 <p>
7419 Returns the largest integral value not greater than the given floating point number. Uses a dedicated hardware instruction
7420 when available. Currently supports f32 and f64.
7421 </p>
7422 {#header_close#}
7423 {#header_open|@ceil#}
7424 <pre>{#syntax#}@ceil(comptime T: type, value: T) T{#endsyntax#}</pre>
7425 <p>
7426 Returns the largest integral value not less than the given floating point number. Uses a dedicated hardware instruction
7427 when available. Currently supports f32 and f64.
7428 </p>
7429 {#header_close#}
7430 {#header_open|@trunc#}
7431 <pre>{#syntax#}@trunc(comptime T: type, value: T) T{#endsyntax#}</pre>
7432 <p>
7433 Rounds the given floating point number to an integer, towards zero. Uses a dedicated hardware instruction
7434 when available. Currently supports f32 and f64.
7435 </p>
7436 {#header_close#}
7437 {#header_open|@round#}
7438 <pre>{#syntax#}@round(comptime T: type, value: T) T{#endsyntax#}</pre>
7352 <p>7439 <p>
7353 This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.7440 Rounds the given floating point number to an integer, away from zero. Uses a dedicated hardware instruction
7441 when available. Currently supports f32 and f64.
7354 </p>7442 </p>
7355 {#header_close#}7443 {#header_close#}
73567444
src-self-hosted/dep_tokenizer.zig+1-1
...@@ -998,7 +998,7 @@ fn printCharValues(out: var, bytes: []const u8) !void {...@@ -998,7 +998,7 @@ fn printCharValues(out: var, bytes: []const u8) !void {
998998
999fn printUnderstandableChar(out: var, char: u8) !void {999fn printUnderstandableChar(out: var, char: u8) !void {
1000 if (!std.ascii.isPrint(char) or char == ' ') {1000 if (!std.ascii.isPrint(char) or char == ' ') {
1001 std.fmt.format(out.context, anyerror, out.output, "\\x{X2}", char) catch {};1001 std.fmt.format(out.context, anyerror, out.output, "\\x{X:2}", char) catch {};
1002 } else {1002 } else {
1003 try out.write("'");1003 try out.write("'");
1004 try out.write([_]u8{printable_char_tab[char]});1004 try out.write([_]u8{printable_char_tab[char]});
src/all_types.hpp+311-98
...@@ -34,12 +34,17 @@ struct CodeGen;...@@ -34,12 +34,17 @@ struct CodeGen;
34struct ConstExprValue;34struct ConstExprValue;
35struct IrInstruction;35struct IrInstruction;
36struct IrInstructionCast;36struct IrInstructionCast;
37struct IrInstructionAllocaGen;
37struct IrBasicBlock;38struct IrBasicBlock;
38struct ScopeDecls;39struct ScopeDecls;
39struct ZigWindowsSDK;40struct ZigWindowsSDK;
40struct Tld;41struct Tld;
41struct TldExport;42struct TldExport;
42struct IrAnalyze;43struct IrAnalyze;
44struct ResultLoc;
45struct ResultLocPeer;
46struct ResultLocPeerParent;
47struct ResultLocBitCast;
4348
44enum X64CABIClass {49enum X64CABIClass {
45 X64CABIClass_Unknown,50 X64CABIClass_Unknown,
...@@ -198,6 +203,9 @@ enum ConstPtrMut {...@@ -198,6 +203,9 @@ enum ConstPtrMut {
198 // The pointer points to memory that is known only at runtime.203 // The pointer points to memory that is known only at runtime.
199 // For example it may point to the initializer value of a variable.204 // For example it may point to the initializer value of a variable.
200 ConstPtrMutRuntimeVar,205 ConstPtrMutRuntimeVar,
206 // The pointer points to memory for which it must be inferred whether the
207 // value is comptime known or not.
208 ConstPtrMutInfer,
201};209};
202210
203struct ConstPtrValue {211struct ConstPtrValue {
...@@ -289,6 +297,7 @@ struct RuntimeHintSlice {...@@ -289,6 +297,7 @@ struct RuntimeHintSlice {
289struct ConstGlobalRefs {297struct ConstGlobalRefs {
290 LLVMValueRef llvm_value;298 LLVMValueRef llvm_value;
291 LLVMValueRef llvm_global;299 LLVMValueRef llvm_global;
300 uint32_t align;
292};301};
293302
294struct ConstExprValue {303struct ConstExprValue {
...@@ -325,6 +334,10 @@ struct ConstExprValue {...@@ -325,6 +334,10 @@ struct ConstExprValue {
325 RuntimeHintPtr rh_ptr;334 RuntimeHintPtr rh_ptr;
326 RuntimeHintSlice rh_slice;335 RuntimeHintSlice rh_slice;
327 } data;336 } data;
337
338 // uncomment these to find bugs. can't leave them uncommented because of a gcc-9 warning
339 //ConstExprValue(const ConstExprValue &other) = delete; // plz zero initialize with {}
340 //ConstExprValue& operator= (const ConstExprValue &other) = delete; // use copy_const_val
328};341};
329342
330enum ReturnKnowledge {343enum ReturnKnowledge {
...@@ -426,7 +439,7 @@ enum NodeType {...@@ -426,7 +439,7 @@ enum NodeType {
426 NodeTypeVariableDeclaration,439 NodeTypeVariableDeclaration,
427 NodeTypeTestDecl,440 NodeTypeTestDecl,
428 NodeTypeBinOpExpr,441 NodeTypeBinOpExpr,
429 NodeTypeUnwrapErrorExpr,442 NodeTypeCatchExpr,
430 NodeTypeFloatLiteral,443 NodeTypeFloatLiteral,
431 NodeTypeIntLiteral,444 NodeTypeIntLiteral,
432 NodeTypeStringLiteral,445 NodeTypeStringLiteral,
...@@ -1097,6 +1110,8 @@ struct ZigPackage {...@@ -1097,6 +1110,8 @@ struct ZigPackage {
10971110
1098 // reminder: hash tables must be initialized before use1111 // reminder: hash tables must be initialized before use
1099 HashMap<Buf *, ZigPackage *, buf_hash, buf_eql_buf> package_table;1112 HashMap<Buf *, ZigPackage *, buf_hash, buf_eql_buf> package_table;
1113
1114 bool added_to_cache;
1100};1115};
11011116
1102// Stuff that only applies to a struct which is the implicit root struct of a file1117// Stuff that only applies to a struct which is the implicit root struct of a file
...@@ -1364,7 +1379,7 @@ struct ZigFn {...@@ -1364,7 +1379,7 @@ struct ZigFn {
1364 AstNode *fn_no_inline_set_node;1379 AstNode *fn_no_inline_set_node;
1365 AstNode *fn_static_eval_set_node;1380 AstNode *fn_static_eval_set_node;
13661381
1367 ZigList<IrInstruction *> alloca_list;1382 ZigList<IrInstructionAllocaGen *> alloca_gen_list;
1368 ZigList<ZigVar *> variable_list;1383 ZigList<ZigVar *> variable_list;
13691384
1370 Buf *section_name;1385 Buf *section_name;
...@@ -1406,6 +1421,7 @@ enum BuiltinFnId {...@@ -1406,6 +1421,7 @@ enum BuiltinFnId {
1406 BuiltinFnIdSubWithOverflow,1421 BuiltinFnIdSubWithOverflow,
1407 BuiltinFnIdMulWithOverflow,1422 BuiltinFnIdMulWithOverflow,
1408 BuiltinFnIdShlWithOverflow,1423 BuiltinFnIdShlWithOverflow,
1424 BuiltinFnIdMulAdd,
1409 BuiltinFnIdCInclude,1425 BuiltinFnIdCInclude,
1410 BuiltinFnIdCDefine,1426 BuiltinFnIdCDefine,
1411 BuiltinFnIdCUndef,1427 BuiltinFnIdCUndef,
...@@ -1433,6 +1449,19 @@ enum BuiltinFnId {...@@ -1433,6 +1449,19 @@ enum BuiltinFnId {
1433 BuiltinFnIdRem,1449 BuiltinFnIdRem,
1434 BuiltinFnIdMod,1450 BuiltinFnIdMod,
1435 BuiltinFnIdSqrt,1451 BuiltinFnIdSqrt,
1452 BuiltinFnIdSin,
1453 BuiltinFnIdCos,
1454 BuiltinFnIdExp,
1455 BuiltinFnIdExp2,
1456 BuiltinFnIdLn,
1457 BuiltinFnIdLog2,
1458 BuiltinFnIdLog10,
1459 BuiltinFnIdFabs,
1460 BuiltinFnIdFloor,
1461 BuiltinFnIdCeil,
1462 BuiltinFnIdTrunc,
1463 BuiltinFnIdNearbyInt,
1464 BuiltinFnIdRound,
1436 BuiltinFnIdTruncate,1465 BuiltinFnIdTruncate,
1437 BuiltinFnIdIntCast,1466 BuiltinFnIdIntCast,
1438 BuiltinFnIdFloatCast,1467 BuiltinFnIdFloatCast,
...@@ -1554,9 +1583,8 @@ enum ZigLLVMFnId {...@@ -1554,9 +1583,8 @@ enum ZigLLVMFnId {
1554 ZigLLVMFnIdClz,1583 ZigLLVMFnIdClz,
1555 ZigLLVMFnIdPopCount,1584 ZigLLVMFnIdPopCount,
1556 ZigLLVMFnIdOverflowArithmetic,1585 ZigLLVMFnIdOverflowArithmetic,
1557 ZigLLVMFnIdFloor,1586 ZigLLVMFnIdFMA,
1558 ZigLLVMFnIdCeil,1587 ZigLLVMFnIdFloatOp,
1559 ZigLLVMFnIdSqrt,
1560 ZigLLVMFnIdBswap,1588 ZigLLVMFnIdBswap,
1561 ZigLLVMFnIdBitReverse,1589 ZigLLVMFnIdBitReverse,
1562};1590};
...@@ -1583,7 +1611,9 @@ struct ZigLLVMFnKey {...@@ -1583,7 +1611,9 @@ struct ZigLLVMFnKey {
1583 uint32_t bit_count;1611 uint32_t bit_count;
1584 } pop_count;1612 } pop_count;
1585 struct {1613 struct {
1614 BuiltinFnId op;
1586 uint32_t bit_count;1615 uint32_t bit_count;
1616 uint32_t vector_len; // 0 means not a vector
1587 } floating;1617 } floating;
1588 struct {1618 struct {
1589 AddSubMul add_sub_mul;1619 AddSubMul add_sub_mul;
...@@ -1984,6 +2014,11 @@ struct ScopeDecls {...@@ -1984,6 +2014,11 @@ struct ScopeDecls {
1984 bool any_imports_failed;2014 bool any_imports_failed;
1985};2015};
19862016
2017enum LVal {
2018 LValNone,
2019 LValPtr,
2020};
2021
1987// This scope comes from a block expression in user code.2022// This scope comes from a block expression in user code.
1988// NodeTypeBlock2023// NodeTypeBlock
1989struct ScopeBlock {2024struct ScopeBlock {
...@@ -1992,12 +2027,14 @@ struct ScopeBlock {...@@ -1992,12 +2027,14 @@ struct ScopeBlock {
1992 Buf *name;2027 Buf *name;
1993 IrBasicBlock *end_block;2028 IrBasicBlock *end_block;
1994 IrInstruction *is_comptime;2029 IrInstruction *is_comptime;
2030 ResultLocPeerParent *peer_parent;
1995 ZigList<IrInstruction *> *incoming_values;2031 ZigList<IrInstruction *> *incoming_values;
1996 ZigList<IrBasicBlock *> *incoming_blocks;2032 ZigList<IrBasicBlock *> *incoming_blocks;
19972033
1998 AstNode *safety_set_node;2034 AstNode *safety_set_node;
1999 AstNode *fast_math_set_node;2035 AstNode *fast_math_set_node;
20002036
2037 LVal lval;
2001 bool safety_off;2038 bool safety_off;
2002 bool fast_math_on;2039 bool fast_math_on;
2003};2040};
...@@ -2041,12 +2078,14 @@ struct ScopeCImport {...@@ -2041,12 +2078,14 @@ struct ScopeCImport {
2041struct ScopeLoop {2078struct ScopeLoop {
2042 Scope base;2079 Scope base;
20432080
2081 LVal lval;
2044 Buf *name;2082 Buf *name;
2045 IrBasicBlock *break_block;2083 IrBasicBlock *break_block;
2046 IrBasicBlock *continue_block;2084 IrBasicBlock *continue_block;
2047 IrInstruction *is_comptime;2085 IrInstruction *is_comptime;
2048 ZigList<IrInstruction *> *incoming_values;2086 ZigList<IrInstruction *> *incoming_values;
2049 ZigList<IrBasicBlock *> *incoming_blocks;2087 ZigList<IrBasicBlock *> *incoming_blocks;
2088 ResultLocPeerParent *peer_parent;
2050};2089};
20512090
2052// This scope blocks certain things from working such as comptime continue2091// This scope blocks certain things from working such as comptime continue
...@@ -2123,6 +2162,8 @@ struct IrBasicBlock {...@@ -2123,6 +2162,8 @@ struct IrBasicBlock {
2123 const char *name_hint;2162 const char *name_hint;
2124 size_t debug_id;2163 size_t debug_id;
2125 size_t ref_count;2164 size_t ref_count;
2165 // index into the basic block list
2166 size_t index;
2126 LLVMBasicBlockRef llvm_block;2167 LLVMBasicBlockRef llvm_block;
2127 LLVMBasicBlockRef llvm_exit_block;2168 LLVMBasicBlockRef llvm_exit_block;
2128 // The instruction that referenced this basic block and caused us to2169 // The instruction that referenced this basic block and caused us to
...@@ -2133,11 +2174,10 @@ struct IrBasicBlock {...@@ -2133,11 +2174,10 @@ struct IrBasicBlock {
2133 // if the branch is comptime. The instruction points to the reason2174 // if the branch is comptime. The instruction points to the reason
2134 // the basic block must be comptime.2175 // the basic block must be comptime.
2135 IrInstruction *must_be_comptime_source_instr;2176 IrInstruction *must_be_comptime_source_instr;
2136};2177 IrInstruction *suspend_instruction_ref;
21372178 bool already_appended;
2138enum LVal {2179 bool suspended;
2139 LValNone,2180 bool in_resume_stack;
2140 LValPtr,
2141};2181};
21422182
2143// These instructions are in transition to having "pass 1" instructions2183// These instructions are in transition to having "pass 1" instructions
...@@ -2170,19 +2210,17 @@ enum IrInstructionId {...@@ -2170,19 +2210,17 @@ enum IrInstructionId {
2170 IrInstructionIdUnionFieldPtr,2210 IrInstructionIdUnionFieldPtr,
2171 IrInstructionIdElemPtr,2211 IrInstructionIdElemPtr,
2172 IrInstructionIdVarPtr,2212 IrInstructionIdVarPtr,
2173 IrInstructionIdCall,2213 IrInstructionIdReturnPtr,
2214 IrInstructionIdCallSrc,
2215 IrInstructionIdCallGen,
2174 IrInstructionIdConst,2216 IrInstructionIdConst,
2175 IrInstructionIdReturn,2217 IrInstructionIdReturn,
2176 IrInstructionIdCast,2218 IrInstructionIdCast,
2177 IrInstructionIdResizeSlice,2219 IrInstructionIdResizeSlice,
2178 IrInstructionIdContainerInitList,2220 IrInstructionIdContainerInitList,
2179 IrInstructionIdContainerInitFields,2221 IrInstructionIdContainerInitFields,
2180 IrInstructionIdStructInit,
2181 IrInstructionIdUnionInit,
2182 IrInstructionIdUnreachable,2222 IrInstructionIdUnreachable,
2183 IrInstructionIdTypeOf,2223 IrInstructionIdTypeOf,
2184 IrInstructionIdToPtrType,
2185 IrInstructionIdPtrTypeChild,
2186 IrInstructionIdSetCold,2224 IrInstructionIdSetCold,
2187 IrInstructionIdSetRuntimeSafety,2225 IrInstructionIdSetRuntimeSafety,
2188 IrInstructionIdSetFloatMode,2226 IrInstructionIdSetFloatMode,
...@@ -2207,6 +2245,7 @@ enum IrInstructionId {...@@ -2207,6 +2245,7 @@ enum IrInstructionId {
2207 IrInstructionIdCDefine,2245 IrInstructionIdCDefine,
2208 IrInstructionIdCUndef,2246 IrInstructionIdCUndef,
2209 IrInstructionIdRef,2247 IrInstructionIdRef,
2248 IrInstructionIdRefGen,
2210 IrInstructionIdCompileErr,2249 IrInstructionIdCompileErr,
2211 IrInstructionIdCompileLog,2250 IrInstructionIdCompileLog,
2212 IrInstructionIdErrName,2251 IrInstructionIdErrName,
...@@ -2225,7 +2264,8 @@ enum IrInstructionId {...@@ -2225,7 +2264,8 @@ enum IrInstructionId {
2225 IrInstructionIdBoolNot,2264 IrInstructionIdBoolNot,
2226 IrInstructionIdMemset,2265 IrInstructionIdMemset,
2227 IrInstructionIdMemcpy,2266 IrInstructionIdMemcpy,
2228 IrInstructionIdSlice,2267 IrInstructionIdSliceSrc,
2268 IrInstructionIdSliceGen,
2229 IrInstructionIdMemberCount,2269 IrInstructionIdMemberCount,
2230 IrInstructionIdMemberType,2270 IrInstructionIdMemberType,
2231 IrInstructionIdMemberName,2271 IrInstructionIdMemberName,
...@@ -2235,7 +2275,10 @@ enum IrInstructionId {...@@ -2235,7 +2275,10 @@ enum IrInstructionId {
2235 IrInstructionIdHandle,2275 IrInstructionIdHandle,
2236 IrInstructionIdAlignOf,2276 IrInstructionIdAlignOf,
2237 IrInstructionIdOverflowOp,2277 IrInstructionIdOverflowOp,
2238 IrInstructionIdTestErr,2278 IrInstructionIdTestErrSrc,
2279 IrInstructionIdTestErrGen,
2280 IrInstructionIdMulAdd,
2281 IrInstructionIdFloatOp,
2239 IrInstructionIdUnwrapErrCode,2282 IrInstructionIdUnwrapErrCode,
2240 IrInstructionIdUnwrapErrPayload,2283 IrInstructionIdUnwrapErrPayload,
2241 IrInstructionIdErrWrapCode,2284 IrInstructionIdErrWrapCode,
...@@ -2244,7 +2287,7 @@ enum IrInstructionId {...@@ -2244,7 +2287,7 @@ enum IrInstructionId {
2244 IrInstructionIdTestComptime,2287 IrInstructionIdTestComptime,
2245 IrInstructionIdPtrCastSrc,2288 IrInstructionIdPtrCastSrc,
2246 IrInstructionIdPtrCastGen,2289 IrInstructionIdPtrCastGen,
2247 IrInstructionIdBitCast,2290 IrInstructionIdBitCastSrc,
2248 IrInstructionIdBitCastGen,2291 IrInstructionIdBitCastGen,
2249 IrInstructionIdWidenOrShorten,2292 IrInstructionIdWidenOrShorten,
2250 IrInstructionIdIntToPtr,2293 IrInstructionIdIntToPtr,
...@@ -2268,6 +2311,10 @@ enum IrInstructionId {...@@ -2268,6 +2311,10 @@ enum IrInstructionId {
2268 IrInstructionIdSetEvalBranchQuota,2311 IrInstructionIdSetEvalBranchQuota,
2269 IrInstructionIdPtrType,2312 IrInstructionIdPtrType,
2270 IrInstructionIdAlignCast,2313 IrInstructionIdAlignCast,
2314 IrInstructionIdImplicitCast,
2315 IrInstructionIdResolveResult,
2316 IrInstructionIdResetResult,
2317 IrInstructionIdResultPtr,
2271 IrInstructionIdOpaqueType,2318 IrInstructionIdOpaqueType,
2272 IrInstructionIdSetAlignStack,2319 IrInstructionIdSetAlignStack,
2273 IrInstructionIdArgType,2320 IrInstructionIdArgType,
...@@ -2296,7 +2343,6 @@ enum IrInstructionId {...@@ -2296,7 +2343,6 @@ enum IrInstructionId {
2296 IrInstructionIdAddImplicitReturnType,2343 IrInstructionIdAddImplicitReturnType,
2297 IrInstructionIdMergeErrRetTraces,2344 IrInstructionIdMergeErrRetTraces,
2298 IrInstructionIdMarkErrRetTracePtr,2345 IrInstructionIdMarkErrRetTracePtr,
2299 IrInstructionIdSqrt,
2300 IrInstructionIdErrSetCast,2346 IrInstructionIdErrSetCast,
2301 IrInstructionIdToBytes,2347 IrInstructionIdToBytes,
2302 IrInstructionIdFromBytes,2348 IrInstructionIdFromBytes,
...@@ -2307,10 +2353,13 @@ enum IrInstructionId {...@@ -2307,10 +2353,13 @@ enum IrInstructionId {
2307 IrInstructionIdAssertNonNull,2353 IrInstructionIdAssertNonNull,
2308 IrInstructionIdHasDecl,2354 IrInstructionIdHasDecl,
2309 IrInstructionIdUndeclaredIdent,2355 IrInstructionIdUndeclaredIdent,
2356 IrInstructionIdAllocaSrc,
2357 IrInstructionIdAllocaGen,
2358 IrInstructionIdEndExpr,
2359 IrInstructionIdPtrOfArrayToSlice,
2310};2360};
23112361
2312struct IrInstruction {2362struct IrInstruction {
2313 IrInstructionId id;
2314 Scope *scope;2363 Scope *scope;
2315 AstNode *source_node;2364 AstNode *source_node;
2316 ConstExprValue value;2365 ConstExprValue value;
...@@ -2324,6 +2373,7 @@ struct IrInstruction {...@@ -2324,6 +2373,7 @@ struct IrInstruction {
2324 // with this child field.2373 // with this child field.
2325 IrInstruction *child;2374 IrInstruction *child;
2326 IrBasicBlock *owner_bb;2375 IrBasicBlock *owner_bb;
2376 IrInstructionId id;
2327 // true if this instruction was generated by zig and not from user code2377 // true if this instruction was generated by zig and not from user code
2328 bool is_gen;2378 bool is_gen;
2329};2379};
...@@ -2334,14 +2384,14 @@ struct IrInstructionDeclVarSrc {...@@ -2334,14 +2384,14 @@ struct IrInstructionDeclVarSrc {
2334 ZigVar *var;2384 ZigVar *var;
2335 IrInstruction *var_type;2385 IrInstruction *var_type;
2336 IrInstruction *align_value;2386 IrInstruction *align_value;
2337 IrInstruction *init_value;2387 IrInstruction *ptr;
2338};2388};
23392389
2340struct IrInstructionDeclVarGen {2390struct IrInstructionDeclVarGen {
2341 IrInstruction base;2391 IrInstruction base;
23422392
2343 ZigVar *var;2393 ZigVar *var;
2344 IrInstruction *init_value;2394 IrInstruction *var_ptr;
2345};2395};
23462396
2347struct IrInstructionCondBr {2397struct IrInstructionCondBr {
...@@ -2351,6 +2401,7 @@ struct IrInstructionCondBr {...@@ -2351,6 +2401,7 @@ struct IrInstructionCondBr {
2351 IrBasicBlock *then_block;2401 IrBasicBlock *then_block;
2352 IrBasicBlock *else_block;2402 IrBasicBlock *else_block;
2353 IrInstruction *is_comptime;2403 IrInstruction *is_comptime;
2404 ResultLoc *result_loc;
2354};2405};
23552406
2356struct IrInstructionBr {2407struct IrInstructionBr {
...@@ -2403,6 +2454,7 @@ struct IrInstructionPhi {...@@ -2403,6 +2454,7 @@ struct IrInstructionPhi {
2403 size_t incoming_count;2454 size_t incoming_count;
2404 IrBasicBlock **incoming_blocks;2455 IrBasicBlock **incoming_blocks;
2405 IrInstruction **incoming_values;2456 IrInstruction **incoming_values;
2457 ResultLocPeerParent *peer_parent;
2406};2458};
24072459
2408enum IrUnOp {2460enum IrUnOp {
...@@ -2418,8 +2470,9 @@ struct IrInstructionUnOp {...@@ -2418,8 +2470,9 @@ struct IrInstructionUnOp {
2418 IrInstruction base;2470 IrInstruction base;
24192471
2420 IrUnOp op_id;2472 IrUnOp op_id;
2421 IrInstruction *value;
2422 LVal lval;2473 LVal lval;
2474 IrInstruction *value;
2475 ResultLoc *result_loc;
2423};2476};
24242477
2425enum IrBinOp {2478enum IrBinOp {
...@@ -2476,7 +2529,7 @@ struct IrInstructionLoadPtrGen {...@@ -2476,7 +2529,7 @@ struct IrInstructionLoadPtrGen {
2476 IrInstruction base;2529 IrInstruction base;
24772530
2478 IrInstruction *ptr;2531 IrInstruction *ptr;
2479 LLVMValueRef tmp_ptr;2532 IrInstruction *result_loc;
2480};2533};
24812534
2482struct IrInstructionStorePtr {2535struct IrInstructionStorePtr {
...@@ -2489,6 +2542,7 @@ struct IrInstructionStorePtr {...@@ -2489,6 +2542,7 @@ struct IrInstructionStorePtr {
2489struct IrInstructionFieldPtr {2542struct IrInstructionFieldPtr {
2490 IrInstruction base;2543 IrInstruction base;
24912544
2545 bool initializing;
2492 IrInstruction *container_ptr;2546 IrInstruction *container_ptr;
2493 Buf *field_name_buffer;2547 Buf *field_name_buffer;
2494 IrInstruction *field_name_expr;2548 IrInstruction *field_name_expr;
...@@ -2505,9 +2559,10 @@ struct IrInstructionStructFieldPtr {...@@ -2505,9 +2559,10 @@ struct IrInstructionStructFieldPtr {
2505struct IrInstructionUnionFieldPtr {2559struct IrInstructionUnionFieldPtr {
2506 IrInstruction base;2560 IrInstruction base;
25072561
2562 bool safety_check_on;
2563 bool initializing;
2508 IrInstruction *union_ptr;2564 IrInstruction *union_ptr;
2509 TypeUnionField *field;2565 TypeUnionField *field;
2510 bool is_const;
2511};2566};
25122567
2513struct IrInstructionElemPtr {2568struct IrInstructionElemPtr {
...@@ -2515,8 +2570,8 @@ struct IrInstructionElemPtr {...@@ -2515,8 +2570,8 @@ struct IrInstructionElemPtr {
25152570
2516 IrInstruction *array_ptr;2571 IrInstruction *array_ptr;
2517 IrInstruction *elem_index;2572 IrInstruction *elem_index;
2573 IrInstruction *init_array_type;
2518 PtrLen ptr_len;2574 PtrLen ptr_len;
2519 bool is_const;
2520 bool safety_check_on;2575 bool safety_check_on;
2521};2576};
25222577
...@@ -2527,14 +2582,21 @@ struct IrInstructionVarPtr {...@@ -2527,14 +2582,21 @@ struct IrInstructionVarPtr {
2527 ScopeFnDef *crossed_fndef_scope;2582 ScopeFnDef *crossed_fndef_scope;
2528};2583};
25292584
2530struct IrInstructionCall {2585// For functions that have a return type for which handle_is_ptr is true, a
2586// result location pointer is the secret first parameter ("sret"). This
2587// instruction returns that pointer.
2588struct IrInstructionReturnPtr {
2589 IrInstruction base;
2590};
2591
2592struct IrInstructionCallSrc {
2531 IrInstruction base;2593 IrInstruction base;
25322594
2533 IrInstruction *fn_ref;2595 IrInstruction *fn_ref;
2534 ZigFn *fn_entry;2596 ZigFn *fn_entry;
2535 size_t arg_count;2597 size_t arg_count;
2536 IrInstruction **args;2598 IrInstruction **args;
2537 LLVMValueRef tmp_ptr;2599 ResultLoc *result_loc;
25382600
2539 IrInstruction *async_allocator;2601 IrInstruction *async_allocator;
2540 IrInstruction *new_stack;2602 IrInstruction *new_stack;
...@@ -2543,6 +2605,21 @@ struct IrInstructionCall {...@@ -2543,6 +2605,21 @@ struct IrInstructionCall {
2543 bool is_comptime;2605 bool is_comptime;
2544};2606};
25452607
2608struct IrInstructionCallGen {
2609 IrInstruction base;
2610
2611 IrInstruction *fn_ref;
2612 ZigFn *fn_entry;
2613 size_t arg_count;
2614 IrInstruction **args;
2615 IrInstruction *result_loc;
2616
2617 IrInstruction *async_allocator;
2618 IrInstruction *new_stack;
2619 FnInline fn_inline;
2620 bool is_async;
2621};
2622
2546struct IrInstructionConst {2623struct IrInstructionConst {
2547 IrInstruction base;2624 IrInstruction base;
2548};2625};
...@@ -2565,7 +2642,6 @@ enum CastOp {...@@ -2565,7 +2642,6 @@ enum CastOp {
2565 CastOpNumLitToConcrete,2642 CastOpNumLitToConcrete,
2566 CastOpErrSet,2643 CastOpErrSet,
2567 CastOpBitCast,2644 CastOpBitCast,
2568 CastOpPtrOfArrayToSlice,
2569};2645};
25702646
2571// TODO get rid of this instruction, replace with instructions for each op code2647// TODO get rid of this instruction, replace with instructions for each op code
...@@ -2575,14 +2651,13 @@ struct IrInstructionCast {...@@ -2575,14 +2651,13 @@ struct IrInstructionCast {
2575 IrInstruction *value;2651 IrInstruction *value;
2576 ZigType *dest_type;2652 ZigType *dest_type;
2577 CastOp cast_op;2653 CastOp cast_op;
2578 LLVMValueRef tmp_ptr;
2579};2654};
25802655
2581struct IrInstructionResizeSlice {2656struct IrInstructionResizeSlice {
2582 IrInstruction base;2657 IrInstruction base;
25832658
2584 IrInstruction *operand;2659 IrInstruction *operand;
2585 LLVMValueRef tmp_ptr;2660 IrInstruction *result_loc;
2586};2661};
25872662
2588struct IrInstructionContainerInitList {2663struct IrInstructionContainerInitList {
...@@ -2591,15 +2666,15 @@ struct IrInstructionContainerInitList {...@@ -2591,15 +2666,15 @@ struct IrInstructionContainerInitList {
2591 IrInstruction *container_type;2666 IrInstruction *container_type;
2592 IrInstruction *elem_type;2667 IrInstruction *elem_type;
2593 size_t item_count;2668 size_t item_count;
2594 IrInstruction **items;2669 IrInstruction **elem_result_loc_list;
2595 LLVMValueRef tmp_ptr;2670 IrInstruction *result_loc;
2596};2671};
25972672
2598struct IrInstructionContainerInitFieldsField {2673struct IrInstructionContainerInitFieldsField {
2599 Buf *name;2674 Buf *name;
2600 IrInstruction *value;
2601 AstNode *source_node;2675 AstNode *source_node;
2602 TypeStructField *type_struct_field;2676 TypeStructField *type_struct_field;
2677 IrInstruction *result_loc;
2603};2678};
26042679
2605struct IrInstructionContainerInitFields {2680struct IrInstructionContainerInitFields {
...@@ -2608,29 +2683,7 @@ struct IrInstructionContainerInitFields {...@@ -2608,29 +2683,7 @@ struct IrInstructionContainerInitFields {
2608 IrInstruction *container_type;2683 IrInstruction *container_type;
2609 size_t field_count;2684 size_t field_count;
2610 IrInstructionContainerInitFieldsField *fields;2685 IrInstructionContainerInitFieldsField *fields;
2611};2686 IrInstruction *result_loc;
2612
2613struct IrInstructionStructInitField {
2614 IrInstruction *value;
2615 TypeStructField *type_struct_field;
2616};
2617
2618struct IrInstructionStructInit {
2619 IrInstruction base;
2620
2621 ZigType *struct_type;
2622 size_t field_count;
2623 IrInstructionStructInitField *fields;
2624 LLVMValueRef tmp_ptr;
2625};
2626
2627struct IrInstructionUnionInit {
2628 IrInstruction base;
2629
2630 ZigType *union_type;
2631 TypeUnionField *field;
2632 IrInstruction *init_value;
2633 LLVMValueRef tmp_ptr;
2634};2687};
26352688
2636struct IrInstructionUnreachable {2689struct IrInstructionUnreachable {
...@@ -2643,18 +2696,6 @@ struct IrInstructionTypeOf {...@@ -2643,18 +2696,6 @@ struct IrInstructionTypeOf {
2643 IrInstruction *value;2696 IrInstruction *value;
2644};2697};
26452698
2646struct IrInstructionToPtrType {
2647 IrInstruction base;
2648
2649 IrInstruction *ptr;
2650};
2651
2652struct IrInstructionPtrTypeChild {
2653 IrInstruction base;
2654
2655 IrInstruction *value;
2656};
2657
2658struct IrInstructionSetCold {2699struct IrInstructionSetCold {
2659 IrInstruction base;2700 IrInstruction base;
26602701
...@@ -2748,8 +2789,9 @@ struct IrInstructionTestNonNull {...@@ -2748,8 +2789,9 @@ struct IrInstructionTestNonNull {
2748struct IrInstructionOptionalUnwrapPtr {2789struct IrInstructionOptionalUnwrapPtr {
2749 IrInstruction base;2790 IrInstruction base;
27502791
2751 IrInstruction *base_ptr;
2752 bool safety_check_on;2792 bool safety_check_on;
2793 bool initializing;
2794 IrInstruction *base_ptr;
2753};2795};
27542796
2755struct IrInstructionCtz {2797struct IrInstructionCtz {
...@@ -2789,11 +2831,17 @@ struct IrInstructionRef {...@@ -2789,11 +2831,17 @@ struct IrInstructionRef {
2789 IrInstruction base;2831 IrInstruction base;
27902832
2791 IrInstruction *value;2833 IrInstruction *value;
2792 LLVMValueRef tmp_ptr;
2793 bool is_const;2834 bool is_const;
2794 bool is_volatile;2835 bool is_volatile;
2795};2836};
27962837
2838struct IrInstructionRefGen {
2839 IrInstruction base;
2840
2841 IrInstruction *operand;
2842 IrInstruction *result_loc;
2843};
2844
2797struct IrInstructionCompileErr {2845struct IrInstructionCompileErr {
2798 IrInstruction base;2846 IrInstruction base;
27992847
...@@ -2845,26 +2893,26 @@ struct IrInstructionEmbedFile {...@@ -2845,26 +2893,26 @@ struct IrInstructionEmbedFile {
2845struct IrInstructionCmpxchgSrc {2893struct IrInstructionCmpxchgSrc {
2846 IrInstruction base;2894 IrInstruction base;
28472895
2896 bool is_weak;
2848 IrInstruction *type_value;2897 IrInstruction *type_value;
2849 IrInstruction *ptr;2898 IrInstruction *ptr;
2850 IrInstruction *cmp_value;2899 IrInstruction *cmp_value;
2851 IrInstruction *new_value;2900 IrInstruction *new_value;
2852 IrInstruction *success_order_value;2901 IrInstruction *success_order_value;
2853 IrInstruction *failure_order_value;2902 IrInstruction *failure_order_value;
28542903 ResultLoc *result_loc;
2855 bool is_weak;
2856};2904};
28572905
2858struct IrInstructionCmpxchgGen {2906struct IrInstructionCmpxchgGen {
2859 IrInstruction base;2907 IrInstruction base;
28602908
2909 bool is_weak;
2910 AtomicOrder success_order;
2911 AtomicOrder failure_order;
2861 IrInstruction *ptr;2912 IrInstruction *ptr;
2862 IrInstruction *cmp_value;2913 IrInstruction *cmp_value;
2863 IrInstruction *new_value;2914 IrInstruction *new_value;
2864 LLVMValueRef tmp_ptr;2915 IrInstruction *result_loc;
2865 AtomicOrder success_order;
2866 AtomicOrder failure_order;
2867 bool is_weak;
2868};2916};
28692917
2870struct IrInstructionFence {2918struct IrInstructionFence {
...@@ -2908,6 +2956,7 @@ struct IrInstructionToBytes {...@@ -2908,6 +2956,7 @@ struct IrInstructionToBytes {
2908 IrInstruction base;2956 IrInstruction base;
29092957
2910 IrInstruction *target;2958 IrInstruction *target;
2959 ResultLoc *result_loc;
2911};2960};
29122961
2913struct IrInstructionFromBytes {2962struct IrInstructionFromBytes {
...@@ -2915,6 +2964,7 @@ struct IrInstructionFromBytes {...@@ -2915,6 +2964,7 @@ struct IrInstructionFromBytes {
29152964
2916 IrInstruction *dest_child_type;2965 IrInstruction *dest_child_type;
2917 IrInstruction *target;2966 IrInstruction *target;
2967 ResultLoc *result_loc;
2918};2968};
29192969
2920struct IrInstructionIntToFloat {2970struct IrInstructionIntToFloat {
...@@ -2973,14 +3023,24 @@ struct IrInstructionMemcpy {...@@ -2973,14 +3023,24 @@ struct IrInstructionMemcpy {
2973 IrInstruction *count;3023 IrInstruction *count;
2974};3024};
29753025
2976struct IrInstructionSlice {3026struct IrInstructionSliceSrc {
2977 IrInstruction base;3027 IrInstruction base;
29783028
3029 bool safety_check_on;
2979 IrInstruction *ptr;3030 IrInstruction *ptr;
2980 IrInstruction *start;3031 IrInstruction *start;
2981 IrInstruction *end;3032 IrInstruction *end;
3033 ResultLoc *result_loc;
3034};
3035
3036struct IrInstructionSliceGen {
3037 IrInstruction base;
3038
2982 bool safety_check_on;3039 bool safety_check_on;
2983 LLVMValueRef tmp_ptr;3040 IrInstruction *ptr;
3041 IrInstruction *start;
3042 IrInstruction *end;
3043 IrInstruction *result_loc;
2984};3044};
29853045
2986struct IrInstructionMemberCount {3046struct IrInstructionMemberCount {
...@@ -3038,6 +3098,15 @@ struct IrInstructionOverflowOp {...@@ -3038,6 +3098,15 @@ struct IrInstructionOverflowOp {
3038 ZigType *result_ptr_type;3098 ZigType *result_ptr_type;
3039};3099};
30403100
3101struct IrInstructionMulAdd {
3102 IrInstruction base;
3103
3104 IrInstruction *type_value;
3105 IrInstruction *op1;
3106 IrInstruction *op2;
3107 IrInstruction *op3;
3108};
3109
3041struct IrInstructionAlignOf {3110struct IrInstructionAlignOf {
3042 IrInstruction base;3111 IrInstruction base;
30433112
...@@ -3045,44 +3114,54 @@ struct IrInstructionAlignOf {...@@ -3045,44 +3114,54 @@ struct IrInstructionAlignOf {
3045};3114};
30463115
3047// returns true if error, returns false if not error3116// returns true if error, returns false if not error
3048struct IrInstructionTestErr {3117struct IrInstructionTestErrSrc {
3049 IrInstruction base;3118 IrInstruction base;
30503119
3051 IrInstruction *value;3120 bool resolve_err_set;
3121 IrInstruction *base_ptr;
3052};3122};
30533123
3054struct IrInstructionUnwrapErrCode {3124struct IrInstructionTestErrGen {
3055 IrInstruction base;3125 IrInstruction base;
30563126
3057 IrInstruction *err_union;3127 IrInstruction *err_union;
3058};3128};
30593129
3130// Takes an error union pointer, returns a pointer to the error code.
3131struct IrInstructionUnwrapErrCode {
3132 IrInstruction base;
3133
3134 bool initializing;
3135 IrInstruction *err_union_ptr;
3136};
3137
3060struct IrInstructionUnwrapErrPayload {3138struct IrInstructionUnwrapErrPayload {
3061 IrInstruction base;3139 IrInstruction base;
30623140
3063 IrInstruction *value;
3064 bool safety_check_on;3141 bool safety_check_on;
3142 bool initializing;
3143 IrInstruction *value;
3065};3144};
30663145
3067struct IrInstructionOptionalWrap {3146struct IrInstructionOptionalWrap {
3068 IrInstruction base;3147 IrInstruction base;
30693148
3070 IrInstruction *value;3149 IrInstruction *operand;
3071 LLVMValueRef tmp_ptr;3150 IrInstruction *result_loc;
3072};3151};
30733152
3074struct IrInstructionErrWrapPayload {3153struct IrInstructionErrWrapPayload {
3075 IrInstruction base;3154 IrInstruction base;
30763155
3077 IrInstruction *value;3156 IrInstruction *operand;
3078 LLVMValueRef tmp_ptr;3157 IrInstruction *result_loc;
3079};3158};
30803159
3081struct IrInstructionErrWrapCode {3160struct IrInstructionErrWrapCode {
3082 IrInstruction base;3161 IrInstruction base;
30833162
3084 IrInstruction *value;3163 IrInstruction *operand;
3085 LLVMValueRef tmp_ptr;3164 IrInstruction *result_loc;
3086};3165};
30873166
3088struct IrInstructionFnProto {3167struct IrInstructionFnProto {
...@@ -3117,18 +3196,17 @@ struct IrInstructionPtrCastGen {...@@ -3117,18 +3196,17 @@ struct IrInstructionPtrCastGen {
3117 bool safety_check_on;3196 bool safety_check_on;
3118};3197};
31193198
3120struct IrInstructionBitCast {3199struct IrInstructionBitCastSrc {
3121 IrInstruction base;3200 IrInstruction base;
31223201
3123 IrInstruction *dest_type;3202 IrInstruction *operand;
3124 IrInstruction *value;3203 ResultLocBitCast *result_loc_bit_cast;
3125};3204};
31263205
3127struct IrInstructionBitCastGen {3206struct IrInstructionBitCastGen {
3128 IrInstruction base;3207 IrInstruction base;
31293208
3130 IrInstruction *operand;3209 IrInstruction *operand;
3131 LLVMValueRef tmp_ptr;
3132};3210};
31333211
3134struct IrInstructionWidenOrShorten {3212struct IrInstructionWidenOrShorten {
...@@ -3204,8 +3282,8 @@ struct IrInstructionTypeName {...@@ -3204,8 +3282,8 @@ struct IrInstructionTypeName {
3204struct IrInstructionDeclRef {3282struct IrInstructionDeclRef {
3205 IrInstruction base;3283 IrInstruction base;
32063284
3207 Tld *tld;
3208 LVal lval;3285 LVal lval;
3286 Tld *tld;
3209};3287};
32103288
3211struct IrInstructionPanic {3289struct IrInstructionPanic {
...@@ -3461,11 +3539,13 @@ struct IrInstructionMarkErrRetTracePtr {...@@ -3461,11 +3539,13 @@ struct IrInstructionMarkErrRetTracePtr {
3461 IrInstruction *err_ret_trace_ptr;3539 IrInstruction *err_ret_trace_ptr;
3462};3540};
34633541
3464struct IrInstructionSqrt {3542// For float ops which take a single argument
3543struct IrInstructionFloatOp {
3465 IrInstruction base;3544 IrInstruction base;
34663545
3546 BuiltinFnId op;
3467 IrInstruction *type;3547 IrInstruction *type;
3468 IrInstruction *op;3548 IrInstruction *op1;
3469};3549};
34703550
3471struct IrInstructionCheckRuntimeScope {3551struct IrInstructionCheckRuntimeScope {
...@@ -3499,7 +3579,7 @@ struct IrInstructionVectorToArray {...@@ -3499,7 +3579,7 @@ struct IrInstructionVectorToArray {
3499 IrInstruction base;3579 IrInstruction base;
35003580
3501 IrInstruction *vector;3581 IrInstruction *vector;
3502 LLVMValueRef tmp_ptr;3582 IrInstruction *result_loc;
3503};3583};
35043584
3505struct IrInstructionAssertZero {3585struct IrInstructionAssertZero {
...@@ -3527,6 +3607,139 @@ struct IrInstructionUndeclaredIdent {...@@ -3527,6 +3607,139 @@ struct IrInstructionUndeclaredIdent {
3527 Buf *name;3607 Buf *name;
3528};3608};
35293609
3610struct IrInstructionAllocaSrc {
3611 IrInstruction base;
3612
3613 IrInstruction *align;
3614 IrInstruction *is_comptime;
3615 const char *name_hint;
3616};
3617
3618struct IrInstructionAllocaGen {
3619 IrInstruction base;
3620
3621 uint32_t align;
3622 const char *name_hint;
3623};
3624
3625struct IrInstructionEndExpr {
3626 IrInstruction base;
3627
3628 IrInstruction *value;
3629 ResultLoc *result_loc;
3630};
3631
3632struct IrInstructionImplicitCast {
3633 IrInstruction base;
3634
3635 IrInstruction *dest_type;
3636 IrInstruction *target;
3637 ResultLoc *result_loc;
3638};
3639
3640// This one is for writing through the result pointer.
3641struct IrInstructionResolveResult {
3642 IrInstruction base;
3643
3644 ResultLoc *result_loc;
3645 IrInstruction *ty;
3646};
3647
3648// This one is when you want to read the value of the result.
3649// You have to give the value in case it is comptime.
3650struct IrInstructionResultPtr {
3651 IrInstruction base;
3652
3653 ResultLoc *result_loc;
3654 IrInstruction *result;
3655};
3656
3657struct IrInstructionResetResult {
3658 IrInstruction base;
3659
3660 ResultLoc *result_loc;
3661};
3662
3663struct IrInstructionPtrOfArrayToSlice {
3664 IrInstruction base;
3665
3666 IrInstruction *operand;
3667 IrInstruction *result_loc;
3668};
3669
3670enum ResultLocId {
3671 ResultLocIdInvalid,
3672 ResultLocIdNone,
3673 ResultLocIdVar,
3674 ResultLocIdReturn,
3675 ResultLocIdPeer,
3676 ResultLocIdPeerParent,
3677 ResultLocIdInstruction,
3678 ResultLocIdBitCast,
3679};
3680
3681// Additions to this struct may need to be handled in
3682// ir_reset_result
3683struct ResultLoc {
3684 ResultLocId id;
3685 bool written;
3686 IrInstruction *resolved_loc; // result ptr
3687 IrInstruction *source_instruction;
3688 IrInstruction *gen_instruction; // value to store to the result loc
3689 ZigType *implicit_elem_type;
3690};
3691
3692struct ResultLocNone {
3693 ResultLoc base;
3694};
3695
3696struct ResultLocVar {
3697 ResultLoc base;
3698
3699 ZigVar *var;
3700};
3701
3702struct ResultLocReturn {
3703 ResultLoc base;
3704};
3705
3706struct IrSuspendPosition {
3707 size_t basic_block_index;
3708 size_t instruction_index;
3709};
3710
3711struct ResultLocPeerParent {
3712 ResultLoc base;
3713
3714 bool skipped;
3715 bool done_resuming;
3716 IrBasicBlock *end_bb;
3717 ResultLoc *parent;
3718 ZigList<ResultLocPeer *> peers;
3719 ZigType *resolved_type;
3720 IrInstruction *is_comptime;
3721};
3722
3723struct ResultLocPeer {
3724 ResultLoc base;
3725
3726 ResultLocPeerParent *parent;
3727 IrBasicBlock *next_bb;
3728 IrSuspendPosition suspend_pos;
3729};
3730
3731// The result location is the source instruction
3732struct ResultLocInstruction {
3733 ResultLoc base;
3734};
3735
3736// The source_instruction is the destination type
3737struct ResultLocBitCast {
3738 ResultLoc base;
3739
3740 ResultLoc *parent;
3741};
3742
3530static const size_t slice_ptr_index = 0;3743static const size_t slice_ptr_index = 0;
3531static const size_t slice_len_index = 1;3744static const size_t slice_len_index = 1;
35323745
...@@ -3574,7 +3787,7 @@ struct FnWalkAttrs {...@@ -3574,7 +3787,7 @@ struct FnWalkAttrs {
35743787
3575struct FnWalkCall {3788struct FnWalkCall {
3576 ZigList<LLVMValueRef> *gen_param_values;3789 ZigList<LLVMValueRef> *gen_param_values;
3577 IrInstructionCall *inst;3790 IrInstructionCallGen *inst;
3578 bool is_var_args;3791 bool is_var_args;
3579};3792};
35803793
src/analyze.cpp+23-24
...@@ -2995,7 +2995,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -2995,7 +2995,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
2995 case NodeTypeBlock:2995 case NodeTypeBlock:
2996 case NodeTypeGroupedExpr:2996 case NodeTypeGroupedExpr:
2997 case NodeTypeBinOpExpr:2997 case NodeTypeBinOpExpr:
2998 case NodeTypeUnwrapErrorExpr:2998 case NodeTypeCatchExpr:
2999 case NodeTypeFnCallExpr:2999 case NodeTypeFnCallExpr:
3000 case NodeTypeArrayAccessExpr:3000 case NodeTypeArrayAccessExpr:
3001 case NodeTypeSliceExpr:3001 case NodeTypeSliceExpr:
...@@ -4181,6 +4181,7 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {...@@ -4181,6 +4181,7 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4181 case ConstPtrMutComptimeConst:4181 case ConstPtrMutComptimeConst:
4182 hash_val += (uint32_t)4214318515;4182 hash_val += (uint32_t)4214318515;
4183 break;4183 break;
4184 case ConstPtrMutInfer:
4184 case ConstPtrMutComptimeVar:4185 case ConstPtrMutComptimeVar:
4185 hash_val += (uint32_t)1103195694;4186 hash_val += (uint32_t)1103195694;
4186 break;4187 break;
...@@ -4511,6 +4512,8 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {...@@ -4511,6 +4512,8 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
4511 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;4512 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
4512 if (type_is_invalid(var_scope->var->var_type))4513 if (type_is_invalid(var_scope->var->var_type))
4513 return false;4514 return false;
4515 if (var_scope->var->const_value->special == ConstValSpecialUndef)
4516 return false;
4514 if (can_mutate_comptime_var_state(var_scope->var->const_value))4517 if (can_mutate_comptime_var_state(var_scope->var->const_value))
4515 return false;4518 return false;
4516 } else if (scope->id == ScopeIdFnDef) {4519 } else if (scope->id == ScopeIdFnDef) {
...@@ -4710,7 +4713,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {...@@ -4710,7 +4713,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
4710void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {4713void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
4711 auto entry = g->string_literals_table.maybe_get(str);4714 auto entry = g->string_literals_table.maybe_get(str);
4712 if (entry != nullptr) {4715 if (entry != nullptr) {
4713 *const_val = *entry->value;4716 memcpy(const_val, entry->value, sizeof(ConstExprValue));
4714 return;4717 return;
4715 }4718 }
47164719
...@@ -4998,12 +5001,9 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {...@@ -4998,12 +5001,9 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
4998 field_val->type = wanted_type->data.structure.fields[i].type_entry;5001 field_val->type = wanted_type->data.structure.fields[i].type_entry;
4999 assert(field_val->type);5002 assert(field_val->type);
5000 init_const_undefined(g, field_val);5003 init_const_undefined(g, field_val);
5001 ConstParent *parent = get_const_val_parent(g, field_val);5004 field_val->parent.id = ConstParentIdStruct;
5002 if (parent != nullptr) {5005 field_val->parent.data.p_struct.struct_val = const_val;
5003 parent->id = ConstParentIdStruct;5006 field_val->parent.data.p_struct.field_index = i;
5004 parent->data.p_struct.struct_val = const_val;
5005 parent->data.p_struct.field_index = i;
5006 }
5007 }5007 }
5008 } else {5008 } else {
5009 const_val->special = ConstValSpecialUndef;5009 const_val->special = ConstValSpecialUndef;
...@@ -5736,12 +5736,13 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {...@@ -5736,12 +5736,13 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
5736 return (uint32_t)(x.data.clz.bit_count) * (uint32_t)2428952817;5736 return (uint32_t)(x.data.clz.bit_count) * (uint32_t)2428952817;
5737 case ZigLLVMFnIdPopCount:5737 case ZigLLVMFnIdPopCount:
5738 return (uint32_t)(x.data.clz.bit_count) * (uint32_t)101195049;5738 return (uint32_t)(x.data.clz.bit_count) * (uint32_t)101195049;
5739 case ZigLLVMFnIdFloor:5739 case ZigLLVMFnIdFloatOp:
5740 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1899859168;5740 return (uint32_t)(x.data.floating.bit_count) * ((uint32_t)x.id + 1025) +
5741 case ZigLLVMFnIdCeil:5741 (uint32_t)(x.data.floating.vector_len) * (((uint32_t)x.id << 5) + 1025) +
5742 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;5742 (uint32_t)(x.data.floating.op) * (uint32_t)43789879;
5743 case ZigLLVMFnIdSqrt:5743 case ZigLLVMFnIdFMA:
5744 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;5744 return (uint32_t)(x.data.floating.bit_count) * ((uint32_t)x.id + 1025) +
5745 (uint32_t)(x.data.floating.vector_len) * (((uint32_t)x.id << 5) + 1025);
5745 case ZigLLVMFnIdBswap:5746 case ZigLLVMFnIdBswap:
5746 return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;5747 return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;
5747 case ZigLLVMFnIdBitReverse:5748 case ZigLLVMFnIdBitReverse:
...@@ -5769,10 +5770,13 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {...@@ -5769,10 +5770,13 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
5769 return a.data.bswap.bit_count == b.data.bswap.bit_count;5770 return a.data.bswap.bit_count == b.data.bswap.bit_count;
5770 case ZigLLVMFnIdBitReverse:5771 case ZigLLVMFnIdBitReverse:
5771 return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;5772 return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;
5772 case ZigLLVMFnIdFloor:5773 case ZigLLVMFnIdFloatOp:
5773 case ZigLLVMFnIdCeil:5774 return a.data.floating.bit_count == b.data.floating.bit_count &&
5774 case ZigLLVMFnIdSqrt:5775 a.data.floating.vector_len == b.data.floating.vector_len &&
5775 return a.data.floating.bit_count == b.data.floating.bit_count;5776 a.data.floating.op == b.data.floating.op;
5777 case ZigLLVMFnIdFMA:
5778 return a.data.floating.bit_count == b.data.floating.bit_count &&
5779 a.data.floating.vector_len == b.data.floating.vector_len;
5776 case ZigLLVMFnIdOverflowArithmetic:5780 case ZigLLVMFnIdOverflowArithmetic:
5777 return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) &&5781 return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) &&
5778 (a.data.overflow_arithmetic.add_sub_mul == b.data.overflow_arithmetic.add_sub_mul) &&5782 (a.data.overflow_arithmetic.add_sub_mul == b.data.overflow_arithmetic.add_sub_mul) &&
...@@ -5839,11 +5843,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {...@@ -5839,11 +5843,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
5839 zig_unreachable();5843 zig_unreachable();
5840}5844}
58415845
5842// Deprecated. Reference the parent field directly.
5843ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
5844 return &value->parent;
5845}
5846
5847static const ZigTypeId all_type_ids[] = {5846static const ZigTypeId all_type_ids[] = {
5848 ZigTypeIdMetaType,5847 ZigTypeIdMetaType,
5849 ZigTypeIdVoid,5848 ZigTypeIdVoid,
...@@ -7277,6 +7276,6 @@ void src_assert(bool ok, AstNode *source_node) {...@@ -7277,6 +7276,6 @@ void src_assert(bool ok, AstNode *source_node) {
7277 buf_ptr(source_node->owner->data.structure.root_struct->path),7276 buf_ptr(source_node->owner->data.structure.root_struct->path),
7278 (unsigned)source_node->line + 1, (unsigned)source_node->column + 1);7277 (unsigned)source_node->line + 1, (unsigned)source_node->column + 1);
7279 }7278 }
7280 const char *msg = "assertion failed";7279 const char *msg = "assertion failed. This is a bug in the Zig compiler.";
7281 stage2_panic(msg, strlen(msg));7280 stage2_panic(msg, strlen(msg));
7282}7281}
src/analyze.hpp-1
...@@ -180,7 +180,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val);...@@ -180,7 +180,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
180ConstExprValue *create_const_vals(size_t count);180ConstExprValue *create_const_vals(size_t count);
181181
182ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);182ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
183ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
184void expand_undef_array(CodeGen *g, ConstExprValue *const_val);183void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
185void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);184void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
186185
src/ast_render.cpp+3-3
...@@ -165,8 +165,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -165,8 +165,8 @@ static const char *node_type_str(NodeType node_type) {
165 return "Parens";165 return "Parens";
166 case NodeTypeBinOpExpr:166 case NodeTypeBinOpExpr:
167 return "BinOpExpr";167 return "BinOpExpr";
168 case NodeTypeUnwrapErrorExpr:168 case NodeTypeCatchExpr:
169 return "UnwrapErrorExpr";169 return "CatchExpr";
170 case NodeTypeFnCallExpr:170 case NodeTypeFnCallExpr:
171 return "FnCallExpr";171 return "FnCallExpr";
172 case NodeTypeArrayAccessExpr:172 case NodeTypeArrayAccessExpr:
...@@ -1107,7 +1107,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -1107,7 +1107,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
1107 fprintf(ar->f, "]");1107 fprintf(ar->f, "]");
1108 break;1108 break;
1109 }1109 }
1110 case NodeTypeUnwrapErrorExpr:1110 case NodeTypeCatchExpr:
1111 {1111 {
1112 render_node_ungrouped(ar, node->data.unwrap_err_expr.op1);1112 render_node_ungrouped(ar, node->data.unwrap_err_expr.op1);
1113 fprintf(ar->f, " catch ");1113 fprintf(ar->f, " catch ");
src/codegen.cpp+364-360
...@@ -180,6 +180,8 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget...@@ -180,6 +180,8 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
180 g->root_package = new_package(".", "", "");180 g->root_package = new_package(".", "", "");
181 }181 }
182182
183 g->root_package->package_table.put(buf_create_from_str("root"), g->root_package);
184
183 g->zig_std_special_dir = buf_alloc();185 g->zig_std_special_dir = buf_alloc();
184 os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);186 os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);
185187
...@@ -691,7 +693,9 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -691,7 +693,9 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
691 is_definition, scope_line, flags, is_optimized, nullptr);693 is_definition, scope_line, flags, is_optimized, nullptr);
692694
693 scope->di_scope = ZigLLVMSubprogramToScope(subprogram);695 scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
694 ZigLLVMFnSetSubprogram(fn_llvm_value(g, fn_table_entry), subprogram);696 if (!g->strip_debug_symbols) {
697 ZigLLVMFnSetSubprogram(fn_llvm_value(g, fn_table_entry), subprogram);
698 }
695 return scope->di_scope;699 return scope->di_scope;
696 }700 }
697 case ScopeIdDecls:701 case ScopeIdDecls:
...@@ -806,32 +810,47 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *operand_type, AddSu...@@ -806,32 +810,47 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *operand_type, AddSu
806 return fn_val;810 return fn_val;
807}811}
808812
809static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn_id) {813static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn_id, BuiltinFnId op) {
810 assert(type_entry->id == ZigTypeIdFloat);814 assert(type_entry->id == ZigTypeIdFloat ||
815 type_entry->id == ZigTypeIdVector);
816
817 bool is_vector = (type_entry->id == ZigTypeIdVector);
818 ZigType *float_type = is_vector ? type_entry->data.vector.elem_type : type_entry;
811819
812 ZigLLVMFnKey key = {};820 ZigLLVMFnKey key = {};
813 key.id = fn_id;821 key.id = fn_id;
814 key.data.floating.bit_count = (uint32_t)type_entry->data.floating.bit_count;822 key.data.floating.bit_count = (uint32_t)float_type->data.floating.bit_count;
823 key.data.floating.vector_len = is_vector ? (uint32_t)type_entry->data.vector.len : 0;
824 key.data.floating.op = op;
815825
816 auto existing_entry = g->llvm_fn_table.maybe_get(key);826 auto existing_entry = g->llvm_fn_table.maybe_get(key);
817 if (existing_entry)827 if (existing_entry)
818 return existing_entry->value;828 return existing_entry->value;
819829
820 const char *name;830 const char *name;
821 if (fn_id == ZigLLVMFnIdFloor) {831 uint32_t num_args;
822 name = "floor";832 if (fn_id == ZigLLVMFnIdFMA) {
823 } else if (fn_id == ZigLLVMFnIdCeil) {833 name = "fma";
824 name = "ceil";834 num_args = 3;
825 } else if (fn_id == ZigLLVMFnIdSqrt) {835 } else if (fn_id == ZigLLVMFnIdFloatOp) {
826 name = "sqrt";836 name = float_op_to_name(op, true);
837 num_args = 1;
827 } else {838 } else {
828 zig_unreachable();839 zig_unreachable();
829 }840 }
830841
831 char fn_name[64];842 char fn_name[64];
832 sprintf(fn_name, "llvm.%s.f%" ZIG_PRI_usize "", name, type_entry->data.floating.bit_count);843 if (is_vector)
844 sprintf(fn_name, "llvm.%s.v%" PRIu32 "f%" PRIu32, name, key.data.floating.vector_len, key.data.floating.bit_count);
845 else
846 sprintf(fn_name, "llvm.%s.f%" PRIu32, name, key.data.floating.bit_count);
833 LLVMTypeRef float_type_ref = get_llvm_type(g, type_entry);847 LLVMTypeRef float_type_ref = get_llvm_type(g, type_entry);
834 LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, &float_type_ref, 1, false);848 LLVMTypeRef return_elem_types[3] = {
849 float_type_ref,
850 float_type_ref,
851 float_type_ref,
852 };
853 LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, return_elem_types, num_args, false);
835 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);854 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
836 assert(LLVMGetIntrinsicID(fn_val));855 assert(LLVMGetIntrinsicID(fn_val));
837856
...@@ -844,9 +863,7 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR...@@ -844,9 +863,7 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR
844{863{
845 LLVMValueRef instruction = LLVMBuildStore(g->builder, value, ptr);864 LLVMValueRef instruction = LLVMBuildStore(g->builder, value, ptr);
846 if (is_volatile) LLVMSetVolatile(instruction, true);865 if (is_volatile) LLVMSetVolatile(instruction, true);
847 if (alignment == 0) {866 if (alignment != 0) {
848 LLVMSetAlignment(instruction, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(value)));
849 } else {
850 LLVMSetAlignment(instruction, alignment);867 LLVMSetAlignment(instruction, alignment);
851 }868 }
852 return instruction;869 return instruction;
...@@ -1324,7 +1341,9 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {...@@ -1324,7 +1341,9 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
1324 LLVMBuildRetVoid(g->builder);1341 LLVMBuildRetVoid(g->builder);
13251342
1326 LLVMPositionBuilderAtEnd(g->builder, prev_block);1343 LLVMPositionBuilderAtEnd(g->builder, prev_block);
1327 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);1344 if (!g->strip_debug_symbols) {
1345 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
1346 }
13281347
1329 g->add_error_return_trace_addr_fn_val = fn_val;1348 g->add_error_return_trace_addr_fn_val = fn_val;
1330 return fn_val;1349 return fn_val;
...@@ -1455,7 +1474,9 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -1455,7 +1474,9 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
1455 LLVMBuildBr(g->builder, loop_block);1474 LLVMBuildBr(g->builder, loop_block);
14561475
1457 LLVMPositionBuilderAtEnd(g->builder, prev_block);1476 LLVMPositionBuilderAtEnd(g->builder, prev_block);
1458 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);1477 if (!g->strip_debug_symbols) {
1478 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
1479 }
14591480
1460 g->merge_err_ret_traces_fn_val = fn_val;1481 g->merge_err_ret_traces_fn_val = fn_val;
1461 return fn_val;1482 return fn_val;
...@@ -1511,7 +1532,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {...@@ -1511,7 +1532,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
1511 LLVMBuildRetVoid(g->builder);1532 LLVMBuildRetVoid(g->builder);
15121533
1513 LLVMPositionBuilderAtEnd(g->builder, prev_block);1534 LLVMPositionBuilderAtEnd(g->builder, prev_block);
1514 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);1535 if (!g->strip_debug_symbols) {
1536 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
1537 }
15151538
1516 g->return_err_fn = fn_val;1539 g->return_err_fn = fn_val;
1517 return fn_val;1540 return fn_val;
...@@ -1639,7 +1662,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {...@@ -1639,7 +1662,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
1639 gen_panic(g, msg_slice, err_ret_trace_arg);1662 gen_panic(g, msg_slice, err_ret_trace_arg);
16401663
1641 LLVMPositionBuilderAtEnd(g->builder, prev_block);1664 LLVMPositionBuilderAtEnd(g->builder, prev_block);
1642 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);1665 if (!g->strip_debug_symbols) {
1666 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
1667 }
16431668
1644 g->safety_crash_err_fn = fn_val;1669 g->safety_crash_err_fn = fn_val;
1645 return fn_val;1670 return fn_val;
...@@ -1989,6 +2014,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty...@@ -1989,6 +2014,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
1989}2014}
19902015
1991static void gen_var_debug_decl(CodeGen *g, ZigVar *var) {2016static void gen_var_debug_decl(CodeGen *g, ZigVar *var) {
2017 if (g->strip_debug_symbols) return;
1992 assert(var->di_loc_var != nullptr);2018 assert(var->di_loc_var != nullptr);
1993 AstNode *source_node = var->decl_node;2019 AstNode *source_node = var->decl_node;
1994 ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc((unsigned)source_node->line + 1,2020 ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc((unsigned)source_node->line + 1,
...@@ -2001,7 +2027,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {...@@ -2001,7 +2027,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
2001 if (!type_has_bits(instruction->value.type))2027 if (!type_has_bits(instruction->value.type))
2002 return nullptr;2028 return nullptr;
2003 if (!instruction->llvm_value) {2029 if (!instruction->llvm_value) {
2004 assert(instruction->value.special != ConstValSpecialRuntime);2030 src_assert(instruction->value.special != ConstValSpecialRuntime, instruction->source_node);
2005 assert(instruction->value.type);2031 assert(instruction->value.type);
2006 render_const_val(g, &instruction->value, "");2032 render_const_val(g, &instruction->value, "");
2007 // we might have to do some pointer casting here due to the way union2033 // we might have to do some pointer casting here due to the way union
...@@ -2010,11 +2036,9 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {...@@ -2010,11 +2036,9 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
2010 render_const_val_global(g, &instruction->value, "");2036 render_const_val_global(g, &instruction->value, "");
2011 ZigType *ptr_type = get_pointer_to_type(g, instruction->value.type, true);2037 ZigType *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
2012 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_global, get_llvm_type(g, ptr_type), "");2038 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_global, get_llvm_type(g, ptr_type), "");
2013 } else if (get_codegen_ptr_type(instruction->value.type) != nullptr) {2039 } else {
2014 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_value,2040 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_value,
2015 get_llvm_type(g, instruction->value.type), "");2041 get_llvm_type(g, instruction->value.type), "");
2016 } else {
2017 instruction->llvm_value = instruction->value.global_refs->llvm_value;
2018 }2042 }
2019 assert(instruction->llvm_value);2043 assert(instruction->llvm_value);
2020 }2044 }
...@@ -2295,7 +2319,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {...@@ -2295,7 +2319,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
2295 return;2319 return;
2296 }2320 }
2297 if (fn_walk->id == FnWalkIdCall) {2321 if (fn_walk->id == FnWalkIdCall) {
2298 IrInstructionCall *instruction = fn_walk->data.call.inst;2322 IrInstructionCallGen *instruction = fn_walk->data.call.inst;
2299 bool is_var_args = fn_walk->data.call.is_var_args;2323 bool is_var_args = fn_walk->data.call.is_var_args;
2300 for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {2324 for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
2301 IrInstruction *param_instruction = instruction->args[call_i];2325 IrInstruction *param_instruction = instruction->args[call_i];
...@@ -2389,17 +2413,33 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut...@@ -2389,17 +2413,33 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
2389}2413}
23902414
2391static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {2415static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
2392 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
2393 ZigType *return_type = return_instruction->value->value.type;
2394
2395 if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {2416 if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
2417 if (return_instruction->value == nullptr) {
2418 LLVMBuildRetVoid(g->builder);
2419 return nullptr;
2420 }
2396 assert(g->cur_ret_ptr);2421 assert(g->cur_ret_ptr);
2422 src_assert(return_instruction->value->value.special != ConstValSpecialRuntime,
2423 return_instruction->base.source_node);
2424 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
2425 ZigType *return_type = return_instruction->value->value.type;
2397 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);2426 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
2398 LLVMBuildRetVoid(g->builder);2427 LLVMBuildRetVoid(g->builder);
2399 } else if (handle_is_ptr(return_type)) {2428 } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync &&
2400 LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");2429 handle_is_ptr(g->cur_fn->type_entry->data.fn.fn_type_id.return_type))
2401 LLVMBuildRet(g->builder, by_val_value);2430 {
2431 if (return_instruction->value == nullptr) {
2432 LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, "");
2433 LLVMBuildRet(g->builder, by_val_value);
2434 } else {
2435 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
2436 LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
2437 LLVMBuildRet(g->builder, by_val_value);
2438 }
2439 } else if (return_instruction->value == nullptr) {
2440 LLVMBuildRetVoid(g->builder);
2402 } else {2441 } else {
2442 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
2403 LLVMBuildRet(g->builder, value);2443 LLVMBuildRet(g->builder, value);
2404 }2444 }
2405 return nullptr;2445 return nullptr;
...@@ -2460,22 +2500,17 @@ static LLVMValueRef gen_overflow_shr_op(CodeGen *g, ZigType *type_entry,...@@ -2460,22 +2500,17 @@ static LLVMValueRef gen_overflow_shr_op(CodeGen *g, ZigType *type_entry,
2460 return result;2500 return result;
2461}2501}
24622502
2463static LLVMValueRef gen_floor(CodeGen *g, LLVMValueRef val, ZigType *type_entry) {2503static LLVMValueRef gen_float_op(CodeGen *g, LLVMValueRef val, ZigType *type_entry, BuiltinFnId op) {
2464 if (type_entry->id == ZigTypeIdInt)2504 if ((op == BuiltinFnIdCeil ||
2505 op == BuiltinFnIdFloor) &&
2506 type_entry->id == ZigTypeIdInt)
2465 return val;2507 return val;
2508 assert(type_entry->id == ZigTypeIdFloat);
24662509
2467 LLVMValueRef floor_fn = get_float_fn(g, type_entry, ZigLLVMFnIdFloor);2510 LLVMValueRef floor_fn = get_float_fn(g, type_entry, ZigLLVMFnIdFloatOp, op);
2468 return LLVMBuildCall(g->builder, floor_fn, &val, 1, "");2511 return LLVMBuildCall(g->builder, floor_fn, &val, 1, "");
2469}2512}
24702513
2471static LLVMValueRef gen_ceil(CodeGen *g, LLVMValueRef val, ZigType *type_entry) {
2472 if (type_entry->id == ZigTypeIdInt)
2473 return val;
2474
2475 LLVMValueRef ceil_fn = get_float_fn(g, type_entry, ZigLLVMFnIdCeil);
2476 return LLVMBuildCall(g->builder, ceil_fn, &val, 1, "");
2477}
2478
2479enum DivKind {2514enum DivKind {
2480 DivKindFloat,2515 DivKindFloat,
2481 DivKindTrunc,2516 DivKindTrunc,
...@@ -2551,7 +2586,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast...@@ -2551,7 +2586,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
2551 return result;2586 return result;
2552 case DivKindExact:2587 case DivKindExact:
2553 if (want_runtime_safety) {2588 if (want_runtime_safety) {
2554 LLVMValueRef floored = gen_floor(g, result, type_entry);2589 LLVMValueRef floored = gen_float_op(g, result, type_entry, BuiltinFnIdFloor);
2555 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk");2590 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk");
2556 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail");2591 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail");
2557 LLVMValueRef ok_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, floored, result, "");2592 LLVMValueRef ok_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, floored, result, "");
...@@ -2573,12 +2608,12 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast...@@ -2573,12 +2608,12 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
2573 LLVMBuildCondBr(g->builder, ltz, ltz_block, gez_block);2608 LLVMBuildCondBr(g->builder, ltz, ltz_block, gez_block);
25742609
2575 LLVMPositionBuilderAtEnd(g->builder, ltz_block);2610 LLVMPositionBuilderAtEnd(g->builder, ltz_block);
2576 LLVMValueRef ceiled = gen_ceil(g, result, type_entry);2611 LLVMValueRef ceiled = gen_float_op(g, result, type_entry, BuiltinFnIdCeil);
2577 LLVMBasicBlockRef ceiled_end_block = LLVMGetInsertBlock(g->builder);2612 LLVMBasicBlockRef ceiled_end_block = LLVMGetInsertBlock(g->builder);
2578 LLVMBuildBr(g->builder, end_block);2613 LLVMBuildBr(g->builder, end_block);
25792614
2580 LLVMPositionBuilderAtEnd(g->builder, gez_block);2615 LLVMPositionBuilderAtEnd(g->builder, gez_block);
2581 LLVMValueRef floored = gen_floor(g, result, type_entry);2616 LLVMValueRef floored = gen_float_op(g, result, type_entry, BuiltinFnIdFloor);
2582 LLVMBasicBlockRef floored_end_block = LLVMGetInsertBlock(g->builder);2617 LLVMBasicBlockRef floored_end_block = LLVMGetInsertBlock(g->builder);
2583 LLVMBuildBr(g->builder, end_block);2618 LLVMBuildBr(g->builder, end_block);
25842619
...@@ -2590,7 +2625,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast...@@ -2590,7 +2625,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast
2590 return phi;2625 return phi;
2591 }2626 }
2592 case DivKindFloor:2627 case DivKindFloor:
2593 return gen_floor(g, result, type_entry);2628 return gen_float_op(g, result, type_entry, BuiltinFnIdFloor);
2594 }2629 }
2595 zig_unreachable();2630 zig_unreachable();
2596 }2631 }
...@@ -2942,7 +2977,7 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,...@@ -2942,7 +2977,7 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
2942 LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);2977 LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
2943 assert(expr_val);2978 assert(expr_val);
29442979
2945 assert(instruction->tmp_ptr);2980 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
2946 assert(wanted_type->id == ZigTypeIdStruct);2981 assert(wanted_type->id == ZigTypeIdStruct);
2947 assert(wanted_type->data.structure.is_slice);2982 assert(wanted_type->data.structure.is_slice);
2948 assert(actual_type->id == ZigTypeIdStruct);2983 assert(actual_type->id == ZigTypeIdStruct);
...@@ -2963,7 +2998,7 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,...@@ -2963,7 +2998,7 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
2963 LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, "");2998 LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, "");
2964 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,2999 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
2965 get_llvm_type(g, wanted_type->data.structure.fields[0].type_entry), "");3000 get_llvm_type(g, wanted_type->data.structure.fields[0].type_entry), "");
2966 LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,3001 LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, result_loc,
2967 (unsigned)wanted_ptr_index, "");3002 (unsigned)wanted_ptr_index, "");
2968 gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);3003 gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
29693004
...@@ -2996,12 +3031,10 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,...@@ -2996,12 +3031,10 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
2996 zig_unreachable();3031 zig_unreachable();
2997 }3032 }
29983033
2999 LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,3034 LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, result_loc, (unsigned)wanted_len_index, "");
3000 (unsigned)wanted_len_index, "");
3001 gen_store_untyped(g, new_len, dest_len_ptr, 0, false);3035 gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
30023036
30033037 return result_loc;
3004 return instruction->tmp_ptr;
3005}3038}
30063039
3007static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,3040static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
...@@ -3071,33 +3104,39 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -3071,33 +3104,39 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
3071 return expr_val;3104 return expr_val;
3072 case CastOpBitCast:3105 case CastOpBitCast:
3073 return LLVMBuildBitCast(g->builder, expr_val, get_llvm_type(g, wanted_type), "");3106 return LLVMBuildBitCast(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
3074 case CastOpPtrOfArrayToSlice: {
3075 assert(cast_instruction->tmp_ptr);
3076 assert(actual_type->id == ZigTypeIdPointer);
3077 ZigType *array_type = actual_type->data.pointer.child_type;
3078 assert(array_type->id == ZigTypeIdArray);
3079
3080 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
3081 slice_ptr_index, "");
3082 LLVMValueRef indices[] = {
3083 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
3084 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
3085 };
3086 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");
3087 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
3088
3089 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
3090 slice_len_index, "");
3091 LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
3092 array_type->data.array.len, false);
3093 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
3094
3095 return cast_instruction->tmp_ptr;
3096 }
3097 }3107 }
3098 zig_unreachable();3108 zig_unreachable();
3099}3109}
31003110
3111static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *executable,
3112 IrInstructionPtrOfArrayToSlice *instruction)
3113{
3114 ZigType *actual_type = instruction->operand->value.type;
3115 LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
3116 assert(expr_val);
3117
3118 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
3119
3120 assert(actual_type->id == ZigTypeIdPointer);
3121 ZigType *array_type = actual_type->data.pointer.child_type;
3122 assert(array_type->id == ZigTypeIdArray);
3123
3124 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_ptr_index, "");
3125 LLVMValueRef indices[] = {
3126 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
3127 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
3128 };
3129 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");
3130 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
3131
3132 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_len_index, "");
3133 LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
3134 array_type->data.array.len, false);
3135 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
3136
3137 return result_loc;
3138}
3139
3101static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,3140static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
3102 IrInstructionPtrCastGen *instruction)3141 IrInstructionPtrCastGen *instruction)
3103{3142{
...@@ -3144,12 +3183,7 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,...@@ -3144,12 +3183,7 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
3144 uint32_t alignment = get_abi_alignment(g, actual_type);3183 uint32_t alignment = get_abi_alignment(g, actual_type);
3145 return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");3184 return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");
3146 } else {3185 } else {
3147 assert(instruction->tmp_ptr != nullptr);3186 zig_unreachable();
3148 LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, actual_type), 0);
3149 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, wanted_ptr_type_ref, "");
3150 uint32_t alignment = get_abi_alignment(g, wanted_type);
3151 gen_store_untyped(g, value, bitcasted_ptr, alignment, false);
3152 return instruction->tmp_ptr;
3153 }3187 }
3154}3188}
31553189
...@@ -3335,31 +3369,13 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI...@@ -3335,31 +3369,13 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
3335 return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, "");3369 return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, "");
3336}3370}
33373371
3338static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,3372static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrInstructionDeclVarGen *instruction) {
3339 IrInstructionDeclVarGen *decl_var_instruction)3373 ZigVar *var = instruction->var;
3340{
3341 ZigVar *var = decl_var_instruction->var;
33423374
3343 if (!type_has_bits(var->var_type))3375 if (!type_has_bits(var->var_type))
3344 return nullptr;3376 return nullptr;
33453377
3346 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)3378 var->value_ref = ir_llvm_value(g, instruction->var_ptr);
3347 return nullptr;
3348
3349 IrInstruction *init_value = decl_var_instruction->init_value;
3350
3351 bool have_init_expr = !value_is_all_undef(&init_value->value);
3352
3353 if (have_init_expr) {
3354 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
3355 PtrLenSingle, var->align_bytes, 0, 0, false);
3356 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
3357 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
3358 } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
3359 uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
3360 gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
3361 }
3362
3363 gen_var_debug_decl(g, var);3379 gen_var_debug_decl(g, var);
3364 return nullptr;3380 return nullptr;
3365}3381}
...@@ -3391,13 +3407,13 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3391,13 +3407,13 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
3391 LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");3407 LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
33923408
3393 if (handle_is_ptr(child_type)) {3409 if (handle_is_ptr(child_type)) {
3394 assert(instruction->tmp_ptr != nullptr);3410 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
3395 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);3411 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
3396 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");3412 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
3397 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,3413 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, result_loc,
3398 LLVMPointerType(same_size_int, 0), "");3414 LLVMPointerType(same_size_int, 0), "");
3399 LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr);3415 LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr);
3400 return instruction->tmp_ptr;3416 return result_loc;
3401 }3417 }
34023418
3403 if (child_type->id == ZigTypeIdFloat) {3419 if (child_type->id == ZigTypeIdFloat) {
...@@ -3575,6 +3591,14 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn...@@ -3575,6 +3591,14 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn
3575 }3591 }
3576}3592}
35773593
3594static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable,
3595 IrInstructionReturnPtr *instruction)
3596{
3597 src_assert(g->cur_ret_ptr != nullptr || !type_has_bits(instruction->base.value.type),
3598 instruction->base.source_node);
3599 return g->cur_ret_ptr;
3600}
3601
3578static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) {3602static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) {
3579 LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr);3603 LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr);
3580 ZigType *array_ptr_type = instruction->array_ptr->value.type;3604 ZigType *array_ptr_type = instruction->array_ptr->value.type;
...@@ -3726,7 +3750,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {...@@ -3726,7 +3750,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {
3726 LLVMAddCallSiteAttribute(call_instr, 1, sret_attr);3750 LLVMAddCallSiteAttribute(call_instr, 1, sret_attr);
3727}3751}
37283752
3729static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {3753static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCallGen *instruction) {
3730 LLVMValueRef fn_val;3754 LLVMValueRef fn_val;
3731 ZigType *fn_type;3755 ZigType *fn_type;
3732 if (instruction->fn_entry) {3756 if (instruction->fn_entry) {
...@@ -3749,8 +3773,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3749,8 +3773,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3749 bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id);3773 bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id);
3750 bool is_var_args = fn_type_id->is_var_args;3774 bool is_var_args = fn_type_id->is_var_args;
3751 ZigList<LLVMValueRef> gen_param_values = {};3775 ZigList<LLVMValueRef> gen_param_values = {};
3776 LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;
3752 if (first_arg_ret) {3777 if (first_arg_ret) {
3753 gen_param_values.append(instruction->tmp_ptr);3778 gen_param_values.append(result_loc);
3754 }3779 }
3755 if (prefix_arg_err_ret_stack) {3780 if (prefix_arg_err_ret_stack) {
3756 gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope));3781 gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope));
...@@ -3758,7 +3783,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3758,7 +3783,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3758 if (instruction->is_async) {3783 if (instruction->is_async) {
3759 gen_param_values.append(ir_llvm_value(g, instruction->async_allocator));3784 gen_param_values.append(ir_llvm_value(g, instruction->async_allocator));
37603785
3761 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");3786 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, "");
3762 gen_param_values.append(err_val_ptr);3787 gen_param_values.append(err_val_ptr);
3763 }3788 }
3764 FnWalk fn_walk = {};3789 FnWalk fn_walk = {};
...@@ -3801,9 +3826,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3801,9 +3826,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
38013826
38023827
3803 if (instruction->is_async) {3828 if (instruction->is_async) {
3804 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");3829 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, "");
3805 LLVMBuildStore(g->builder, result, payload_ptr);3830 LLVMBuildStore(g->builder, result, payload_ptr);
3806 return instruction->tmp_ptr;3831 return result_loc;
3807 }3832 }
38083833
3809 if (src_return_type->id == ZigTypeIdUnreachable) {3834 if (src_return_type->id == ZigTypeIdUnreachable) {
...@@ -3812,11 +3837,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3812,11 +3837,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3812 return nullptr;3837 return nullptr;
3813 } else if (first_arg_ret) {3838 } else if (first_arg_ret) {
3814 set_call_instr_sret(g, result);3839 set_call_instr_sret(g, result);
3815 return instruction->tmp_ptr;3840 return result_loc;
3816 } else if (handle_is_ptr(src_return_type)) {3841 } else if (handle_is_ptr(src_return_type)) {
3817 auto store_instr = LLVMBuildStore(g->builder, result, instruction->tmp_ptr);3842 LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
3818 LLVMSetAlignment(store_instr, LLVMGetAlignment(instruction->tmp_ptr));3843 LLVMSetAlignment(store_instr, LLVMGetAlignment(result_loc));
3819 return instruction->tmp_ptr;3844 return result_loc;
3820 } else {3845 } else {
3821 return result;3846 return result;
3822 }3847 }
...@@ -3825,6 +3850,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3825,6 +3850,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3825static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable,3850static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable,
3826 IrInstructionStructFieldPtr *instruction)3851 IrInstructionStructFieldPtr *instruction)
3827{3852{
3853 if (instruction->base.value.special != ConstValSpecialRuntime)
3854 return nullptr;
3855
3828 LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr);3856 LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr);
3829 // not necessarily a pointer. could be ZigTypeIdStruct3857 // not necessarily a pointer. could be ZigTypeIdStruct
3830 ZigType *struct_ptr_type = instruction->struct_ptr->value.type;3858 ZigType *struct_ptr_type = instruction->struct_ptr->value.type;
...@@ -3846,6 +3874,9 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa...@@ -3846,6 +3874,9 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
3846static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,3874static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,
3847 IrInstructionUnionFieldPtr *instruction)3875 IrInstructionUnionFieldPtr *instruction)
3848{3876{
3877 if (instruction->base.value.special != ConstValSpecialRuntime)
3878 return nullptr;
3879
3849 ZigType *union_ptr_type = instruction->union_ptr->value.type;3880 ZigType *union_ptr_type = instruction->union_ptr->value.type;
3850 assert(union_ptr_type->id == ZigTypeIdPointer);3881 assert(union_ptr_type->id == ZigTypeIdPointer);
3851 ZigType *union_type = union_ptr_type->data.pointer.child_type;3882 ZigType *union_type = union_ptr_type->data.pointer.child_type;
...@@ -3853,8 +3884,20 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab...@@ -3853,8 +3884,20 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
38533884
3854 TypeUnionField *field = instruction->field;3885 TypeUnionField *field = instruction->field;
38553886
3856 if (!type_has_bits(field->type_entry))3887 if (!type_has_bits(field->type_entry)) {
3888 if (union_type->data.unionation.gen_tag_index == SIZE_MAX) {
3889 return nullptr;
3890 }
3891 if (instruction->initializing) {
3892 LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
3893 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
3894 union_type->data.unionation.gen_tag_index, "");
3895 LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
3896 &field->enum_field->value);
3897 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
3898 }
3857 return nullptr;3899 return nullptr;
3900 }
38583901
3859 LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);3902 LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr);
3860 LLVMTypeRef field_type_ref = LLVMPointerType(get_llvm_type(g, field->type_entry), 0);3903 LLVMTypeRef field_type_ref = LLVMPointerType(get_llvm_type(g, field->type_entry), 0);
...@@ -3865,7 +3908,12 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab...@@ -3865,7 +3908,12 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
3865 return bitcasted_union_field_ptr;3908 return bitcasted_union_field_ptr;
3866 }3909 }
38673910
3868 if (ir_want_runtime_safety(g, &instruction->base)) {3911 if (instruction->initializing) {
3912 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
3913 LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
3914 &field->enum_field->value);
3915 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
3916 } else if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) {
3869 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");3917 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
3870 LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, "");3918 LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, "");
38713919
...@@ -4065,14 +4113,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable...@@ -4065,14 +4113,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
4065static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,4113static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
4066 IrInstructionOptionalUnwrapPtr *instruction)4114 IrInstructionOptionalUnwrapPtr *instruction)
4067{4115{
4116 if (instruction->base.value.special != ConstValSpecialRuntime)
4117 return nullptr;
4118
4068 ZigType *ptr_type = instruction->base_ptr->value.type;4119 ZigType *ptr_type = instruction->base_ptr->value.type;
4069 assert(ptr_type->id == ZigTypeIdPointer);4120 assert(ptr_type->id == ZigTypeIdPointer);
4070 ZigType *maybe_type = ptr_type->data.pointer.child_type;4121 ZigType *maybe_type = ptr_type->data.pointer.child_type;
4071 assert(maybe_type->id == ZigTypeIdOptional);4122 assert(maybe_type->id == ZigTypeIdOptional);
4072 ZigType *child_type = maybe_type->data.maybe.child_type;4123 ZigType *child_type = maybe_type->data.maybe.child_type;
4073 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);4124 LLVMValueRef base_ptr = ir_llvm_value(g, instruction->base_ptr);
4074 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {4125 if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) {
4075 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);4126 LLVMValueRef maybe_handle = get_handle_value(g, base_ptr, maybe_type, ptr_type);
4076 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);4127 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
4077 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");4128 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
4078 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");4129 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
...@@ -4088,10 +4139,16 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec...@@ -4088,10 +4139,16 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec
4088 } else {4139 } else {
4089 bool is_scalar = !handle_is_ptr(maybe_type);4140 bool is_scalar = !handle_is_ptr(maybe_type);
4090 if (is_scalar) {4141 if (is_scalar) {
4091 return maybe_ptr;4142 return base_ptr;
4092 } else {4143 } else {
4093 LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);4144 LLVMValueRef optional_struct_ref = get_handle_value(g, base_ptr, maybe_type, ptr_type);
4094 return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, "");4145 if (instruction->initializing) {
4146 LLVMValueRef non_null_bit_ptr = LLVMBuildStructGEP(g->builder, optional_struct_ref,
4147 maybe_null_index, "");
4148 LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false);
4149 gen_store_untyped(g, non_null_bit, non_null_bit_ptr, 0, false);
4150 }
4151 return LLVMBuildStructGEP(g->builder, optional_struct_ref, maybe_child_index, "");
4095 }4152 }
4096 }4153 }
4097}4154}
...@@ -4214,17 +4271,17 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru...@@ -4214,17 +4271,17 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru
4214 return phi;4271 return phi;
4215}4272}
42164273
4217static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRef *instruction) {4274static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRefGen *instruction) {
4218 if (!type_has_bits(instruction->base.value.type)) {4275 if (!type_has_bits(instruction->base.value.type)) {
4219 return nullptr;4276 return nullptr;
4220 }4277 }
4221 LLVMValueRef value = ir_llvm_value(g, instruction->value);4278 LLVMValueRef value = ir_llvm_value(g, instruction->operand);
4222 if (handle_is_ptr(instruction->value->value.type)) {4279 if (handle_is_ptr(instruction->operand->value.type)) {
4223 return value;4280 return value;
4224 } else {4281 } else {
4225 assert(instruction->tmp_ptr);4282 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
4226 gen_store_untyped(g, value, instruction->tmp_ptr, 0, false);4283 gen_store_untyped(g, value, result_loc, 0, false);
4227 return instruction->tmp_ptr;4284 return result_loc;
4228 }4285 }
4229}4286}
42304287
...@@ -4340,7 +4397,9 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {...@@ -4340,7 +4397,9 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
4340 g->cur_fn = prev_cur_fn;4397 g->cur_fn = prev_cur_fn;
4341 g->cur_fn_val = prev_cur_fn_val;4398 g->cur_fn_val = prev_cur_fn_val;
4342 LLVMPositionBuilderAtEnd(g->builder, prev_block);4399 LLVMPositionBuilderAtEnd(g->builder, prev_block);
4343 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);4400 if (!g->strip_debug_symbols) {
4401 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
4402 }
43444403
4345 enum_type->data.enumeration.name_function = fn_val;4404 enum_type->data.enumeration.name_function = fn_val;
4346 return fn_val;4405 return fn_val;
...@@ -4516,28 +4575,28 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn...@@ -4516,28 +4575,28 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
4516 LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val,4575 LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val,
4517 success_order, failure_order, instruction->is_weak);4576 success_order, failure_order, instruction->is_weak);
45184577
4519 ZigType *maybe_type = instruction->base.value.type;4578 ZigType *optional_type = instruction->base.value.type;
4520 assert(maybe_type->id == ZigTypeIdOptional);4579 assert(optional_type->id == ZigTypeIdOptional);
4521 ZigType *child_type = maybe_type->data.maybe.child_type;4580 ZigType *child_type = optional_type->data.maybe.child_type;
45224581
4523 if (!handle_is_ptr(maybe_type)) {4582 if (!handle_is_ptr(optional_type)) {
4524 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");4583 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
4525 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");4584 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
4526 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");4585 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
4527 }4586 }
45284587
4529 assert(instruction->tmp_ptr != nullptr);4588 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
4530 assert(type_has_bits(child_type));4589 assert(type_has_bits(child_type));
45314590
4532 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");4591 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
4533 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");4592 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
4534 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);4593 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
45354594
4536 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");4595 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
4537 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");4596 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
4538 LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");4597 LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, "");
4539 gen_store_untyped(g, nonnull_bit, maybe_ptr, 0, false);4598 gen_store_untyped(g, nonnull_bit, maybe_ptr, 0, false);
4540 return instruction->tmp_ptr;4599 return result_loc;
4541}4600}
45424601
4543static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutable *executable, IrInstructionFence *instruction) {4602static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutable *executable, IrInstructionFence *instruction) {
...@@ -4609,16 +4668,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns...@@ -4609,16 +4668,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
4609 return nullptr;4668 return nullptr;
4610}4669}
46114670
4612static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSlice *instruction) {4671static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSliceGen *instruction) {
4613 assert(instruction->tmp_ptr);
4614
4615 LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr);4672 LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr);
4616 ZigType *array_ptr_type = instruction->ptr->value.type;4673 ZigType *array_ptr_type = instruction->ptr->value.type;
4617 assert(array_ptr_type->id == ZigTypeIdPointer);4674 assert(array_ptr_type->id == ZigTypeIdPointer);
4618 ZigType *array_type = array_ptr_type->data.pointer.child_type;4675 ZigType *array_type = array_ptr_type->data.pointer.child_type;
4619 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);4676 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
46204677
4621 LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;4678 LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
46224679
4623 bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);4680 bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
46244681
...@@ -4636,7 +4693,9 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst...@@ -4636,7 +4693,9 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
4636 end_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false);4693 end_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false);
4637 }4694 }
4638 if (want_runtime_safety) {4695 if (want_runtime_safety) {
4639 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);4696 if (instruction->start->value.special == ConstValSpecialRuntime || instruction->end) {
4697 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
4698 }
4640 if (instruction->end) {4699 if (instruction->end) {
4641 LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,4700 LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
4642 array_type->data.array.len, false);4701 array_type->data.array.len, false);
...@@ -4867,10 +4926,10 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,...@@ -4867,10 +4926,10 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
4867 return overflow_bit;4926 return overflow_bit;
4868}4927}
48694928
4870static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) {4929static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErrGen *instruction) {
4871 ZigType *err_union_type = instruction->value->value.type;4930 ZigType *err_union_type = instruction->err_union->value.type;
4872 ZigType *payload_type = err_union_type->data.error_union.payload_type;4931 ZigType *payload_type = err_union_type->data.error_union.payload_type;
4873 LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value);4932 LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union);
48744933
4875 LLVMValueRef err_val;4934 LLVMValueRef err_val;
4876 if (type_has_bits(payload_type)) {4935 if (type_has_bits(payload_type)) {
...@@ -4887,25 +4946,30 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI...@@ -4887,25 +4946,30 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
4887static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,4946static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
4888 IrInstructionUnwrapErrCode *instruction)4947 IrInstructionUnwrapErrCode *instruction)
4889{4948{
4890 ZigType *ptr_type = instruction->err_union->value.type;4949 if (instruction->base.value.special != ConstValSpecialRuntime)
4950 return nullptr;
4951
4952 ZigType *ptr_type = instruction->err_union_ptr->value.type;
4891 assert(ptr_type->id == ZigTypeIdPointer);4953 assert(ptr_type->id == ZigTypeIdPointer);
4892 ZigType *err_union_type = ptr_type->data.pointer.child_type;4954 ZigType *err_union_type = ptr_type->data.pointer.child_type;
4893 ZigType *payload_type = err_union_type->data.error_union.payload_type;4955 ZigType *payload_type = err_union_type->data.error_union.payload_type;
4894 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union);4956 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union_ptr);
4895 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);4957 if (!type_has_bits(payload_type)) {
48964958 return err_union_ptr;
4897 if (type_has_bits(payload_type)) {
4898 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
4899 return gen_load_untyped(g, err_val_ptr, 0, false, "");
4900 } else {4959 } else {
4901 return err_union_handle;4960 // TODO assign undef to the payload
4961 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
4962 return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
4902 }4963 }
4903}4964}
49044965
4905static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,4966static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
4906 IrInstructionUnwrapErrPayload *instruction)4967 IrInstructionUnwrapErrPayload *instruction)
4907{4968{
4908 bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&4969 if (instruction->base.value.special != ConstValSpecialRuntime)
4970 return nullptr;
4971
4972 bool want_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base) &&
4909 g->errors_by_index.length > 1;4973 g->errors_by_index.length > 1;
4910 if (!want_safety && !type_has_bits(instruction->base.value.type))4974 if (!want_safety && !type_has_bits(instruction->base.value.type))
4911 return nullptr;4975 return nullptr;
...@@ -4941,13 +5005,18 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu...@@ -4941,13 +5005,18 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
4941 }5005 }
49425006
4943 if (type_has_bits(payload_type)) {5007 if (type_has_bits(payload_type)) {
5008 if (instruction->initializing) {
5009 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
5010 LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
5011 gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);
5012 }
4944 return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, "");5013 return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, "");
4945 } else {5014 } else {
4946 return nullptr;5015 return nullptr;
4947 }5016 }
4948}5017}
49495018
4950static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, IrInstructionOptionalWrap *instruction) {5019static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutable *executable, IrInstructionOptionalWrap *instruction) {
4951 ZigType *wanted_type = instruction->base.value.type;5020 ZigType *wanted_type = instruction->base.value.type;
49525021
4953 assert(wanted_type->id == ZigTypeIdOptional);5022 assert(wanted_type->id == ZigTypeIdOptional);
...@@ -4955,23 +5024,32 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I...@@ -4955,23 +5024,32 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
4955 ZigType *child_type = wanted_type->data.maybe.child_type;5024 ZigType *child_type = wanted_type->data.maybe.child_type;
49565025
4957 if (!type_has_bits(child_type)) {5026 if (!type_has_bits(child_type)) {
4958 return LLVMConstInt(LLVMInt1Type(), 1, false);5027 LLVMValueRef result = LLVMConstAllOnes(LLVMInt1Type());
5028 if (instruction->result_loc != nullptr) {
5029 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
5030 gen_store_untyped(g, result, result_loc, 0, false);
5031 }
5032 return result;
4959 }5033 }
49605034
4961 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);5035 LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
4962 if (!handle_is_ptr(wanted_type)) {5036 if (!handle_is_ptr(wanted_type)) {
5037 if (instruction->result_loc != nullptr) {
5038 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
5039 gen_store_untyped(g, payload_val, result_loc, 0, false);
5040 }
4963 return payload_val;5041 return payload_val;
4964 }5042 }
49655043
4966 assert(instruction->tmp_ptr);5044 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
49675045
4968 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");5046 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
4969 // child_type and instruction->value->value.type may differ by constness5047 // child_type and instruction->value->value.type may differ by constness
4970 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);5048 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
4971 LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");5049 LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, "");
4972 gen_store_untyped(g, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr, 0, false);5050 gen_store_untyped(g, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr, 0, false);
49735051
4974 return instruction->tmp_ptr;5052 return result_loc;
4975}5053}
49765054
4977static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapCode *instruction) {5055static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapCode *instruction) {
...@@ -4979,20 +5057,19 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable...@@ -4979,20 +5057,19 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable
49795057
4980 assert(wanted_type->id == ZigTypeIdErrorUnion);5058 assert(wanted_type->id == ZigTypeIdErrorUnion);
49815059
4982 ZigType *payload_type = wanted_type->data.error_union.payload_type;5060 LLVMValueRef err_val = ir_llvm_value(g, instruction->operand);
4983 ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
4984
4985 LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
49865061
4987 if (!type_has_bits(payload_type) || !type_has_bits(err_set_type))5062 if (!handle_is_ptr(wanted_type))
4988 return err_val;5063 return err_val;
49895064
4990 assert(instruction->tmp_ptr);5065 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
49915066
4992 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");5067 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, "");
4993 gen_store_untyped(g, err_val, err_tag_ptr, 0, false);5068 gen_store_untyped(g, err_val, err_tag_ptr, 0, false);
49945069
4995 return instruction->tmp_ptr;5070 // TODO store undef to the payload
5071
5072 return result_loc;
4996}5073}
49975074
4998static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapPayload *instruction) {5075static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapPayload *instruction) {
...@@ -5004,7 +5081,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa...@@ -5004,7 +5081,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
5004 ZigType *err_set_type = wanted_type->data.error_union.err_set_type;5081 ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
50055082
5006 if (!type_has_bits(err_set_type)) {5083 if (!type_has_bits(err_set_type)) {
5007 return ir_llvm_value(g, instruction->value);5084 return ir_llvm_value(g, instruction->operand);
5008 }5085 }
50095086
5010 LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));5087 LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type));
...@@ -5012,17 +5089,18 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa...@@ -5012,17 +5089,18 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
5012 if (!type_has_bits(payload_type))5089 if (!type_has_bits(payload_type))
5013 return ok_err_val;5090 return ok_err_val;
50145091
5015 assert(instruction->tmp_ptr);
50165092
5017 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);5093 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
50185094
5019 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");5095 LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand);
5096
5097 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, "");
5020 gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);5098 gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false);
50215099
5022 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");5100 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, "");
5023 gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val);5101 gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val);
50245102
5025 return instruction->tmp_ptr;5103 return result_loc;
5026}5104}
50275105
5028static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {5106static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {
...@@ -5043,90 +5121,6 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir...@@ -5043,90 +5121,6 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
5043 return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);5121 return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
5044}5122}
50455123
5046static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {
5047 for (size_t i = 0; i < instruction->field_count; i += 1) {
5048 IrInstructionStructInitField *field = &instruction->fields[i];
5049 TypeStructField *type_struct_field = field->type_struct_field;
5050 if (!type_has_bits(type_struct_field->type_entry))
5051 continue;
5052
5053 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
5054 (unsigned)type_struct_field->gen_index, "");
5055 LLVMValueRef value = ir_llvm_value(g, field->value);
5056
5057 uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry);
5058 uint32_t host_int_bytes = get_host_int_bytes(g, instruction->struct_type, type_struct_field);
5059
5060 ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
5061 false, false, PtrLenSingle, field_align_bytes,
5062 (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes, false);
5063
5064 gen_assign_raw(g, field_ptr, ptr_type, value);
5065 }
5066 return instruction->tmp_ptr;
5067}
5068
5069static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, IrInstructionUnionInit *instruction) {
5070 TypeUnionField *type_union_field = instruction->field;
5071
5072 if (!type_has_bits(type_union_field->type_entry))
5073 return nullptr;
5074
5075 uint32_t field_align_bytes = get_abi_alignment(g, type_union_field->type_entry);
5076 ZigType *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,
5077 false, false, PtrLenSingle, field_align_bytes,
5078 0, 0, false);
5079
5080 LLVMValueRef uncasted_union_ptr;
5081 // Even if safety is off in this block, if the union type has the safety field, we have to populate it
5082 // correctly. Otherwise safety code somewhere other than here could fail.
5083 ZigType *union_type = instruction->union_type;
5084 if (union_type->data.unionation.gen_tag_index != SIZE_MAX) {
5085 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
5086 union_type->data.unionation.gen_tag_index, "");
5087
5088 LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type),
5089 &type_union_field->enum_field->value);
5090 gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
5091
5092 uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
5093 (unsigned)union_type->data.unionation.gen_union_index, "");
5094 } else {
5095 uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, (unsigned)0, "");
5096 }
5097
5098 LLVMValueRef field_ptr = LLVMBuildBitCast(g->builder, uncasted_union_ptr, get_llvm_type(g, ptr_type), "");
5099 LLVMValueRef value = ir_llvm_value(g, instruction->init_value);
5100
5101 gen_assign_raw(g, field_ptr, ptr_type, value);
5102
5103 return instruction->tmp_ptr;
5104}
5105
5106static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *executable,
5107 IrInstructionContainerInitList *instruction)
5108{
5109 ZigType *array_type = instruction->base.value.type;
5110 assert(array_type->id == ZigTypeIdArray);
5111 LLVMValueRef tmp_array_ptr = instruction->tmp_ptr;
5112 assert(tmp_array_ptr);
5113
5114 size_t field_count = instruction->item_count;
5115
5116 ZigType *child_type = array_type->data.array.child_type;
5117 for (size_t i = 0; i < field_count; i += 1) {
5118 LLVMValueRef elem_val = ir_llvm_value(g, instruction->items[i]);
5119 LLVMValueRef indices[] = {
5120 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
5121 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, i, false),
5122 };
5123 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
5124 gen_assign_raw(g, elem_ptr, get_pointer_to_type(g, child_type, false), elem_val);
5125 }
5126
5127 return tmp_array_ptr;
5128}
5129
5130static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {5124static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {
5131 gen_panic(g, ir_llvm_value(g, instruction->msg), get_cur_err_ret_trace_val(g, instruction->base.scope));5125 gen_panic(g, ir_llvm_value(g, instruction->msg), get_cur_err_ret_trace_val(g, instruction->base.scope));
5132 return nullptr;5126 return nullptr;
...@@ -5343,7 +5337,9 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f...@@ -5343,7 +5337,9 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f
5343 g->cur_fn = prev_cur_fn;5337 g->cur_fn = prev_cur_fn;
5344 g->cur_fn_val = prev_cur_fn_val;5338 g->cur_fn_val = prev_cur_fn_val;
5345 LLVMPositionBuilderAtEnd(g->builder, prev_block);5339 LLVMPositionBuilderAtEnd(g->builder, prev_block);
5346 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);5340 if (!g->strip_debug_symbols) {
5341 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
5342 }
53475343
5348 g->coro_alloc_helper_fn_val = fn_val;5344 g->coro_alloc_helper_fn_val = fn_val;
5349 return fn_val;5345 return fn_val;
...@@ -5430,13 +5426,28 @@ static LLVMValueRef ir_render_mark_err_ret_trace_ptr(CodeGen *g, IrExecutable *e...@@ -5430,13 +5426,28 @@ static LLVMValueRef ir_render_mark_err_ret_trace_ptr(CodeGen *g, IrExecutable *e
5430 return nullptr;5426 return nullptr;
5431}5427}
54325428
5433static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstructionSqrt *instruction) {5429static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) {
5434 LLVMValueRef op = ir_llvm_value(g, instruction->op);5430 LLVMValueRef op = ir_llvm_value(g, instruction->op1);
5435 assert(instruction->base.value.type->id == ZigTypeIdFloat);5431 assert(instruction->base.value.type->id == ZigTypeIdFloat);
5436 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value.type, ZigLLVMFnIdSqrt);5432 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value.type, ZigLLVMFnIdFloatOp, instruction->op);
5437 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");5433 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5438}5434}
54395435
5436static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrInstructionMulAdd *instruction) {
5437 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
5438 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
5439 LLVMValueRef op3 = ir_llvm_value(g, instruction->op3);
5440 assert(instruction->base.value.type->id == ZigTypeIdFloat ||
5441 instruction->base.value.type->id == ZigTypeIdVector);
5442 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value.type, ZigLLVMFnIdFMA, BuiltinFnIdMulAdd);
5443 LLVMValueRef args[3] = {
5444 op1,
5445 op2,
5446 op3,
5447 };
5448 return LLVMBuildCall(g->builder, fn_val, args, 3, "");
5449}
5450
5440static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {5451static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {
5441 LLVMValueRef op = ir_llvm_value(g, instruction->op);5452 LLVMValueRef op = ir_llvm_value(g, instruction->op);
5442 ZigType *int_type = instruction->base.value.type;5453 ZigType *int_type = instruction->base.value.type;
...@@ -5474,12 +5485,12 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab...@@ -5474,12 +5485,12 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab
5474 ZigType *array_type = instruction->base.value.type;5485 ZigType *array_type = instruction->base.value.type;
5475 assert(array_type->id == ZigTypeIdArray);5486 assert(array_type->id == ZigTypeIdArray);
5476 assert(handle_is_ptr(array_type));5487 assert(handle_is_ptr(array_type));
5477 assert(instruction->tmp_ptr);5488 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
5478 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);5489 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
5479 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,5490 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
5480 LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");5491 LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");
5481 gen_store_untyped(g, vector, casted_ptr, 0, false);5492 gen_store_untyped(g, vector, casted_ptr, get_ptr_align(g, instruction->result_loc->value.type), false);
5482 return instruction->tmp_ptr;5493 return result_loc;
5483}5494}
54845495
5485static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable,5496static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable,
...@@ -5542,14 +5553,10 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) {...@@ -5542,14 +5553,10 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
5542}5553}
55435554
5544static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {5555static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
5545 set_debug_location(g, instruction);
5546
5547 switch (instruction->id) {5556 switch (instruction->id) {
5548 case IrInstructionIdInvalid:5557 case IrInstructionIdInvalid:
5549 case IrInstructionIdConst:5558 case IrInstructionIdConst:
5550 case IrInstructionIdTypeOf:5559 case IrInstructionIdTypeOf:
5551 case IrInstructionIdToPtrType:
5552 case IrInstructionIdPtrTypeChild:
5553 case IrInstructionIdFieldPtr:5560 case IrInstructionIdFieldPtr:
5554 case IrInstructionIdSetCold:5561 case IrInstructionIdSetCold:
5555 case IrInstructionIdSetRuntimeSafety:5562 case IrInstructionIdSetRuntimeSafety:
...@@ -5611,10 +5618,22 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5611,10 +5618,22 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5611 case IrInstructionIdPtrCastSrc:5618 case IrInstructionIdPtrCastSrc:
5612 case IrInstructionIdCmpxchgSrc:5619 case IrInstructionIdCmpxchgSrc:
5613 case IrInstructionIdLoadPtr:5620 case IrInstructionIdLoadPtr:
5614 case IrInstructionIdBitCast:
5615 case IrInstructionIdGlobalAsm:5621 case IrInstructionIdGlobalAsm:
5616 case IrInstructionIdHasDecl:5622 case IrInstructionIdHasDecl:
5617 case IrInstructionIdUndeclaredIdent:5623 case IrInstructionIdUndeclaredIdent:
5624 case IrInstructionIdCallSrc:
5625 case IrInstructionIdAllocaSrc:
5626 case IrInstructionIdEndExpr:
5627 case IrInstructionIdAllocaGen:
5628 case IrInstructionIdImplicitCast:
5629 case IrInstructionIdResolveResult:
5630 case IrInstructionIdResetResult:
5631 case IrInstructionIdResultPtr:
5632 case IrInstructionIdContainerInitList:
5633 case IrInstructionIdSliceSrc:
5634 case IrInstructionIdRef:
5635 case IrInstructionIdBitCastSrc:
5636 case IrInstructionIdTestErrSrc:
5618 zig_unreachable();5637 zig_unreachable();
56195638
5620 case IrInstructionIdDeclVarGen:5639 case IrInstructionIdDeclVarGen:
...@@ -5639,10 +5658,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5639,10 +5658,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5639 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);5658 return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
5640 case IrInstructionIdVarPtr:5659 case IrInstructionIdVarPtr:
5641 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);5660 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
5661 case IrInstructionIdReturnPtr:
5662 return ir_render_return_ptr(g, executable, (IrInstructionReturnPtr *)instruction);
5642 case IrInstructionIdElemPtr:5663 case IrInstructionIdElemPtr:
5643 return ir_render_elem_ptr(g, executable, (IrInstructionElemPtr *)instruction);5664 return ir_render_elem_ptr(g, executable, (IrInstructionElemPtr *)instruction);
5644 case IrInstructionIdCall:5665 case IrInstructionIdCallGen:
5645 return ir_render_call(g, executable, (IrInstructionCall *)instruction);5666 return ir_render_call(g, executable, (IrInstructionCallGen *)instruction);
5646 case IrInstructionIdStructFieldPtr:5667 case IrInstructionIdStructFieldPtr:
5647 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);5668 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
5648 case IrInstructionIdUnionFieldPtr:5669 case IrInstructionIdUnionFieldPtr:
...@@ -5667,8 +5688,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5667,8 +5688,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5667 return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);5688 return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
5668 case IrInstructionIdPhi:5689 case IrInstructionIdPhi:
5669 return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);5690 return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);
5670 case IrInstructionIdRef:5691 case IrInstructionIdRefGen:
5671 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);5692 return ir_render_ref(g, executable, (IrInstructionRefGen *)instruction);
5672 case IrInstructionIdErrName:5693 case IrInstructionIdErrName:
5673 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);5694 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
5674 case IrInstructionIdCmpxchgGen:5695 case IrInstructionIdCmpxchgGen:
...@@ -5683,8 +5704,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5683,8 +5704,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5683 return ir_render_memset(g, executable, (IrInstructionMemset *)instruction);5704 return ir_render_memset(g, executable, (IrInstructionMemset *)instruction);
5684 case IrInstructionIdMemcpy:5705 case IrInstructionIdMemcpy:
5685 return ir_render_memcpy(g, executable, (IrInstructionMemcpy *)instruction);5706 return ir_render_memcpy(g, executable, (IrInstructionMemcpy *)instruction);
5686 case IrInstructionIdSlice:5707 case IrInstructionIdSliceGen:
5687 return ir_render_slice(g, executable, (IrInstructionSlice *)instruction);5708 return ir_render_slice(g, executable, (IrInstructionSliceGen *)instruction);
5688 case IrInstructionIdBreakpoint:5709 case IrInstructionIdBreakpoint:
5689 return ir_render_breakpoint(g, executable, (IrInstructionBreakpoint *)instruction);5710 return ir_render_breakpoint(g, executable, (IrInstructionBreakpoint *)instruction);
5690 case IrInstructionIdReturnAddress:5711 case IrInstructionIdReturnAddress:
...@@ -5695,24 +5716,20 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5695,24 +5716,20 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5695 return ir_render_handle(g, executable, (IrInstructionHandle *)instruction);5716 return ir_render_handle(g, executable, (IrInstructionHandle *)instruction);
5696 case IrInstructionIdOverflowOp:5717 case IrInstructionIdOverflowOp:
5697 return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);5718 return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
5698 case IrInstructionIdTestErr:5719 case IrInstructionIdTestErrGen:
5699 return ir_render_test_err(g, executable, (IrInstructionTestErr *)instruction);5720 return ir_render_test_err(g, executable, (IrInstructionTestErrGen *)instruction);
5700 case IrInstructionIdUnwrapErrCode:5721 case IrInstructionIdUnwrapErrCode:
5701 return ir_render_unwrap_err_code(g, executable, (IrInstructionUnwrapErrCode *)instruction);5722 return ir_render_unwrap_err_code(g, executable, (IrInstructionUnwrapErrCode *)instruction);
5702 case IrInstructionIdUnwrapErrPayload:5723 case IrInstructionIdUnwrapErrPayload:
5703 return ir_render_unwrap_err_payload(g, executable, (IrInstructionUnwrapErrPayload *)instruction);5724 return ir_render_unwrap_err_payload(g, executable, (IrInstructionUnwrapErrPayload *)instruction);
5704 case IrInstructionIdOptionalWrap:5725 case IrInstructionIdOptionalWrap:
5705 return ir_render_maybe_wrap(g, executable, (IrInstructionOptionalWrap *)instruction);5726 return ir_render_optional_wrap(g, executable, (IrInstructionOptionalWrap *)instruction);
5706 case IrInstructionIdErrWrapCode:5727 case IrInstructionIdErrWrapCode:
5707 return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);5728 return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction);
5708 case IrInstructionIdErrWrapPayload:5729 case IrInstructionIdErrWrapPayload:
5709 return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);5730 return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
5710 case IrInstructionIdUnionTag:5731 case IrInstructionIdUnionTag:
5711 return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);5732 return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);
5712 case IrInstructionIdStructInit:
5713 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
5714 case IrInstructionIdUnionInit:
5715 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
5716 case IrInstructionIdPtrCastGen:5733 case IrInstructionIdPtrCastGen:
5717 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);5734 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
5718 case IrInstructionIdBitCastGen:5735 case IrInstructionIdBitCastGen:
...@@ -5729,8 +5746,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5729,8 +5746,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5729 return ir_render_int_to_err(g, executable, (IrInstructionIntToErr *)instruction);5746 return ir_render_int_to_err(g, executable, (IrInstructionIntToErr *)instruction);
5730 case IrInstructionIdErrToInt:5747 case IrInstructionIdErrToInt:
5731 return ir_render_err_to_int(g, executable, (IrInstructionErrToInt *)instruction);5748 return ir_render_err_to_int(g, executable, (IrInstructionErrToInt *)instruction);
5732 case IrInstructionIdContainerInitList:
5733 return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
5734 case IrInstructionIdPanic:5749 case IrInstructionIdPanic:
5735 return ir_render_panic(g, executable, (IrInstructionPanic *)instruction);5750 return ir_render_panic(g, executable, (IrInstructionPanic *)instruction);
5736 case IrInstructionIdTagName:5751 case IrInstructionIdTagName:
...@@ -5779,8 +5794,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5779,8 +5794,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5779 return ir_render_merge_err_ret_traces(g, executable, (IrInstructionMergeErrRetTraces *)instruction);5794 return ir_render_merge_err_ret_traces(g, executable, (IrInstructionMergeErrRetTraces *)instruction);
5780 case IrInstructionIdMarkErrRetTracePtr:5795 case IrInstructionIdMarkErrRetTracePtr:
5781 return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);5796 return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
5782 case IrInstructionIdSqrt:5797 case IrInstructionIdFloatOp:
5783 return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);5798 return ir_render_float_op(g, executable, (IrInstructionFloatOp *)instruction);
5799 case IrInstructionIdMulAdd:
5800 return ir_render_mul_add(g, executable, (IrInstructionMulAdd *)instruction);
5784 case IrInstructionIdArrayToVector:5801 case IrInstructionIdArrayToVector:
5785 return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction);5802 return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction);
5786 case IrInstructionIdVectorToArray:5803 case IrInstructionIdVectorToArray:
...@@ -5791,6 +5808,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5791,6 +5808,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5791 return ir_render_assert_non_null(g, executable, (IrInstructionAssertNonNull *)instruction);5808 return ir_render_assert_non_null(g, executable, (IrInstructionAssertNonNull *)instruction);
5792 case IrInstructionIdResizeSlice:5809 case IrInstructionIdResizeSlice:
5793 return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);5810 return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);
5811 case IrInstructionIdPtrOfArrayToSlice:
5812 return ir_render_ptr_of_array_to_slice(g, executable, (IrInstructionPtrOfArrayToSlice *)instruction);
5794 }5813 }
5795 zig_unreachable();5814 zig_unreachable();
5796}5815}
...@@ -5802,7 +5821,6 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {...@@ -5802,7 +5821,6 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
5802 assert(executable->basic_block_list.length > 0);5821 assert(executable->basic_block_list.length > 0);
5803 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {5822 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
5804 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);5823 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);
5805 //assert(current_block->ref_count > 0);
5806 assert(current_block->llvm_block);5824 assert(current_block->llvm_block);
5807 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);5825 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
5808 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {5826 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
...@@ -5810,6 +5828,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {...@@ -5810,6 +5828,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
5810 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))5828 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
5811 continue;5829 continue;
58125830
5831 if (!g->strip_debug_symbols) {
5832 set_debug_location(g, instruction);
5833 }
5813 instruction->llvm_value = ir_render_instruction(g, executable, instruction);5834 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
5814 }5835 }
5815 current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);5836 current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
...@@ -6599,7 +6620,8 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const...@@ -6599,7 +6620,8 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const
6599 LLVMSetLinkage(global_value, LLVMInternalLinkage);6620 LLVMSetLinkage(global_value, LLVMInternalLinkage);
6600 LLVMSetGlobalConstant(global_value, true);6621 LLVMSetGlobalConstant(global_value, true);
6601 LLVMSetUnnamedAddr(global_value, true);6622 LLVMSetUnnamedAddr(global_value, true);
6602 LLVMSetAlignment(global_value, get_abi_alignment(g, const_val->type));6623 LLVMSetAlignment(global_value, (const_val->global_refs->align == 0) ?
6624 get_abi_alignment(g, const_val->type) : const_val->global_refs->align);
66036625
6604 const_val->global_refs->llvm_global = global_value;6626 const_val->global_refs->llvm_global = global_value;
6605 }6627 }
...@@ -6724,7 +6746,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6724,7 +6746,7 @@ static void do_code_gen(CodeGen *g) {
6724 zig_panic("TODO debug info for var with ptr casted value");6746 zig_panic("TODO debug info for var with ptr casted value");
6725 }6747 }
6726 ZigType *var_type = g->builtin_types.entry_f128;6748 ZigType *var_type = g->builtin_types.entry_f128;
6727 ConstExprValue coerced_value;6749 ConstExprValue coerced_value = {};
6728 coerced_value.special = ConstValSpecialStatic;6750 coerced_value.special = ConstValSpecialStatic;
6729 coerced_value.type = var_type;6751 coerced_value.type = var_type;
6730 coerced_value.data.x_f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);6752 coerced_value.data.x_f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);
...@@ -6829,20 +6851,24 @@ static void do_code_gen(CodeGen *g) {...@@ -6829,20 +6851,24 @@ static void do_code_gen(CodeGen *g) {
6829 FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;6851 FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
6830 CallingConvention cc = fn_type_id->cc;6852 CallingConvention cc = fn_type_id->cc;
6831 bool is_c_abi = cc == CallingConventionC;6853 bool is_c_abi = cc == CallingConventionC;
6854 bool want_sret = want_first_arg_sret(g, fn_type_id);
68326855
6833 LLVMValueRef fn = fn_llvm_value(g, fn_table_entry);6856 LLVMValueRef fn = fn_llvm_value(g, fn_table_entry);
6834 g->cur_fn = fn_table_entry;6857 g->cur_fn = fn_table_entry;
6835 g->cur_fn_val = fn;6858 g->cur_fn_val = fn;
6836 ZigType *return_type = fn_type_id->return_type;6859
6837 if (handle_is_ptr(return_type)) {6860 build_all_basic_blocks(g, fn_table_entry);
6861 clear_debug_source_node(g);
6862
6863 if (want_sret) {
6838 g->cur_ret_ptr = LLVMGetParam(fn, 0);6864 g->cur_ret_ptr = LLVMGetParam(fn, 0);
6865 } else if (handle_is_ptr(fn_type_id->return_type)) {
6866 g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0);
6867 // TODO add debug info variable for this
6839 } else {6868 } else {
6840 g->cur_ret_ptr = nullptr;6869 g->cur_ret_ptr = nullptr;
6841 }6870 }
68426871
6843 build_all_basic_blocks(g, fn_table_entry);
6844 clear_debug_source_node(g);
6845
6846 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);6872 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
6847 bool have_err_ret_trace_arg = err_ret_trace_arg_index != UINT32_MAX;6873 bool have_err_ret_trace_arg = err_ret_trace_arg_index != UINT32_MAX;
6848 if (have_err_ret_trace_arg) {6874 if (have_err_ret_trace_arg) {
...@@ -6867,68 +6893,28 @@ static void do_code_gen(CodeGen *g) {...@@ -6867,68 +6893,28 @@ static void do_code_gen(CodeGen *g) {
6867 }6893 }
68686894
6869 // allocate temporary stack data6895 // allocate temporary stack data
6870 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_list.length; alloca_i += 1) {6896 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {
6871 IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);6897 IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i);
6872 LLVMValueRef *slot;6898 ZigType *ptr_type = instruction->base.value.type;
6873 ZigType *slot_type = instruction->value.type;6899 assert(ptr_type->id == ZigTypeIdPointer);
6874 uint32_t alignment_bytes = 0;6900 ZigType *child_type = ptr_type->data.pointer.child_type;
6875 if (instruction->id == IrInstructionIdCast) {6901 if (!type_has_bits(child_type))
6876 IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;6902 continue;
6877 slot = &cast_instruction->tmp_ptr;6903 if (instruction->base.ref_count == 0)
6878 } else if (instruction->id == IrInstructionIdRef) {6904 continue;
6879 IrInstructionRef *ref_instruction = (IrInstructionRef *)instruction;6905 if (instruction->base.value.special != ConstValSpecialRuntime) {
6880 slot = &ref_instruction->tmp_ptr;6906 if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special !=
6881 assert(instruction->value.type->id == ZigTypeIdPointer);6907 ConstValSpecialRuntime)
6882 slot_type = instruction->value.type->data.pointer.child_type;6908 {
6883 } else if (instruction->id == IrInstructionIdContainerInitList) {6909 continue;
6884 IrInstructionContainerInitList *container_init_list_instruction = (IrInstructionContainerInitList *)instruction;6910 }
6885 slot = &container_init_list_instruction->tmp_ptr;
6886 } else if (instruction->id == IrInstructionIdStructInit) {
6887 IrInstructionStructInit *struct_init_instruction = (IrInstructionStructInit *)instruction;
6888 slot = &struct_init_instruction->tmp_ptr;
6889 } else if (instruction->id == IrInstructionIdUnionInit) {
6890 IrInstructionUnionInit *union_init_instruction = (IrInstructionUnionInit *)instruction;
6891 slot = &union_init_instruction->tmp_ptr;
6892 } else if (instruction->id == IrInstructionIdCall) {
6893 IrInstructionCall *call_instruction = (IrInstructionCall *)instruction;
6894 slot = &call_instruction->tmp_ptr;
6895 } else if (instruction->id == IrInstructionIdSlice) {
6896 IrInstructionSlice *slice_instruction = (IrInstructionSlice *)instruction;
6897 slot = &slice_instruction->tmp_ptr;
6898 } else if (instruction->id == IrInstructionIdOptionalWrap) {
6899 IrInstructionOptionalWrap *maybe_wrap_instruction = (IrInstructionOptionalWrap *)instruction;
6900 slot = &maybe_wrap_instruction->tmp_ptr;
6901 } else if (instruction->id == IrInstructionIdErrWrapPayload) {
6902 IrInstructionErrWrapPayload *err_wrap_payload_instruction = (IrInstructionErrWrapPayload *)instruction;
6903 slot = &err_wrap_payload_instruction->tmp_ptr;
6904 } else if (instruction->id == IrInstructionIdErrWrapCode) {
6905 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
6906 slot = &err_wrap_code_instruction->tmp_ptr;
6907 } else if (instruction->id == IrInstructionIdCmpxchgGen) {
6908 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
6909 slot = &cmpxchg_instruction->tmp_ptr;
6910 } else if (instruction->id == IrInstructionIdResizeSlice) {
6911 IrInstructionResizeSlice *resize_slice_instruction = (IrInstructionResizeSlice *)instruction;
6912 slot = &resize_slice_instruction->tmp_ptr;
6913 } else if (instruction->id == IrInstructionIdLoadPtrGen) {
6914 IrInstructionLoadPtrGen *load_ptr_inst = (IrInstructionLoadPtrGen *)instruction;
6915 slot = &load_ptr_inst->tmp_ptr;
6916 } else if (instruction->id == IrInstructionIdBitCastGen) {
6917 IrInstructionBitCastGen *bit_cast_inst = (IrInstructionBitCastGen *)instruction;
6918 slot = &bit_cast_inst->tmp_ptr;
6919 } else if (instruction->id == IrInstructionIdVectorToArray) {
6920 IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
6921 alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
6922 slot = &vector_to_array_instruction->tmp_ptr;
6923 } else {
6924 zig_unreachable();
6925 }6911 }
6926 *slot = build_alloca(g, slot_type, "", alignment_bytes);6912 instruction->base.llvm_value = build_alloca(g, child_type, instruction->name_hint,
6913 get_ptr_align(g, ptr_type));
6927 }6914 }
69286915
6929 ZigType *import = get_scope_import(&fn_table_entry->fndef_scope->base);6916 ZigType *import = get_scope_import(&fn_table_entry->fndef_scope->base);
69306917 unsigned gen_i_init = want_sret ? 1 : 0;
6931 unsigned gen_i_init = want_first_arg_sret(g, fn_type_id) ? 1 : 0;
69326918
6933 // create debug variable declarations for variables and allocate all local variables6919 // create debug variable declarations for variables and allocate all local variables
6934 FnWalk fn_walk_var = {};6920 FnWalk fn_walk_var = {};
...@@ -6955,8 +6941,6 @@ static void do_code_gen(CodeGen *g) {...@@ -6955,8 +6941,6 @@ static void do_code_gen(CodeGen *g) {
6955 }6941 }
69566942
6957 if (var->src_arg_index == SIZE_MAX) {6943 if (var->src_arg_index == SIZE_MAX) {
6958 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
6959
6960 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),6944 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
6961 buf_ptr(&var->name), import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1),6945 buf_ptr(&var->name), import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1),
6962 get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0);6946 get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0);
...@@ -7398,6 +7382,21 @@ static void define_builtin_fns(CodeGen *g) {...@@ -7398,6 +7382,21 @@ static void define_builtin_fns(CodeGen *g) {
7398 create_builtin_fn(g, BuiltinFnIdRem, "rem", 2);7382 create_builtin_fn(g, BuiltinFnIdRem, "rem", 2);
7399 create_builtin_fn(g, BuiltinFnIdMod, "mod", 2);7383 create_builtin_fn(g, BuiltinFnIdMod, "mod", 2);
7400 create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 2);7384 create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 2);
7385 create_builtin_fn(g, BuiltinFnIdSin, "sin", 2);
7386 create_builtin_fn(g, BuiltinFnIdCos, "cos", 2);
7387 create_builtin_fn(g, BuiltinFnIdExp, "exp", 2);
7388 create_builtin_fn(g, BuiltinFnIdExp2, "exp2", 2);
7389 create_builtin_fn(g, BuiltinFnIdLn, "ln", 2);
7390 create_builtin_fn(g, BuiltinFnIdLog2, "log2", 2);
7391 create_builtin_fn(g, BuiltinFnIdLog10, "log10", 2);
7392 create_builtin_fn(g, BuiltinFnIdFabs, "fabs", 2);
7393 create_builtin_fn(g, BuiltinFnIdFloor, "floor", 2);
7394 create_builtin_fn(g, BuiltinFnIdCeil, "ceil", 2);
7395 create_builtin_fn(g, BuiltinFnIdTrunc, "trunc", 2);
7396 //Needs library support on Windows
7397 //create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 2);
7398 create_builtin_fn(g, BuiltinFnIdRound, "round", 2);
7399 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
7401 create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);7400 create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);
7402 create_builtin_fn(g, BuiltinFnIdNoInlineCall, "noInlineCall", SIZE_MAX);7401 create_builtin_fn(g, BuiltinFnIdNoInlineCall, "noInlineCall", SIZE_MAX);
7403 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);7402 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);
...@@ -8056,6 +8055,8 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -8056,6 +8055,8 @@ static Error define_builtin_compile_vars(CodeGen *g) {
8056 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);8055 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
8057 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);8056 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
8058 g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);8057 g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
8058 g->std_package->package_table.put(buf_create_from_str("root"),
8059 g->is_test_build ? g->test_runner_package : g->root_package);
8059 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents,8060 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents,
8060 SourceKindPkgMain);8061 SourceKindPkgMain);
80618062
...@@ -8525,7 +8526,7 @@ static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *ba...@@ -8525,7 +8526,7 @@ static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *ba
85258526
8526static ZigPackage *create_bootstrap_pkg(CodeGen *g, ZigPackage *pkg_with_main) {8527static ZigPackage *create_bootstrap_pkg(CodeGen *g, ZigPackage *pkg_with_main) {
8527 ZigPackage *package = codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "bootstrap.zig", "std.special");8528 ZigPackage *package = codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "bootstrap.zig", "std.special");
8528 package->package_table.put(buf_create_from_str("@root"), pkg_with_main);8529 package->package_table.put(buf_create_from_str("root"), pkg_with_main);
8529 return package;8530 return package;
8530}8531}
85318532
...@@ -9378,6 +9379,7 @@ void codegen_add_time_event(CodeGen *g, const char *name) {...@@ -9378,6 +9379,7 @@ void codegen_add_time_event(CodeGen *g, const char *name) {
9378static void add_cache_pkg(CodeGen *g, CacheHash *ch, ZigPackage *pkg) {9379static void add_cache_pkg(CodeGen *g, CacheHash *ch, ZigPackage *pkg) {
9379 if (buf_len(&pkg->root_src_path) == 0)9380 if (buf_len(&pkg->root_src_path) == 0)
9380 return;9381 return;
9382 pkg->added_to_cache = true;
93819383
9382 Buf *rel_full_path = buf_alloc();9384 Buf *rel_full_path = buf_alloc();
9383 os_path_join(&pkg->root_src_dir, &pkg->root_src_path, rel_full_path);9385 os_path_join(&pkg->root_src_dir, &pkg->root_src_path, rel_full_path);
...@@ -9389,9 +9391,7 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, ZigPackage *pkg) {...@@ -9389,9 +9391,7 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, ZigPackage *pkg) {
9389 if (!entry)9391 if (!entry)
9390 break;9392 break;
93919393
9392 // TODO: I think we need a more sophisticated detection of9394 if (!pkg->added_to_cache) {
9393 // packages we have already seen
9394 if (entry->value != pkg) {
9395 cache_buf(ch, entry->key);9395 cache_buf(ch, entry->key);
9396 add_cache_pkg(g, ch, entry->value);9396 add_cache_pkg(g, ch, entry->value);
9397 }9397 }
...@@ -9648,6 +9648,10 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c...@@ -9648,6 +9648,10 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
9648 if (g->std_package != nullptr) {9648 if (g->std_package != nullptr) {
9649 assert(g->compile_var_package != nullptr);9649 assert(g->compile_var_package != nullptr);
9650 pkg->package_table.put(buf_create_from_str("std"), g->std_package);9650 pkg->package_table.put(buf_create_from_str("std"), g->std_package);
9651
9652 ZigPackage *main_pkg = g->is_test_build ? g->test_runner_package : g->root_package;
9653 pkg->package_table.put(buf_create_from_str("root"), main_pkg);
9654
9651 pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);9655 pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
9652 }9656 }
9653 return pkg;9657 return pkg;
src/ir.cpp+3608-1624
...@@ -38,6 +38,7 @@ struct IrAnalyze {...@@ -38,6 +38,7 @@ struct IrAnalyze {
38 ZigType *explicit_return_type;38 ZigType *explicit_return_type;
39 AstNode *explicit_return_type_source_node;39 AstNode *explicit_return_type_source_node;
40 ZigList<IrInstruction *> src_implicit_return_type_list;40 ZigList<IrInstruction *> src_implicit_return_type_list;
41 ZigList<IrSuspendPosition> resume_stack;
41 IrBasicBlock *const_predecessor_bb;42 IrBasicBlock *const_predecessor_bb;
42};43};
4344
...@@ -157,16 +158,19 @@ enum UndefAllowed {...@@ -157,16 +158,19 @@ enum UndefAllowed {
157};158};
158159
159static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);160static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
160static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval);161static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
161static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);162 ResultLoc *result_loc);
162static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type);163static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type);
163static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);164static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
165 ResultLoc *result_loc);
164static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);166static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
165static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,167static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
166 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);168 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing);
169static void ir_assert(bool ok, IrInstruction *source_instruction);
167static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var);170static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var);
168static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op);171static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op);
169static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);172static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval, ResultLoc *result_loc);
173static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc);
170static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);174static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
171static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);175static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
172static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val);176static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val);
...@@ -178,17 +182,28 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -178,17 +182,28 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
178static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);182static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
179static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);183static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
180static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);184static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
181static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
182static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,185static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
183 ZigType *ptr_type);186 ZigType *ptr_type);
184static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,187static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
185 ZigType *dest_type);188 ZigType *dest_type);
189static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr,
190 ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime);
191static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
192 ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime);
193static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
194 IrInstruction *base_ptr, bool safety_check_on, bool initializing);
195static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
196 IrInstruction *base_ptr, bool safety_check_on, bool initializing);
197static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
198 IrInstruction *base_ptr, bool initializing);
199static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
200 IrInstruction *ptr, IrInstruction *uncasted_value);
186201
187static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {202static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
188 assert(get_src_ptr_type(const_val->type) != nullptr);203 assert(get_src_ptr_type(const_val->type) != nullptr);
189 assert(const_val->special == ConstValSpecialStatic);204 assert(const_val->special == ConstValSpecialStatic);
190 ConstExprValue *result;205 ConstExprValue *result;
191 206
192 switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {207 switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {
193 case OnePossibleValueInvalid:208 case OnePossibleValueInvalid:
194 zig_unreachable();209 zig_unreachable();
...@@ -200,7 +215,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -200,7 +215,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
200 case OnePossibleValueNo:215 case OnePossibleValueNo:
201 break;216 break;
202 }217 }
203 218
204 switch (const_val->data.x_ptr.special) {219 switch (const_val->data.x_ptr.special) {
205 case ConstPtrSpecialInvalid:220 case ConstPtrSpecialInvalid:
206 zig_unreachable();221 zig_unreachable();
...@@ -246,6 +261,15 @@ static bool is_opt_err_set(ZigType *ty) {...@@ -246,6 +261,15 @@ static bool is_opt_err_set(ZigType *ty) {
246 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);261 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
247}262}
248263
264static bool is_slice(ZigType *type) {
265 return type->id == ZigTypeIdStruct && type->data.structure.is_slice;
266}
267
268static bool slice_is_const(ZigType *type) {
269 assert(is_slice(type));
270 return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
271}
272
249// This function returns true when you can change the type of a ConstExprValue and the273// This function returns true when you can change the type of a ConstExprValue and the
250// value remains meaningful.274// value remains meaningful.
251static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {275static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
...@@ -282,8 +306,9 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {...@@ -282,8 +306,9 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
282 return a->data.floating.bit_count == b->data.floating.bit_count;306 return a->data.floating.bit_count == b->data.floating.bit_count;
283 case ZigTypeIdInt:307 case ZigTypeIdInt:
284 return a->data.integral.is_signed == b->data.integral.is_signed;308 return a->data.integral.is_signed == b->data.integral.is_signed;
285 case ZigTypeIdArray:
286 case ZigTypeIdStruct:309 case ZigTypeIdStruct:
310 return is_slice(a) && is_slice(b);
311 case ZigTypeIdArray:
287 case ZigTypeIdOptional:312 case ZigTypeIdOptional:
288 case ZigTypeIdErrorUnion:313 case ZigTypeIdErrorUnion:
289 case ZigTypeIdEnum:314 case ZigTypeIdEnum:
...@@ -386,6 +411,7 @@ static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const c...@@ -386,6 +411,7 @@ static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const c
386 result->scope = scope;411 result->scope = scope;
387 result->name_hint = name_hint;412 result->name_hint = name_hint;
388 result->debug_id = exec_next_debug_id(irb->exec);413 result->debug_id = exec_next_debug_id(irb->exec);
414 result->index = SIZE_MAX; // set later
389 return result;415 return result;
390}416}
391417
...@@ -475,8 +501,16 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionVarPtr *) {...@@ -475,8 +501,16 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionVarPtr *) {
475 return IrInstructionIdVarPtr;501 return IrInstructionIdVarPtr;
476}502}
477503
478static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) {504static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnPtr *) {
479 return IrInstructionIdCall;505 return IrInstructionIdReturnPtr;
506}
507
508static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) {
509 return IrInstructionIdCallSrc;
510}
511
512static constexpr IrInstructionId ir_instruction_id(IrInstructionCallGen *) {
513 return IrInstructionIdCallGen;
480}514}
481515
482static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) {516static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) {
...@@ -511,14 +545,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeOf *) {...@@ -511,14 +545,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeOf *) {
511 return IrInstructionIdTypeOf;545 return IrInstructionIdTypeOf;
512}546}
513547
514static constexpr IrInstructionId ir_instruction_id(IrInstructionToPtrType *) {
515 return IrInstructionIdToPtrType;
516}
517
518static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) {
519 return IrInstructionIdPtrTypeChild;
520}
521
522static constexpr IrInstructionId ir_instruction_id(IrInstructionSetCold *) {548static constexpr IrInstructionId ir_instruction_id(IrInstructionSetCold *) {
523 return IrInstructionIdSetCold;549 return IrInstructionIdSetCold;
524}550}
...@@ -611,12 +637,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) {...@@ -611,12 +637,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) {
611 return IrInstructionIdRef;637 return IrInstructionIdRef;
612}638}
613639
614static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) {640static constexpr IrInstructionId ir_instruction_id(IrInstructionRefGen *) {
615 return IrInstructionIdStructInit;641 return IrInstructionIdRefGen;
616}
617
618static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInit *) {
619 return IrInstructionIdUnionInit;
620}642}
621643
622static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileErr *) {644static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileErr *) {
...@@ -703,8 +725,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMemcpy *) {...@@ -703,8 +725,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMemcpy *) {
703 return IrInstructionIdMemcpy;725 return IrInstructionIdMemcpy;
704}726}
705727
706static constexpr IrInstructionId ir_instruction_id(IrInstructionSlice *) {728static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceSrc *) {
707 return IrInstructionIdSlice;729 return IrInstructionIdSliceSrc;
730}
731
732static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceGen *) {
733 return IrInstructionIdSliceGen;
708}734}
709735
710static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) {736static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) {
...@@ -743,8 +769,16 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {...@@ -743,8 +769,16 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {
743 return IrInstructionIdOverflowOp;769 return IrInstructionIdOverflowOp;
744}770}
745771
746static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErr *) {772static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrSrc *) {
747 return IrInstructionIdTestErr;773 return IrInstructionIdTestErrSrc;
774}
775
776static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrGen *) {
777 return IrInstructionIdTestErrGen;
778}
779
780static constexpr IrInstructionId ir_instruction_id(IrInstructionMulAdd *) {
781 return IrInstructionIdMulAdd;
748}782}
749783
750static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrCode *) {784static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrCode *) {
...@@ -783,8 +817,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {...@@ -783,8 +817,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
783 return IrInstructionIdPtrCastGen;817 return IrInstructionIdPtrCastGen;
784}818}
785819
786static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {820static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastSrc *) {
787 return IrInstructionIdBitCast;821 return IrInstructionIdBitCastSrc;
788}822}
789823
790static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {824static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {
...@@ -879,6 +913,26 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) {...@@ -879,6 +913,26 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) {
879 return IrInstructionIdAlignCast;913 return IrInstructionIdAlignCast;
880}914}
881915
916static constexpr IrInstructionId ir_instruction_id(IrInstructionImplicitCast *) {
917 return IrInstructionIdImplicitCast;
918}
919
920static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *) {
921 return IrInstructionIdResolveResult;
922}
923
924static constexpr IrInstructionId ir_instruction_id(IrInstructionResetResult *) {
925 return IrInstructionIdResetResult;
926}
927
928static constexpr IrInstructionId ir_instruction_id(IrInstructionResultPtr *) {
929 return IrInstructionIdResultPtr;
930}
931
932static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrOfArrayToSlice *) {
933 return IrInstructionIdPtrOfArrayToSlice;
934}
935
882static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {936static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
883 return IrInstructionIdOpaqueType;937 return IrInstructionIdOpaqueType;
884}938}
...@@ -987,8 +1041,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMarkErrRetTraceP...@@ -987,8 +1041,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionMarkErrRetTraceP
987 return IrInstructionIdMarkErrRetTracePtr;1041 return IrInstructionIdMarkErrRetTracePtr;
988}1042}
9891043
990static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {1044static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatOp *) {
991 return IrInstructionIdSqrt;1045 return IrInstructionIdFloatOp;
992}1046}
9931047
994static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {1048static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
...@@ -1019,6 +1073,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUndeclaredIdent...@@ -1019,6 +1073,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUndeclaredIdent
1019 return IrInstructionIdUndeclaredIdent;1073 return IrInstructionIdUndeclaredIdent;
1020}1074}
10211075
1076static constexpr IrInstructionId ir_instruction_id(IrInstructionAllocaSrc *) {
1077 return IrInstructionIdAllocaSrc;
1078}
1079
1080static constexpr IrInstructionId ir_instruction_id(IrInstructionAllocaGen *) {
1081 return IrInstructionIdAllocaGen;
1082}
1083
1084static constexpr IrInstructionId ir_instruction_id(IrInstructionEndExpr *) {
1085 return IrInstructionIdEndExpr;
1086}
1087
1022template<typename T>1088template<typename T>
1023static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {1089static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
1024 T *special_instruction = allocate<T>(1);1090 T *special_instruction = allocate<T>(1);
...@@ -1070,13 +1136,15 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so...@@ -1070,13 +1136,15 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
1070 return &cond_br_instruction->base;1136 return &cond_br_instruction->base;
1071}1137}
10721138
1073static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *return_value) {1139static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node,
1140 IrInstruction *return_value)
1141{
1074 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, scope, source_node);1142 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, scope, source_node);
1075 return_instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;1143 return_instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;
1076 return_instruction->base.value.special = ConstValSpecialStatic;1144 return_instruction->base.value.special = ConstValSpecialStatic;
1077 return_instruction->value = return_value;1145 return_instruction->value = return_value;
10781146
1079 ir_ref_instruction(return_value, irb->current_basic_block);1147 if (return_value != nullptr) ir_ref_instruction(return_value, irb->current_basic_block);
10801148
1081 return &return_instruction->base;1149 return &return_instruction->base;
1082}1150}
...@@ -1254,17 +1322,27 @@ static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *so...@@ -1254,17 +1322,27 @@ static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *so
1254 return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr);1322 return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr);
1255}1323}
12561324
1257static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr,1325static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
1258 IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len)1326 IrInstructionReturnPtr *instruction = ir_build_instruction<IrInstructionReturnPtr>(&ira->new_irb,
1327 source_instruction->scope, source_instruction->source_node);
1328 instruction->base.value.type = ty;
1329 return &instruction->base;
1330}
1331
1332static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1333 IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len,
1334 IrInstruction *init_array_type)
1259{1335{
1260 IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node);1336 IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node);
1261 instruction->array_ptr = array_ptr;1337 instruction->array_ptr = array_ptr;
1262 instruction->elem_index = elem_index;1338 instruction->elem_index = elem_index;
1263 instruction->safety_check_on = safety_check_on;1339 instruction->safety_check_on = safety_check_on;
1264 instruction->ptr_len = ptr_len;1340 instruction->ptr_len = ptr_len;
1341 instruction->init_array_type = init_array_type;
12651342
1266 ir_ref_instruction(array_ptr, irb->current_basic_block);1343 ir_ref_instruction(array_ptr, irb->current_basic_block);
1267 ir_ref_instruction(elem_index, irb->current_basic_block);1344 ir_ref_instruction(elem_index, irb->current_basic_block);
1345 if (init_array_type != nullptr) ir_ref_instruction(init_array_type, irb->current_basic_block);
12681346
1269 return &instruction->base;1347 return &instruction->base;
1270}1348}
...@@ -1284,12 +1362,13 @@ static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scop...@@ -1284,12 +1362,13 @@ static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scop
1284}1362}
12851363
1286static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,1364static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1287 IrInstruction *container_ptr, Buf *field_name)1365 IrInstruction *container_ptr, Buf *field_name, bool initializing)
1288{1366{
1289 IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node);1367 IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node);
1290 instruction->container_ptr = container_ptr;1368 instruction->container_ptr = container_ptr;
1291 instruction->field_name_buffer = field_name;1369 instruction->field_name_buffer = field_name;
1292 instruction->field_name_expr = nullptr;1370 instruction->field_name_expr = nullptr;
1371 instruction->initializing = initializing;
12931372
1294 ir_ref_instruction(container_ptr, irb->current_basic_block);1373 ir_ref_instruction(container_ptr, irb->current_basic_block);
12951374
...@@ -1309,9 +1388,11 @@ static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, As...@@ -1309,9 +1388,11 @@ static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, As
1309}1388}
13101389
1311static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,1390static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1312 IrInstruction *union_ptr, TypeUnionField *field)1391 IrInstruction *union_ptr, TypeUnionField *field, bool safety_check_on, bool initializing)
1313{1392{
1314 IrInstructionUnionFieldPtr *instruction = ir_build_instruction<IrInstructionUnionFieldPtr>(irb, scope, source_node);1393 IrInstructionUnionFieldPtr *instruction = ir_build_instruction<IrInstructionUnionFieldPtr>(irb, scope, source_node);
1394 instruction->initializing = initializing;
1395 instruction->safety_check_on = safety_check_on;
1315 instruction->union_ptr = union_ptr;1396 instruction->union_ptr = union_ptr;
1316 instruction->field = field;1397 instruction->field = field;
13171398
...@@ -1320,12 +1401,12 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast...@@ -1320,12 +1401,12 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
1320 return &instruction->base;1401 return &instruction->base;
1321}1402}
13221403
1323static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,1404static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1324 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1405 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1325 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator,1406 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator,
1326 IrInstruction *new_stack)1407 IrInstruction *new_stack, ResultLoc *result_loc)
1327{1408{
1328 IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, scope, source_node);1409 IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);
1329 call_instruction->fn_entry = fn_entry;1410 call_instruction->fn_entry = fn_entry;
1330 call_instruction->fn_ref = fn_ref;1411 call_instruction->fn_ref = fn_ref;
1331 call_instruction->is_comptime = is_comptime;1412 call_instruction->is_comptime = is_comptime;
...@@ -1335,6 +1416,7 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -1335,6 +1416,7 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
1335 call_instruction->is_async = is_async;1416 call_instruction->is_async = is_async;
1336 call_instruction->async_allocator = async_allocator;1417 call_instruction->async_allocator = async_allocator;
1337 call_instruction->new_stack = new_stack;1418 call_instruction->new_stack = new_stack;
1419 call_instruction->result_loc = result_loc;
13381420
1339 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);1421 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
1340 for (size_t i = 0; i < arg_count; i += 1)1422 for (size_t i = 0; i < arg_count; i += 1)
...@@ -1345,8 +1427,37 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -1345,8 +1427,37 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
1345 return &call_instruction->base;1427 return &call_instruction->base;
1346}1428}
13471429
1430static IrInstruction *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1431 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1432 FnInline fn_inline, bool is_async, IrInstruction *async_allocator, IrInstruction *new_stack,
1433 IrInstruction *result_loc, ZigType *return_type)
1434{
1435 IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,
1436 source_instruction->scope, source_instruction->source_node);
1437 call_instruction->base.value.type = return_type;
1438 call_instruction->fn_entry = fn_entry;
1439 call_instruction->fn_ref = fn_ref;
1440 call_instruction->fn_inline = fn_inline;
1441 call_instruction->args = args;
1442 call_instruction->arg_count = arg_count;
1443 call_instruction->is_async = is_async;
1444 call_instruction->async_allocator = async_allocator;
1445 call_instruction->new_stack = new_stack;
1446 call_instruction->result_loc = result_loc;
1447
1448 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, ira->new_irb.current_basic_block);
1449 for (size_t i = 0; i < arg_count; i += 1)
1450 ir_ref_instruction(args[i], ira->new_irb.current_basic_block);
1451 if (async_allocator != nullptr) ir_ref_instruction(async_allocator, ira->new_irb.current_basic_block);
1452 if (new_stack != nullptr) ir_ref_instruction(new_stack, ira->new_irb.current_basic_block);
1453 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
1454
1455 return &call_instruction->base;
1456}
1457
1348static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source_node,1458static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source_node,
1349 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)1459 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values,
1460 ResultLocPeerParent *peer_parent)
1350{1461{
1351 assert(incoming_count != 0);1462 assert(incoming_count != 0);
1352 assert(incoming_count != SIZE_MAX);1463 assert(incoming_count != SIZE_MAX);
...@@ -1355,6 +1466,7 @@ static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source...@@ -1355,6 +1466,7 @@ static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source
1355 phi_instruction->incoming_count = incoming_count;1466 phi_instruction->incoming_count = incoming_count;
1356 phi_instruction->incoming_blocks = incoming_blocks;1467 phi_instruction->incoming_blocks = incoming_blocks;
1357 phi_instruction->incoming_values = incoming_values;1468 phi_instruction->incoming_values = incoming_values;
1469 phi_instruction->peer_parent = peer_parent;
13581470
1359 for (size_t i = 0; i < incoming_count; i += 1) {1471 for (size_t i = 0; i < incoming_count; i += 1) {
1360 ir_ref_bb(incoming_blocks[i]);1472 ir_ref_bb(incoming_blocks[i]);
...@@ -1408,12 +1520,13 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1408,12 +1520,13 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
1408}1520}
14091521
1410static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,1522static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
1411 IrInstruction *value, LVal lval)1523 IrInstruction *value, LVal lval, ResultLoc *result_loc)
1412{1524{
1413 IrInstructionUnOp *instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node);1525 IrInstructionUnOp *instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node);
1414 instruction->op_id = op_id;1526 instruction->op_id = op_id;
1415 instruction->value = value;1527 instruction->value = value;
1416 instruction->lval = lval;1528 instruction->lval = lval;
1529 instruction->result_loc = result_loc;
14171530
1418 ir_ref_instruction(value, irb->current_basic_block);1531 ir_ref_instruction(value, irb->current_basic_block);
14191532
...@@ -1423,72 +1536,49 @@ static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode...@@ -1423,72 +1536,49 @@ static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode
1423static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,1536static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
1424 IrInstruction *value)1537 IrInstruction *value)
1425{1538{
1426 return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone);1539 return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone, nullptr);
1427}1540}
14281541
1429static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,1542static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
1430 IrInstruction *container_type, IrInstruction *elem_type, size_t item_count, IrInstruction **items)1543 IrInstruction *container_type, size_t item_count, IrInstruction **elem_result_loc_list,
1544 IrInstruction *result_loc)
1431{1545{
1432 IrInstructionContainerInitList *container_init_list_instruction =1546 IrInstructionContainerInitList *container_init_list_instruction =
1433 ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);1547 ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
1434 container_init_list_instruction->container_type = container_type;1548 container_init_list_instruction->container_type = container_type;
1435 container_init_list_instruction->elem_type = elem_type;
1436 container_init_list_instruction->item_count = item_count;1549 container_init_list_instruction->item_count = item_count;
1437 container_init_list_instruction->items = items;1550 container_init_list_instruction->elem_result_loc_list = elem_result_loc_list;
1551 container_init_list_instruction->result_loc = result_loc;
14381552
1439 if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);1553 ir_ref_instruction(container_type, irb->current_basic_block);
1440 if (elem_type != nullptr) ir_ref_instruction(elem_type, irb->current_basic_block);
1441 for (size_t i = 0; i < item_count; i += 1) {1554 for (size_t i = 0; i < item_count; i += 1) {
1442 ir_ref_instruction(items[i], irb->current_basic_block);1555 ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block);
1443 }1556 }
1557 if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
14441558
1445 return &container_init_list_instruction->base;1559 return &container_init_list_instruction->base;
1446}1560}
14471561
1448static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,1562static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,
1449 IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields)1563 IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields,
1564 IrInstruction *result_loc)
1450{1565{
1451 IrInstructionContainerInitFields *container_init_fields_instruction =1566 IrInstructionContainerInitFields *container_init_fields_instruction =
1452 ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node);1567 ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node);
1453 container_init_fields_instruction->container_type = container_type;1568 container_init_fields_instruction->container_type = container_type;
1454 container_init_fields_instruction->field_count = field_count;1569 container_init_fields_instruction->field_count = field_count;
1455 container_init_fields_instruction->fields = fields;1570 container_init_fields_instruction->fields = fields;
1571 container_init_fields_instruction->result_loc = result_loc;
14561572
1457 ir_ref_instruction(container_type, irb->current_basic_block);1573 ir_ref_instruction(container_type, irb->current_basic_block);
1458 for (size_t i = 0; i < field_count; i += 1) {1574 for (size_t i = 0; i < field_count; i += 1) {
1459 ir_ref_instruction(fields[i].value, irb->current_basic_block);1575 ir_ref_instruction(fields[i].result_loc, irb->current_basic_block);
1460 }1576 }
1577 if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
14611578
1462 return &container_init_fields_instruction->base;1579 return &container_init_fields_instruction->base;
1463}1580}
14641581
1465static IrInstruction *ir_build_struct_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
1466 ZigType *struct_type, size_t field_count, IrInstructionStructInitField *fields)
1467{
1468 IrInstructionStructInit *struct_init_instruction = ir_build_instruction<IrInstructionStructInit>(irb, scope, source_node);
1469 struct_init_instruction->struct_type = struct_type;
1470 struct_init_instruction->field_count = field_count;
1471 struct_init_instruction->fields = fields;
1472
1473 for (size_t i = 0; i < field_count; i += 1)
1474 ir_ref_instruction(fields[i].value, irb->current_basic_block);
1475
1476 return &struct_init_instruction->base;
1477}
1478
1479static IrInstruction *ir_build_union_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
1480 ZigType *union_type, TypeUnionField *field, IrInstruction *init_value)
1481{
1482 IrInstructionUnionInit *union_init_instruction = ir_build_instruction<IrInstructionUnionInit>(irb, scope, source_node);
1483 union_init_instruction->union_type = union_type;
1484 union_init_instruction->field = field;
1485 union_init_instruction->init_value = init_value;
1486
1487 ir_ref_instruction(init_value, irb->current_basic_block);
1488
1489 return &union_init_instruction->base;
1490}
1491
1492static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node) {1582static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node) {
1493 IrInstructionUnreachable *unreachable_instruction =1583 IrInstructionUnreachable *unreachable_instruction =
1494 ir_build_instruction<IrInstructionUnreachable>(irb, scope, source_node);1584 ir_build_instruction<IrInstructionUnreachable>(irb, scope, source_node);
...@@ -1513,47 +1603,47 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *...@@ -1513,47 +1603,47 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
1513}1603}
15141604
1515static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,1605static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1516 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)1606 ZigVar *var, IrInstruction *align_value, IrInstruction *ptr)
1517{1607{
1518 IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarSrc>(irb, scope, source_node);1608 IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarSrc>(irb, scope, source_node);
1519 decl_var_instruction->base.value.special = ConstValSpecialStatic;1609 decl_var_instruction->base.value.special = ConstValSpecialStatic;
1520 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;1610 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
1521 decl_var_instruction->var = var;1611 decl_var_instruction->var = var;
1522 decl_var_instruction->var_type = var_type;
1523 decl_var_instruction->align_value = align_value;1612 decl_var_instruction->align_value = align_value;
1524 decl_var_instruction->init_value = init_value;1613 decl_var_instruction->ptr = ptr;
15251614
1526 if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
1527 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);1615 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
1528 ir_ref_instruction(init_value, irb->current_basic_block);1616 ir_ref_instruction(ptr, irb->current_basic_block);
15291617
1530 return &decl_var_instruction->base;1618 return &decl_var_instruction->base;
1531}1619}
15321620
1533static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction,1621static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1534 ZigVar *var, IrInstruction *init_value)1622 ZigVar *var, IrInstruction *var_ptr)
1535{1623{
1536 IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarGen>(&ira->new_irb,1624 IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarGen>(&ira->new_irb,
1537 source_instruction->scope, source_instruction->source_node);1625 source_instruction->scope, source_instruction->source_node);
1538 decl_var_instruction->base.value.special = ConstValSpecialStatic;1626 decl_var_instruction->base.value.special = ConstValSpecialStatic;
1539 decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void;1627 decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void;
1540 decl_var_instruction->var = var;1628 decl_var_instruction->var = var;
1541 decl_var_instruction->init_value = init_value;1629 decl_var_instruction->var_ptr = var_ptr;
15421630
1543 ir_ref_instruction(init_value, ira->new_irb.current_basic_block);1631 ir_ref_instruction(var_ptr, ira->new_irb.current_basic_block);
15441632
1545 return &decl_var_instruction->base;1633 return &decl_var_instruction->base;
1546}1634}
15471635
1548static IrInstruction *ir_build_resize_slice(IrAnalyze *ira, IrInstruction *source_instruction,1636static IrInstruction *ir_build_resize_slice(IrAnalyze *ira, IrInstruction *source_instruction,
1549 IrInstruction *operand, ZigType *ty)1637 IrInstruction *operand, ZigType *ty, IrInstruction *result_loc)
1550{1638{
1551 IrInstructionResizeSlice *instruction = ir_build_instruction<IrInstructionResizeSlice>(&ira->new_irb,1639 IrInstructionResizeSlice *instruction = ir_build_instruction<IrInstructionResizeSlice>(&ira->new_irb,
1552 source_instruction->scope, source_instruction->source_node);1640 source_instruction->scope, source_instruction->source_node);
1553 instruction->base.value.type = ty;1641 instruction->base.value.type = ty;
1554 instruction->operand = operand;1642 instruction->operand = operand;
1643 instruction->result_loc = result_loc;
15551644
1556 ir_ref_instruction(operand, ira->new_irb.current_basic_block);1645 ir_ref_instruction(operand, ira->new_irb.current_basic_block);
1646 ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
15571647
1558 return &instruction->base;1648 return &instruction->base;
1559}1649}
...@@ -1594,27 +1684,6 @@ static IrInstruction *ir_build_typeof(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -1594,27 +1684,6 @@ static IrInstruction *ir_build_typeof(IrBuilder *irb, Scope *scope, AstNode *sou
1594 return &instruction->base;1684 return &instruction->base;
1595}1685}
15961686
1597static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) {
1598 IrInstructionToPtrType *instruction = ir_build_instruction<IrInstructionToPtrType>(irb, scope, source_node);
1599 instruction->ptr = ptr;
1600
1601 ir_ref_instruction(ptr, irb->current_basic_block);
1602
1603 return &instruction->base;
1604}
1605
1606static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstNode *source_node,
1607 IrInstruction *value)
1608{
1609 IrInstructionPtrTypeChild *instruction = ir_build_instruction<IrInstructionPtrTypeChild>(
1610 irb, scope, source_node);
1611 instruction->value = value;
1612
1613 ir_ref_instruction(value, irb->current_basic_block);
1614
1615 return &instruction->base;
1616}
1617
1618static IrInstruction *ir_build_set_cold(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_cold) {1687static IrInstruction *ir_build_set_cold(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_cold) {
1619 IrInstructionSetCold *instruction = ir_build_instruction<IrInstructionSetCold>(irb, scope, source_node);1688 IrInstructionSetCold *instruction = ir_build_instruction<IrInstructionSetCold>(irb, scope, source_node);
1620 instruction->is_cold = is_cold;1689 instruction->is_cold = is_cold;
...@@ -1740,40 +1809,59 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod...@@ -1740,40 +1809,59 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
1740}1809}
17411810
1742static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,1811static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1743 IrInstruction *base_ptr, bool safety_check_on)1812 IrInstruction *base_ptr, bool safety_check_on, bool initializing)
1744{1813{
1745 IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node);1814 IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node);
1746 instruction->base_ptr = base_ptr;1815 instruction->base_ptr = base_ptr;
1747 instruction->safety_check_on = safety_check_on;1816 instruction->safety_check_on = safety_check_on;
1817 instruction->initializing = initializing;
17481818
1749 ir_ref_instruction(base_ptr, irb->current_basic_block);1819 ir_ref_instruction(base_ptr, irb->current_basic_block);
17501820
1751 return &instruction->base;1821 return &instruction->base;
1752}1822}
17531823
1754static IrInstruction *ir_build_maybe_wrap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1824static IrInstruction *ir_build_optional_wrap(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_ty,
1755 IrInstructionOptionalWrap *instruction = ir_build_instruction<IrInstructionOptionalWrap>(irb, scope, source_node);1825 IrInstruction *operand, IrInstruction *result_loc)
1756 instruction->value = value;1826{
1827 IrInstructionOptionalWrap *instruction = ir_build_instruction<IrInstructionOptionalWrap>(
1828 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
1829 instruction->base.value.type = result_ty;
1830 instruction->operand = operand;
1831 instruction->result_loc = result_loc;
17571832
1758 ir_ref_instruction(value, irb->current_basic_block);1833 ir_ref_instruction(operand, ira->new_irb.current_basic_block);
1834 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
17591835
1760 return &instruction->base;1836 return &instruction->base;
1761}1837}
17621838
1763static IrInstruction *ir_build_err_wrap_payload(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1839static IrInstruction *ir_build_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instruction,
1764 IrInstructionErrWrapPayload *instruction = ir_build_instruction<IrInstructionErrWrapPayload>(irb, scope, source_node);1840 ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc)
1765 instruction->value = value;1841{
1842 IrInstructionErrWrapPayload *instruction = ir_build_instruction<IrInstructionErrWrapPayload>(
1843 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
1844 instruction->base.value.type = result_type;
1845 instruction->operand = operand;
1846 instruction->result_loc = result_loc;
17661847
1767 ir_ref_instruction(value, irb->current_basic_block);1848 ir_ref_instruction(operand, ira->new_irb.current_basic_block);
1849 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
17681850
1769 return &instruction->base;1851 return &instruction->base;
1770}1852}
17711853
1772static IrInstruction *ir_build_err_wrap_code(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1854static IrInstruction *ir_build_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instruction,
1773 IrInstructionErrWrapCode *instruction = ir_build_instruction<IrInstructionErrWrapCode>(irb, scope, source_node);1855 ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc)
1774 instruction->value = value;1856{
1857 IrInstructionErrWrapCode *instruction = ir_build_instruction<IrInstructionErrWrapCode>(
1858 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
1859 instruction->base.value.type = result_type;
1860 instruction->operand = operand;
1861 instruction->result_loc = result_loc;
17751862
1776 ir_ref_instruction(value, irb->current_basic_block);1863 ir_ref_instruction(operand, ira->new_irb.current_basic_block);
1864 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
17771865
1778 return &instruction->base;1866 return &instruction->base;
1779}1867}
...@@ -1930,6 +2018,21 @@ static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source...@@ -1930,6 +2018,21 @@ static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source
1930 return &instruction->base;2018 return &instruction->base;
1931}2019}
19322020
2021static IrInstruction *ir_build_ref_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type,
2022 IrInstruction *operand, IrInstruction *result_loc)
2023{
2024 IrInstructionRefGen *instruction = ir_build_instruction<IrInstructionRefGen>(&ira->new_irb,
2025 source_instruction->scope, source_instruction->source_node);
2026 instruction->base.value.type = result_type;
2027 instruction->operand = operand;
2028 instruction->result_loc = result_loc;
2029
2030 ir_ref_instruction(operand, ira->new_irb.current_basic_block);
2031 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
2032
2033 return &instruction->base;
2034}
2035
1933static IrInstruction *ir_build_compile_err(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *msg) {2036static IrInstruction *ir_build_compile_err(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *msg) {
1934 IrInstructionCompileErr *instruction = ir_build_instruction<IrInstructionCompileErr>(irb, scope, source_node);2037 IrInstructionCompileErr *instruction = ir_build_instruction<IrInstructionCompileErr>(irb, scope, source_node);
1935 instruction->msg = msg;2038 instruction->msg = msg;
...@@ -2007,8 +2110,7 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode...@@ -2007,8 +2110,7 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
20072110
2008static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,2111static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2009 IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,2112 IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
2010 IrInstruction *success_order_value, IrInstruction *failure_order_value,2113 IrInstruction *success_order_value, IrInstruction *failure_order_value, bool is_weak, ResultLoc *result_loc)
2011 bool is_weak)
2012{2114{
2013 IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);2115 IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);
2014 instruction->type_value = type_value;2116 instruction->type_value = type_value;
...@@ -2018,6 +2120,7 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode...@@ -2018,6 +2120,7 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode
2018 instruction->success_order_value = success_order_value;2120 instruction->success_order_value = success_order_value;
2019 instruction->failure_order_value = failure_order_value;2121 instruction->failure_order_value = failure_order_value;
2020 instruction->is_weak = is_weak;2122 instruction->is_weak = is_weak;
2123 instruction->result_loc = result_loc;
20212124
2022 ir_ref_instruction(type_value, irb->current_basic_block);2125 ir_ref_instruction(type_value, irb->current_basic_block);
2023 ir_ref_instruction(ptr, irb->current_basic_block);2126 ir_ref_instruction(ptr, irb->current_basic_block);
...@@ -2029,22 +2132,25 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode...@@ -2029,22 +2132,25 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode
2029 return &instruction->base;2132 return &instruction->base;
2030}2133}
20312134
2032static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction,2135static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type,
2033 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,2136 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
2034 AtomicOrder success_order, AtomicOrder failure_order, bool is_weak)2137 AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstruction *result_loc)
2035{2138{
2036 IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb,2139 IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb,
2037 source_instruction->scope, source_instruction->source_node);2140 source_instruction->scope, source_instruction->source_node);
2141 instruction->base.value.type = result_type;
2038 instruction->ptr = ptr;2142 instruction->ptr = ptr;
2039 instruction->cmp_value = cmp_value;2143 instruction->cmp_value = cmp_value;
2040 instruction->new_value = new_value;2144 instruction->new_value = new_value;
2041 instruction->success_order = success_order;2145 instruction->success_order = success_order;
2042 instruction->failure_order = failure_order;2146 instruction->failure_order = failure_order;
2043 instruction->is_weak = is_weak;2147 instruction->is_weak = is_weak;
2148 instruction->result_loc = result_loc;
20442149
2045 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);2150 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
2046 ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);2151 ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);
2047 ir_ref_instruction(new_value, ira->new_irb.current_basic_block);2152 ir_ref_instruction(new_value, ira->new_irb.current_basic_block);
2153 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
20482154
2049 return &instruction->base;2155 return &instruction->base;
2050}2156}
...@@ -2103,19 +2209,25 @@ static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNod...@@ -2103,19 +2209,25 @@ static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNod
2103 return &instruction->base;2209 return &instruction->base;
2104}2210}
21052211
2106static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target) {2212static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target,
2213 ResultLoc *result_loc)
2214{
2107 IrInstructionToBytes *instruction = ir_build_instruction<IrInstructionToBytes>(irb, scope, source_node);2215 IrInstructionToBytes *instruction = ir_build_instruction<IrInstructionToBytes>(irb, scope, source_node);
2108 instruction->target = target;2216 instruction->target = target;
2217 instruction->result_loc = result_loc;
21092218
2110 ir_ref_instruction(target, irb->current_basic_block);2219 ir_ref_instruction(target, irb->current_basic_block);
21112220
2112 return &instruction->base;2221 return &instruction->base;
2113}2222}
21142223
2115static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_child_type, IrInstruction *target) {2224static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node,
2225 IrInstruction *dest_child_type, IrInstruction *target, ResultLoc *result_loc)
2226{
2116 IrInstructionFromBytes *instruction = ir_build_instruction<IrInstructionFromBytes>(irb, scope, source_node);2227 IrInstructionFromBytes *instruction = ir_build_instruction<IrInstructionFromBytes>(irb, scope, source_node);
2117 instruction->dest_child_type = dest_child_type;2228 instruction->dest_child_type = dest_child_type;
2118 instruction->target = target;2229 instruction->target = target;
2230 instruction->result_loc = result_loc;
21192231
2120 ir_ref_instruction(dest_child_type, irb->current_basic_block);2232 ir_ref_instruction(dest_child_type, irb->current_basic_block);
2121 ir_ref_instruction(target, irb->current_basic_block);2233 ir_ref_instruction(target, irb->current_basic_block);
...@@ -2217,14 +2329,15 @@ static IrInstruction *ir_build_memcpy(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -2217,14 +2329,15 @@ static IrInstruction *ir_build_memcpy(IrBuilder *irb, Scope *scope, AstNode *sou
2217 return &instruction->base;2329 return &instruction->base;
2218}2330}
22192331
2220static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *source_node,2332static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2221 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on)2333 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, ResultLoc *result_loc)
2222{2334{
2223 IrInstructionSlice *instruction = ir_build_instruction<IrInstructionSlice>(irb, scope, source_node);2335 IrInstructionSliceSrc *instruction = ir_build_instruction<IrInstructionSliceSrc>(irb, scope, source_node);
2224 instruction->ptr = ptr;2336 instruction->ptr = ptr;
2225 instruction->start = start;2337 instruction->start = start;
2226 instruction->end = end;2338 instruction->end = end;
2227 instruction->safety_check_on = safety_check_on;2339 instruction->safety_check_on = safety_check_on;
2340 instruction->result_loc = result_loc;
22282341
2229 ir_ref_instruction(ptr, irb->current_basic_block);2342 ir_ref_instruction(ptr, irb->current_basic_block);
2230 ir_ref_instruction(start, irb->current_basic_block);2343 ir_ref_instruction(start, irb->current_basic_block);
...@@ -2233,6 +2346,26 @@ static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *sour...@@ -2233,6 +2346,26 @@ static IrInstruction *ir_build_slice(IrBuilder *irb, Scope *scope, AstNode *sour
2233 return &instruction->base;2346 return &instruction->base;
2234}2347}
22352348
2349static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type,
2350 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc)
2351{
2352 IrInstructionSliceGen *instruction = ir_build_instruction<IrInstructionSliceGen>(
2353 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2354 instruction->base.value.type = slice_type;
2355 instruction->ptr = ptr;
2356 instruction->start = start;
2357 instruction->end = end;
2358 instruction->safety_check_on = safety_check_on;
2359 instruction->result_loc = result_loc;
2360
2361 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
2362 ir_ref_instruction(start, ira->new_irb.current_basic_block);
2363 if (end) ir_ref_instruction(end, ira->new_irb.current_basic_block);
2364 ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
2365
2366 return &instruction->base;
2367}
2368
2236static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *container) {2369static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *container) {
2237 IrInstructionMemberCount *instruction = ir_build_instruction<IrInstructionMemberCount>(irb, scope, source_node);2370 IrInstructionMemberCount *instruction = ir_build_instruction<IrInstructionMemberCount>(irb, scope, source_node);
2238 instruction->container = container;2371 instruction->container = container;
...@@ -2308,6 +2441,75 @@ static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode...@@ -2308,6 +2441,75 @@ static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode
2308 return &instruction->base;2441 return &instruction->base;
2309}2442}
23102443
2444
2445//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign,
2446// lround, llround, lrint, llrint
2447// So far this is only non-complicated type functions.
2448const char *float_op_to_name(BuiltinFnId op, bool llvm_name) {
2449 const bool b = llvm_name;
2450
2451 switch (op) {
2452 case BuiltinFnIdSqrt:
2453 return "sqrt";
2454 case BuiltinFnIdSin:
2455 return "sin";
2456 case BuiltinFnIdCos:
2457 return "cos";
2458 case BuiltinFnIdExp:
2459 return "exp";
2460 case BuiltinFnIdExp2:
2461 return "exp2";
2462 case BuiltinFnIdLn:
2463 return b ? "log" : "ln";
2464 case BuiltinFnIdLog10:
2465 return "log10";
2466 case BuiltinFnIdLog2:
2467 return "log2";
2468 case BuiltinFnIdFabs:
2469 return "fabs";
2470 case BuiltinFnIdFloor:
2471 return "floor";
2472 case BuiltinFnIdCeil:
2473 return "ceil";
2474 case BuiltinFnIdTrunc:
2475 return "trunc";
2476 case BuiltinFnIdNearbyInt:
2477 return b ? "nearbyint" : "nearbyInt";
2478 case BuiltinFnIdRound:
2479 return "round";
2480 default:
2481 zig_unreachable();
2482 }
2483}
2484
2485static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op1, BuiltinFnId op) {
2486 IrInstructionFloatOp *instruction = ir_build_instruction<IrInstructionFloatOp>(irb, scope, source_node);
2487 instruction->type = type;
2488 instruction->op1 = op1;
2489 instruction->op = op;
2490
2491 if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
2492 ir_ref_instruction(op1, irb->current_basic_block);
2493
2494 return &instruction->base;
2495}
2496
2497static IrInstruction *ir_build_mul_add(IrBuilder *irb, Scope *scope, AstNode *source_node,
2498 IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2, IrInstruction *op3) {
2499 IrInstructionMulAdd *instruction = ir_build_instruction<IrInstructionMulAdd>(irb, scope, source_node);
2500 instruction->type_value = type_value;
2501 instruction->op1 = op1;
2502 instruction->op2 = op2;
2503 instruction->op3 = op3;
2504
2505 ir_ref_instruction(type_value, irb->current_basic_block);
2506 ir_ref_instruction(op1, irb->current_basic_block);
2507 ir_ref_instruction(op2, irb->current_basic_block);
2508 ir_ref_instruction(op3, irb->current_basic_block);
2509
2510 return &instruction->base;
2511}
2512
2311static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {2513static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {
2312 IrInstructionAlignOf *instruction = ir_build_instruction<IrInstructionAlignOf>(irb, scope, source_node);2514 IrInstructionAlignOf *instruction = ir_build_instruction<IrInstructionAlignOf>(irb, scope, source_node);
2313 instruction->type_value = type_value;2515 instruction->type_value = type_value;
...@@ -2317,34 +2519,49 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s...@@ -2317,34 +2519,49 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s
2317 return &instruction->base;2519 return &instruction->base;
2318}2520}
23192521
2320static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *source_node,2522static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2321 IrInstruction *value)2523 IrInstruction *base_ptr, bool resolve_err_set)
2322{2524{
2323 IrInstructionTestErr *instruction = ir_build_instruction<IrInstructionTestErr>(irb, scope, source_node);2525 IrInstructionTestErrSrc *instruction = ir_build_instruction<IrInstructionTestErrSrc>(irb, scope, source_node);
2324 instruction->value = value;2526 instruction->base_ptr = base_ptr;
2527 instruction->resolve_err_set = resolve_err_set;
23252528
2326 ir_ref_instruction(value, irb->current_basic_block);2529 ir_ref_instruction(base_ptr, irb->current_basic_block);
23272530
2328 return &instruction->base;2531 return &instruction->base;
2329}2532}
23302533
2331static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,2534static IrInstruction *ir_build_test_err_gen(IrAnalyze *ira, IrInstruction *source_instruction,
2332 IrInstruction *err_union)2535 IrInstruction *err_union)
2333{2536{
2334 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);2537 IrInstructionTestErrGen *instruction = ir_build_instruction<IrInstructionTestErrGen>(
2538 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2539 instruction->base.value.type = ira->codegen->builtin_types.entry_bool;
2335 instruction->err_union = err_union;2540 instruction->err_union = err_union;
23362541
2337 ir_ref_instruction(err_union, irb->current_basic_block);2542 ir_ref_instruction(err_union, ira->new_irb.current_basic_block);
2543
2544 return &instruction->base;
2545}
2546
2547static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
2548 IrInstruction *err_union_ptr)
2549{
2550 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);
2551 instruction->err_union_ptr = err_union_ptr;
2552
2553 ir_ref_instruction(err_union_ptr, irb->current_basic_block);
23382554
2339 return &instruction->base;2555 return &instruction->base;
2340}2556}
23412557
2342static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope, AstNode *source_node,2558static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope, AstNode *source_node,
2343 IrInstruction *value, bool safety_check_on)2559 IrInstruction *value, bool safety_check_on, bool initializing)
2344{2560{
2345 IrInstructionUnwrapErrPayload *instruction = ir_build_instruction<IrInstructionUnwrapErrPayload>(irb, scope, source_node);2561 IrInstructionUnwrapErrPayload *instruction = ir_build_instruction<IrInstructionUnwrapErrPayload>(irb, scope, source_node);
2346 instruction->value = value;2562 instruction->value = value;
2347 instruction->safety_check_on = safety_check_on;2563 instruction->safety_check_on = safety_check_on;
2564 instruction->initializing = initializing;
23482565
2349 ir_ref_instruction(value, irb->current_basic_block);2566 ir_ref_instruction(value, irb->current_basic_block);
23502567
...@@ -2414,28 +2631,28 @@ static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *sourc...@@ -2414,28 +2631,28 @@ static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *sourc
2414}2631}
24152632
2416static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *source_instruction,2633static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *source_instruction,
2417 IrInstruction *ptr, ZigType *ty)2634 IrInstruction *ptr, ZigType *ty, IrInstruction *result_loc)
2418{2635{
2419 IrInstructionLoadPtrGen *instruction = ir_build_instruction<IrInstructionLoadPtrGen>(2636 IrInstructionLoadPtrGen *instruction = ir_build_instruction<IrInstructionLoadPtrGen>(
2420 &ira->new_irb, source_instruction->scope, source_instruction->source_node);2637 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2421 instruction->base.value.type = ty;2638 instruction->base.value.type = ty;
2422 instruction->ptr = ptr;2639 instruction->ptr = ptr;
2640 instruction->result_loc = result_loc;
24232641
2424 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);2642 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
2643 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
24252644
2426 return &instruction->base;2645 return &instruction->base;
2427}2646}
24282647
2429static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,2648static IrInstruction *ir_build_bit_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2430 IrInstruction *dest_type, IrInstruction *value)2649 IrInstruction *operand, ResultLocBitCast *result_loc_bit_cast)
2431{2650{
2432 IrInstructionBitCast *instruction = ir_build_instruction<IrInstructionBitCast>(2651 IrInstructionBitCastSrc *instruction = ir_build_instruction<IrInstructionBitCastSrc>(irb, scope, source_node);
2433 irb, scope, source_node);2652 instruction->operand = operand;
2434 instruction->dest_type = dest_type;2653 instruction->result_loc_bit_cast = result_loc_bit_cast;
2435 instruction->value = value;
24362654
2437 ir_ref_instruction(dest_type, irb->current_basic_block);2655 ir_ref_instruction(operand, irb->current_basic_block);
2438 ir_ref_instruction(value, irb->current_basic_block);
24392656
2440 return &instruction->base;2657 return &instruction->base;
2441}2658}
...@@ -2587,11 +2804,8 @@ static IrInstruction *ir_build_type_name(IrBuilder *irb, Scope *scope, AstNode *...@@ -2587,11 +2804,8 @@ static IrInstruction *ir_build_type_name(IrBuilder *irb, Scope *scope, AstNode *
2587 return &instruction->base;2804 return &instruction->base;
2588}2805}
25892806
2590static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node,2807static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) {
2591 Tld *tld, LVal lval)2808 IrInstructionDeclRef *instruction = ir_build_instruction<IrInstructionDeclRef>(irb, scope, source_node);
2592{
2593 IrInstructionDeclRef *instruction = ir_build_instruction<IrInstructionDeclRef>(
2594 irb, scope, source_node);
2595 instruction->tld = tld;2809 instruction->tld = tld;
2596 instruction->lval = lval;2810 instruction->lval = lval;
25972811
...@@ -2719,6 +2933,53 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode...@@ -2719,6 +2933,53 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode
2719 return &instruction->base;2933 return &instruction->base;
2720}2934}
27212935
2936static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
2937 IrInstruction *dest_type, IrInstruction *target, ResultLoc *result_loc)
2938{
2939 IrInstructionImplicitCast *instruction = ir_build_instruction<IrInstructionImplicitCast>(irb, scope, source_node);
2940 instruction->dest_type = dest_type;
2941 instruction->target = target;
2942 instruction->result_loc = result_loc;
2943
2944 ir_ref_instruction(dest_type, irb->current_basic_block);
2945 ir_ref_instruction(target, irb->current_basic_block);
2946
2947 return &instruction->base;
2948}
2949
2950static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstNode *source_node,
2951 ResultLoc *result_loc, IrInstruction *ty)
2952{
2953 IrInstructionResolveResult *instruction = ir_build_instruction<IrInstructionResolveResult>(irb, scope, source_node);
2954 instruction->result_loc = result_loc;
2955 instruction->ty = ty;
2956
2957 ir_ref_instruction(ty, irb->current_basic_block);
2958
2959 return &instruction->base;
2960}
2961
2962static IrInstruction *ir_build_reset_result(IrBuilder *irb, Scope *scope, AstNode *source_node,
2963 ResultLoc *result_loc)
2964{
2965 IrInstructionResetResult *instruction = ir_build_instruction<IrInstructionResetResult>(irb, scope, source_node);
2966 instruction->result_loc = result_loc;
2967
2968 return &instruction->base;
2969}
2970
2971static IrInstruction *ir_build_result_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
2972 ResultLoc *result_loc, IrInstruction *result)
2973{
2974 IrInstructionResultPtr *instruction = ir_build_instruction<IrInstructionResultPtr>(irb, scope, source_node);
2975 instruction->result_loc = result_loc;
2976 instruction->result = result;
2977
2978 ir_ref_instruction(result, irb->current_basic_block);
2979
2980 return &instruction->base;
2981}
2982
2722static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {2983static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2723 IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);2984 IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);
27242985
...@@ -3013,17 +3274,6 @@ static IrInstruction *ir_build_mark_err_ret_trace_ptr(IrBuilder *irb, Scope *sco...@@ -3013,17 +3274,6 @@ static IrInstruction *ir_build_mark_err_ret_trace_ptr(IrBuilder *irb, Scope *sco
3013 return &instruction->base;3274 return &instruction->base;
3014}3275}
30153276
3016static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
3017 IrInstructionSqrt *instruction = ir_build_instruction<IrInstructionSqrt>(irb, scope, source_node);
3018 instruction->type = type;
3019 instruction->op = op;
3020
3021 if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
3022 ir_ref_instruction(op, irb->current_basic_block);
3023
3024 return &instruction->base;
3025}
3026
3027static IrInstruction *ir_build_has_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,3277static IrInstruction *ir_build_has_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,
3028 IrInstruction *container, IrInstruction *name)3278 IrInstruction *container, IrInstruction *name)
3029{3279{
...@@ -3058,16 +3308,31 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,...@@ -3058,16 +3308,31 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
3058}3308}
30593309
3060static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,3310static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
3061 IrInstruction *vector, ZigType *result_type)3311 ZigType *result_type, IrInstruction *vector, IrInstruction *result_loc)
3062{3312{
3063 IrInstructionVectorToArray *instruction = ir_build_instruction<IrInstructionVectorToArray>(&ira->new_irb,3313 IrInstructionVectorToArray *instruction = ir_build_instruction<IrInstructionVectorToArray>(&ira->new_irb,
3064 source_instruction->scope, source_instruction->source_node);3314 source_instruction->scope, source_instruction->source_node);
3065 instruction->base.value.type = result_type;3315 instruction->base.value.type = result_type;
3066 instruction->vector = vector;3316 instruction->vector = vector;
3317 instruction->result_loc = result_loc;
30673318
3068 ir_ref_instruction(vector, ira->new_irb.current_basic_block);3319 ir_ref_instruction(vector, ira->new_irb.current_basic_block);
3320 ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
3321
3322 return &instruction->base;
3323}
3324
3325static IrInstruction *ir_build_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instruction,
3326 ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc)
3327{
3328 IrInstructionPtrOfArrayToSlice *instruction = ir_build_instruction<IrInstructionPtrOfArrayToSlice>(&ira->new_irb,
3329 source_instruction->scope, source_instruction->source_node);
3330 instruction->base.value.type = result_type;
3331 instruction->operand = operand;
3332 instruction->result_loc = result_loc;
30693333
3070 ir_add_alloca(ira, &instruction->base, result_type);3334 ir_ref_instruction(operand, ira->new_irb.current_basic_block);
3335 ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
30713336
3072 return &instruction->base;3337 return &instruction->base;
3073}3338}
...@@ -3111,18 +3376,57 @@ static IrInstruction *ir_build_assert_non_null(IrAnalyze *ira, IrInstruction *so...@@ -3111,18 +3376,57 @@ static IrInstruction *ir_build_assert_non_null(IrAnalyze *ira, IrInstruction *so
3111 return &instruction->base;3376 return &instruction->base;
3112}3377}
31133378
3114static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {3379static IrInstruction *ir_build_alloca_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
3115 results[ReturnKindUnconditional] = 0;3380 IrInstruction *align, const char *name_hint, IrInstruction *is_comptime)
3116 results[ReturnKindError] = 0;3381{
3382 IrInstructionAllocaSrc *instruction = ir_build_instruction<IrInstructionAllocaSrc>(irb, scope, source_node);
3383 instruction->base.is_gen = true;
3384 instruction->align = align;
3385 instruction->name_hint = name_hint;
3386 instruction->is_comptime = is_comptime;
31173387
3118 Scope *scope = inner_scope;3388 if (align != nullptr) ir_ref_instruction(align, irb->current_basic_block);
3389 if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block);
31193390
3120 while (scope != outer_scope) {3391 return &instruction->base;
3121 assert(scope);3392}
3122 switch (scope->id) {3393
3123 case ScopeIdDefer: {3394static IrInstructionAllocaGen *ir_create_alloca_gen(IrAnalyze *ira, IrInstruction *source_instruction,
3124 AstNode *defer_node = scope->source_node;3395 uint32_t align, const char *name_hint)
3125 assert(defer_node->type == NodeTypeDefer);3396{
3397 IrInstructionAllocaGen *instruction = ir_create_instruction<IrInstructionAllocaGen>(&ira->new_irb,
3398 source_instruction->scope, source_instruction->source_node);
3399 instruction->align = align;
3400 instruction->name_hint = name_hint;
3401
3402 return instruction;
3403}
3404
3405static IrInstruction *ir_build_end_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
3406 IrInstruction *value, ResultLoc *result_loc)
3407{
3408 IrInstructionEndExpr *instruction = ir_build_instruction<IrInstructionEndExpr>(irb, scope, source_node);
3409 instruction->base.is_gen = true;
3410 instruction->value = value;
3411 instruction->result_loc = result_loc;
3412
3413 ir_ref_instruction(value, irb->current_basic_block);
3414
3415 return &instruction->base;
3416}
3417
3418static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
3419 results[ReturnKindUnconditional] = 0;
3420 results[ReturnKindError] = 0;
3421
3422 Scope *scope = inner_scope;
3423
3424 while (scope != outer_scope) {
3425 assert(scope);
3426 switch (scope->id) {
3427 case ScopeIdDefer: {
3428 AstNode *defer_node = scope->source_node;
3429 assert(defer_node->type == NodeTypeDefer);
3126 ReturnKind defer_kind = defer_node->data.defer.kind;3430 ReturnKind defer_kind = defer_node->data.defer.kind;
3127 results[defer_kind] += 1;3431 results[defer_kind] += 1;
3128 scope = scope->parent;3432 scope = scope->parent;
...@@ -3211,6 +3515,7 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {...@@ -3211,6 +3515,7 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
3211}3515}
32123516
3213static void ir_set_cursor_at_end_and_append_block(IrBuilder *irb, IrBasicBlock *basic_block) {3517static void ir_set_cursor_at_end_and_append_block(IrBuilder *irb, IrBasicBlock *basic_block) {
3518 basic_block->index = irb->exec->basic_block_list.length;
3214 irb->exec->basic_block_list.append(basic_block);3519 irb->exec->basic_block_list.append(basic_block);
3215 ir_set_cursor_at_end(irb, basic_block);3520 ir_set_cursor_at_end(irb, basic_block);
3216}3521}
...@@ -3299,7 +3604,7 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode...@@ -3299,7 +3604,7 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode
3299 return ir_build_cond_br(irb, scope, node, is_canceled_bool, irb->exec->coro_final_cleanup_block, irb->exec->coro_early_final, is_comptime);3604 return ir_build_cond_br(irb, scope, node, is_canceled_bool, irb->exec->coro_final_cleanup_block, irb->exec->coro_early_final, is_comptime);
3300}3605}
33013606
3302static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {3607static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
3303 assert(node->type == NodeTypeReturnExpr);3608 assert(node->type == NodeTypeReturnExpr);
33043609
3305 ZigFn *fn_entry = exec_fn_entry(irb->exec);3610 ZigFn *fn_entry = exec_fn_entry(irb->exec);
...@@ -3323,12 +3628,16 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3323,12 +3628,16 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3323 switch (node->data.return_expr.kind) {3628 switch (node->data.return_expr.kind) {
3324 case ReturnKindUnconditional:3629 case ReturnKindUnconditional:
3325 {3630 {
3631 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);
3632 result_loc_ret->base.id = ResultLocIdReturn;
3633 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
3634
3326 IrInstruction *return_value;3635 IrInstruction *return_value;
3327 if (expr_node) {3636 if (expr_node) {
3328 // Temporarily set this so that if we return a type it gets the name of the function3637 // Temporarily set this so that if we return a type it gets the name of the function
3329 ZigFn *prev_name_fn = irb->exec->name_fn;3638 ZigFn *prev_name_fn = irb->exec->name_fn;
3330 irb->exec->name_fn = exec_fn_entry(irb->exec);3639 irb->exec->name_fn = exec_fn_entry(irb->exec);
3331 return_value = ir_gen_node(irb, expr_node, scope);3640 return_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_ret->base);
3332 irb->exec->name_fn = prev_name_fn;3641 irb->exec->name_fn = prev_name_fn;
3333 if (return_value == irb->codegen->invalid_instruction)3642 if (return_value == irb->codegen->invalid_instruction)
3334 return irb->codegen->invalid_instruction;3643 return irb->codegen->invalid_instruction;
...@@ -3346,7 +3655,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3346,7 +3655,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3346 ir_gen_defers_for_block(irb, scope, outer_scope, false);3655 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3347 }3656 }
33483657
3349 IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);3658 IrInstruction *ret_ptr = ir_build_result_ptr(irb, scope, node, &result_loc_ret->base,
3659 return_value);
3660 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, ret_ptr, false);
33503661
3351 bool should_inline = ir_should_inline(irb->exec, scope);3662 bool should_inline = ir_should_inline(irb->exec, scope);
3352 IrInstruction *is_comptime;3663 IrInstruction *is_comptime;
...@@ -3375,21 +3686,24 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3375,21 +3686,24 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3375 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);3686 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
33763687
3377 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);3688 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
3378 return ir_gen_async_return(irb, scope, node, return_value, false);3689 IrInstruction *result = ir_gen_async_return(irb, scope, node, return_value, false);
3690 result_loc_ret->base.source_instruction = result;
3691 return result;
3379 } else {3692 } else {
3380 // generate unconditional defers3693 // generate unconditional defers
3381 ir_gen_defers_for_block(irb, scope, outer_scope, false);3694 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3382 return ir_gen_async_return(irb, scope, node, return_value, false);3695 IrInstruction *result = ir_gen_async_return(irb, scope, node, return_value, false);
3696 result_loc_ret->base.source_instruction = result;
3697 return result;
3383 }3698 }
3384 }3699 }
3385 case ReturnKindError:3700 case ReturnKindError:
3386 {3701 {
3387 assert(expr_node);3702 assert(expr_node);
3388 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);3703 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
3389 if (err_union_ptr == irb->codegen->invalid_instruction)3704 if (err_union_ptr == irb->codegen->invalid_instruction)
3390 return irb->codegen->invalid_instruction;3705 return irb->codegen->invalid_instruction;
3391 IrInstruction *err_union_val = ir_build_load_ptr(irb, scope, node, err_union_ptr);3706 IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true);
3392 IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_val);
33933707
3394 IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");3708 IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");
3395 IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");3709 IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");
...@@ -3404,19 +3718,27 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3404,19 +3718,27 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
34043718
3405 ir_set_cursor_at_end_and_append_block(irb, return_block);3719 ir_set_cursor_at_end_and_append_block(irb, return_block);
3406 if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {3720 if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {
3407 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);3721 IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
3722 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
3723
3724 ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);
3725 result_loc_ret->base.id = ResultLocIdReturn;
3726 ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
3727 ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base);
3728
3408 if (irb->codegen->have_err_ret_tracing && !should_inline) {3729 if (irb->codegen->have_err_ret_tracing && !should_inline) {
3409 ir_build_save_err_ret_addr(irb, scope, node);3730 ir_build_save_err_ret_addr(irb, scope, node);
3410 }3731 }
3411 ir_gen_async_return(irb, scope, node, err_val, false);3732 IrInstruction *ret_inst = ir_gen_async_return(irb, scope, node, err_val, false);
3733 result_loc_ret->base.source_instruction = ret_inst;
3412 }3734 }
34133735
3414 ir_set_cursor_at_end_and_append_block(irb, continue_block);3736 ir_set_cursor_at_end_and_append_block(irb, continue_block);
3415 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);3737 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false, false);
3416 if (lval == LValPtr)3738 if (lval == LValPtr)
3417 return unwrapped_ptr;3739 return unwrapped_ptr;
3418 else3740 else
3419 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);3741 return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, unwrapped_ptr), result_loc);
3420 }3742 }
3421 }3743 }
3422 zig_unreachable();3744 zig_unreachable();
...@@ -3500,7 +3822,17 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n...@@ -3500,7 +3822,17 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n
3500 return var;3822 return var;
3501}3823}
35023824
3503static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node) {3825static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {
3826 ResultLocPeer *result = allocate<ResultLocPeer>(1);
3827 result->base.id = ResultLocIdPeer;
3828 result->base.source_instruction = peer_parent->base.source_instruction;
3829 result->parent = peer_parent;
3830 return result;
3831}
3832
3833static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node, LVal lval,
3834 ResultLoc *result_loc)
3835{
3504 assert(block_node->type == NodeTypeBlock);3836 assert(block_node->type == NodeTypeBlock);
35053837
3506 ZigList<IrInstruction *> incoming_values = {0};3838 ZigList<IrInstruction *> incoming_values = {0};
...@@ -3518,15 +3850,24 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3518,15 +3850,24 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
35183850
3519 if (block_node->data.block.statements.length == 0) {3851 if (block_node->data.block.statements.length == 0) {
3520 // {}3852 // {}
3521 return ir_build_const_void(irb, child_scope, block_node);3853 return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc);
3522 }3854 }
35233855
3524 if (block_node->data.block.name != nullptr) {3856 if (block_node->data.block.name != nullptr) {
3857 scope_block->lval = lval;
3525 scope_block->incoming_blocks = &incoming_blocks;3858 scope_block->incoming_blocks = &incoming_blocks;
3526 scope_block->incoming_values = &incoming_values;3859 scope_block->incoming_values = &incoming_values;
3527 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");3860 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
3528 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,3861 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
3529 ir_should_inline(irb->exec, parent_scope));3862 ir_should_inline(irb->exec, parent_scope));
3863
3864 scope_block->peer_parent = allocate<ResultLocPeerParent>(1);
3865 scope_block->peer_parent->base.id = ResultLocIdPeerParent;
3866 scope_block->peer_parent->base.source_instruction = scope_block->is_comptime;
3867 scope_block->peer_parent->end_bb = scope_block->end_block;
3868 scope_block->peer_parent->is_comptime = scope_block->is_comptime;
3869 scope_block->peer_parent->parent = result_loc;
3870 ir_build_reset_result(irb, parent_scope, block_node, &scope_block->peer_parent->base);
3530 }3871 }
35313872
3532 bool is_continuation_unreachable = false;3873 bool is_continuation_unreachable = false;
...@@ -3540,6 +3881,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3540,6 +3881,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3540 // keep the last noreturn statement value around in case we need to return it3881 // keep the last noreturn statement value around in case we need to return it
3541 noreturn_return_value = statement_value;3882 noreturn_return_value = statement_value;
3542 }3883 }
3884 // This logic must be kept in sync with
3885 // [STMT_EXPR_TEST_THING] <--- (search this token)
3543 if (statement_node->type == NodeTypeDefer && statement_value != irb->codegen->invalid_instruction) {3886 if (statement_node->type == NodeTypeDefer && statement_value != irb->codegen->invalid_instruction) {
3544 // defer starts a new scope3887 // defer starts a new scope
3545 child_scope = statement_node->data.defer.child_scope;3888 child_scope = statement_node->data.defer.child_scope;
...@@ -3560,21 +3903,41 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3560,21 +3903,41 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3560 return noreturn_return_value;3903 return noreturn_return_value;
3561 }3904 }
35623905
3906 if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) {
3907 scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block;
3908 }
3563 ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);3909 ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);
3564 return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);3910 IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
3911 incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
3912 return ir_expr_wrap(irb, parent_scope, phi, result_loc);
3565 } else {3913 } else {
3566 incoming_blocks.append(irb->current_basic_block);3914 incoming_blocks.append(irb->current_basic_block);
3567 incoming_values.append(ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)));3915 IrInstruction *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node));
3916
3917 if (scope_block->peer_parent != nullptr) {
3918 ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent);
3919 scope_block->peer_parent->peers.append(peer_result);
3920 ir_build_end_expr(irb, parent_scope, block_node, else_expr_result, &peer_result->base);
3921
3922 if (scope_block->peer_parent->peers.length != 0) {
3923 scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block;
3924 }
3925 }
3926
3927 incoming_values.append(else_expr_result);
3568 }3928 }
35693929
3570 if (block_node->data.block.name != nullptr) {3930 if (block_node->data.block.name != nullptr) {
3571 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);3931 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
3572 ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));3932 ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));
3573 ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);3933 ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);
3574 return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);3934 IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
3935 incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
3936 return ir_expr_wrap(irb, parent_scope, phi, result_loc);
3575 } else {3937 } else {
3576 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);3938 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
3577 return ir_mark_gen(ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)));3939 IrInstruction *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));
3940 return ir_lval_wrap(irb, parent_scope, void_inst, lval, result_loc);
3578 }3941 }
3579}3942}
35803943
...@@ -3594,7 +3957,7 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no...@@ -3594,7 +3957,7 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no
3594}3957}
35953958
3596static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {3959static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {
3597 IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr);3960 IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
3598 IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);3961 IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
35993962
3600 if (lvalue == irb->codegen->invalid_instruction || rvalue == irb->codegen->invalid_instruction)3963 if (lvalue == irb->codegen->invalid_instruction || rvalue == irb->codegen->invalid_instruction)
...@@ -3605,7 +3968,7 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3605,7 +3968,7 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node)
3605}3968}
36063969
3607static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) {3970static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) {
3608 IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr);3971 IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
3609 if (lvalue == irb->codegen->invalid_instruction)3972 if (lvalue == irb->codegen->invalid_instruction)
3610 return lvalue;3973 return lvalue;
3611 IrInstruction *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue);3974 IrInstruction *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue);
...@@ -3656,7 +4019,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node...@@ -3656,7 +4019,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node
3656 incoming_blocks[0] = post_val1_block;4019 incoming_blocks[0] = post_val1_block;
3657 incoming_blocks[1] = post_val2_block;4020 incoming_blocks[1] = post_val2_block;
36584021
3659 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);4022 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
3660}4023}
36614024
3662static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *node) {4025static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -3698,16 +4061,51 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3698,16 +4061,51 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
3698 incoming_blocks[0] = post_val1_block;4061 incoming_blocks[0] = post_val1_block;
3699 incoming_blocks[1] = post_val2_block;4062 incoming_blocks[1] = post_val2_block;
37004063
3701 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);4064 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
4065}
4066
4067static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
4068 IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
4069{
4070 ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);
4071 peer_parent->base.id = ResultLocIdPeerParent;
4072 peer_parent->base.source_instruction = cond_br_inst;
4073 peer_parent->end_bb = end_block;
4074 peer_parent->is_comptime = is_comptime;
4075 peer_parent->parent = parent;
4076
4077 IrInstruction *popped_inst = irb->current_basic_block->instruction_list.pop();
4078 ir_assert(popped_inst == cond_br_inst, cond_br_inst);
4079
4080 ir_build_reset_result(irb, cond_br_inst->scope, cond_br_inst->source_node, &peer_parent->base);
4081 irb->current_basic_block->instruction_list.append(popped_inst);
4082
4083 return peer_parent;
4084}
4085
4086static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
4087 IrBasicBlock *else_block, IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
4088{
4089 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, parent, is_comptime);
4090
4091 peer_parent->peers.append(create_peer_result(peer_parent));
4092 peer_parent->peers.last()->next_bb = else_block;
4093
4094 peer_parent->peers.append(create_peer_result(peer_parent));
4095 peer_parent->peers.last()->next_bb = end_block;
4096
4097 return peer_parent;
3702}4098}
37034099
3704static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) {4100static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,
4101 ResultLoc *result_loc)
4102{
3705 assert(node->type == NodeTypeBinOpExpr);4103 assert(node->type == NodeTypeBinOpExpr);
37064104
3707 AstNode *op1_node = node->data.bin_op_expr.op1;4105 AstNode *op1_node = node->data.bin_op_expr.op1;
3708 AstNode *op2_node = node->data.bin_op_expr.op2;4106 AstNode *op2_node = node->data.bin_op_expr.op2;
37094107
3710 IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr);4108 IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr);
3711 if (maybe_ptr == irb->codegen->invalid_instruction)4109 if (maybe_ptr == irb->codegen->invalid_instruction)
3712 return irb->codegen->invalid_instruction;4110 return irb->codegen->invalid_instruction;
37134111
...@@ -3724,10 +4122,14 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3724,10 +4122,14 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
3724 IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull");4122 IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull");
3725 IrBasicBlock *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull");4123 IrBasicBlock *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull");
3726 IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd");4124 IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd");
3727 ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);4125 IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);
4126
4127 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block,
4128 result_loc, is_comptime);
37284129
3729 ir_set_cursor_at_end_and_append_block(irb, null_block);4130 ir_set_cursor_at_end_and_append_block(irb, null_block);
3730 IrInstruction *null_result = ir_gen_node(irb, op2_node, parent_scope);4131 IrInstruction *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, LValNone,
4132 &peer_parent->peers.at(0)->base);
3731 if (null_result == irb->codegen->invalid_instruction)4133 if (null_result == irb->codegen->invalid_instruction)
3732 return irb->codegen->invalid_instruction;4134 return irb->codegen->invalid_instruction;
3733 IrBasicBlock *after_null_block = irb->current_basic_block;4135 IrBasicBlock *after_null_block = irb->current_basic_block;
...@@ -3735,8 +4137,9 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3735,8 +4137,9 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
3735 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));4137 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
37364138
3737 ir_set_cursor_at_end_and_append_block(irb, ok_block);4139 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3738 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false);4140 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false, false);
3739 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);4141 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
4142 ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
3740 IrBasicBlock *after_ok_block = irb->current_basic_block;4143 IrBasicBlock *after_ok_block = irb->current_basic_block;
3741 ir_build_br(irb, parent_scope, node, end_block, is_comptime);4144 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
37424145
...@@ -3747,7 +4150,8 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3747,7 +4150,8 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
3747 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);4150 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
3748 incoming_blocks[0] = after_null_block;4151 incoming_blocks[0] = after_null_block;
3749 incoming_blocks[1] = after_ok_block;4152 incoming_blocks[1] = after_ok_block;
3750 return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);4153 IrInstruction *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent);
4154 return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc);
3751}4155}
37524156
3753static IrInstruction *ir_gen_error_union(IrBuilder *irb, Scope *parent_scope, AstNode *node) {4157static IrInstruction *ir_gen_error_union(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
...@@ -3767,7 +4171,7 @@ static IrInstruction *ir_gen_error_union(IrBuilder *irb, Scope *parent_scope, As...@@ -3767,7 +4171,7 @@ static IrInstruction *ir_gen_error_union(IrBuilder *irb, Scope *parent_scope, As
3767 return ir_build_error_union(irb, parent_scope, node, err_set, payload);4171 return ir_build_error_union(irb, parent_scope, node, err_set, payload);
3768}4172}
37694173
3770static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) {4174static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
3771 assert(node->type == NodeTypeBinOpExpr);4175 assert(node->type == NodeTypeBinOpExpr);
37724176
3773 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;4177 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
...@@ -3775,87 +4179,87 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3775,87 +4179,87 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
3775 case BinOpTypeInvalid:4179 case BinOpTypeInvalid:
3776 zig_unreachable();4180 zig_unreachable();
3777 case BinOpTypeAssign:4181 case BinOpTypeAssign:
3778 return ir_gen_assign(irb, scope, node);4182 return ir_lval_wrap(irb, scope, ir_gen_assign(irb, scope, node), lval, result_loc);
3779 case BinOpTypeAssignTimes:4183 case BinOpTypeAssignTimes:
3780 return ir_gen_assign_op(irb, scope, node, IrBinOpMult);4184 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMult), lval, result_loc);
3781 case BinOpTypeAssignTimesWrap:4185 case BinOpTypeAssignTimesWrap:
3782 return ir_gen_assign_op(irb, scope, node, IrBinOpMultWrap);4186 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMultWrap), lval, result_loc);
3783 case BinOpTypeAssignDiv:4187 case BinOpTypeAssignDiv:
3784 return ir_gen_assign_op(irb, scope, node, IrBinOpDivUnspecified);4188 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc);
3785 case BinOpTypeAssignMod:4189 case BinOpTypeAssignMod:
3786 return ir_gen_assign_op(irb, scope, node, IrBinOpRemUnspecified);4190 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc);
3787 case BinOpTypeAssignPlus:4191 case BinOpTypeAssignPlus:
3788 return ir_gen_assign_op(irb, scope, node, IrBinOpAdd);4192 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAdd), lval, result_loc);
3789 case BinOpTypeAssignPlusWrap:4193 case BinOpTypeAssignPlusWrap:
3790 return ir_gen_assign_op(irb, scope, node, IrBinOpAddWrap);4194 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAddWrap), lval, result_loc);
3791 case BinOpTypeAssignMinus:4195 case BinOpTypeAssignMinus:
3792 return ir_gen_assign_op(irb, scope, node, IrBinOpSub);4196 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSub), lval, result_loc);
3793 case BinOpTypeAssignMinusWrap:4197 case BinOpTypeAssignMinusWrap:
3794 return ir_gen_assign_op(irb, scope, node, IrBinOpSubWrap);4198 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSubWrap), lval, result_loc);
3795 case BinOpTypeAssignBitShiftLeft:4199 case BinOpTypeAssignBitShiftLeft:
3796 return ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftLeftLossy);4200 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc);
3797 case BinOpTypeAssignBitShiftRight:4201 case BinOpTypeAssignBitShiftRight:
3798 return ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftRightLossy);4202 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc);
3799 case BinOpTypeAssignBitAnd:4203 case BinOpTypeAssignBitAnd:
3800 return ir_gen_assign_op(irb, scope, node, IrBinOpBinAnd);4204 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinAnd), lval, result_loc);
3801 case BinOpTypeAssignBitXor:4205 case BinOpTypeAssignBitXor:
3802 return ir_gen_assign_op(irb, scope, node, IrBinOpBinXor);4206 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinXor), lval, result_loc);
3803 case BinOpTypeAssignBitOr:4207 case BinOpTypeAssignBitOr:
3804 return ir_gen_assign_op(irb, scope, node, IrBinOpBinOr);4208 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinOr), lval, result_loc);
3805 case BinOpTypeAssignMergeErrorSets:4209 case BinOpTypeAssignMergeErrorSets:
3806 return ir_gen_assign_op(irb, scope, node, IrBinOpMergeErrorSets);4210 return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMergeErrorSets), lval, result_loc);
3807 case BinOpTypeBoolOr:4211 case BinOpTypeBoolOr:
3808 return ir_gen_bool_or(irb, scope, node);4212 return ir_lval_wrap(irb, scope, ir_gen_bool_or(irb, scope, node), lval, result_loc);
3809 case BinOpTypeBoolAnd:4213 case BinOpTypeBoolAnd:
3810 return ir_gen_bool_and(irb, scope, node);4214 return ir_lval_wrap(irb, scope, ir_gen_bool_and(irb, scope, node), lval, result_loc);
3811 case BinOpTypeCmpEq:4215 case BinOpTypeCmpEq:
3812 return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq);4216 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq), lval, result_loc);
3813 case BinOpTypeCmpNotEq:4217 case BinOpTypeCmpNotEq:
3814 return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpNotEq);4218 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpNotEq), lval, result_loc);
3815 case BinOpTypeCmpLessThan:4219 case BinOpTypeCmpLessThan:
3816 return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessThan);4220 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessThan), lval, result_loc);
3817 case BinOpTypeCmpGreaterThan:4221 case BinOpTypeCmpGreaterThan:
3818 return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterThan);4222 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterThan), lval, result_loc);
3819 case BinOpTypeCmpLessOrEq:4223 case BinOpTypeCmpLessOrEq:
3820 return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessOrEq);4224 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessOrEq), lval, result_loc);
3821 case BinOpTypeCmpGreaterOrEq:4225 case BinOpTypeCmpGreaterOrEq:
3822 return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterOrEq);4226 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc);
3823 case BinOpTypeBinOr:4227 case BinOpTypeBinOr:
3824 return ir_gen_bin_op_id(irb, scope, node, IrBinOpBinOr);4228 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinOr), lval, result_loc);
3825 case BinOpTypeBinXor:4229 case BinOpTypeBinXor:
3826 return ir_gen_bin_op_id(irb, scope, node, IrBinOpBinXor);4230 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinXor), lval, result_loc);
3827 case BinOpTypeBinAnd:4231 case BinOpTypeBinAnd:
3828 return ir_gen_bin_op_id(irb, scope, node, IrBinOpBinAnd);4232 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinAnd), lval, result_loc);
3829 case BinOpTypeBitShiftLeft:4233 case BinOpTypeBitShiftLeft:
3830 return ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftLeftLossy);4234 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc);
3831 case BinOpTypeBitShiftRight:4235 case BinOpTypeBitShiftRight:
3832 return ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftRightLossy);4236 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc);
3833 case BinOpTypeAdd:4237 case BinOpTypeAdd:
3834 return ir_gen_bin_op_id(irb, scope, node, IrBinOpAdd);4238 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAdd), lval, result_loc);
3835 case BinOpTypeAddWrap:4239 case BinOpTypeAddWrap:
3836 return ir_gen_bin_op_id(irb, scope, node, IrBinOpAddWrap);4240 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAddWrap), lval, result_loc);
3837 case BinOpTypeSub:4241 case BinOpTypeSub:
3838 return ir_gen_bin_op_id(irb, scope, node, IrBinOpSub);4242 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSub), lval, result_loc);
3839 case BinOpTypeSubWrap:4243 case BinOpTypeSubWrap:
3840 return ir_gen_bin_op_id(irb, scope, node, IrBinOpSubWrap);4244 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSubWrap), lval, result_loc);
3841 case BinOpTypeMult:4245 case BinOpTypeMult:
3842 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMult);4246 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMult), lval, result_loc);
3843 case BinOpTypeMultWrap:4247 case BinOpTypeMultWrap:
3844 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMultWrap);4248 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMultWrap), lval, result_loc);
3845 case BinOpTypeDiv:4249 case BinOpTypeDiv:
3846 return ir_gen_bin_op_id(irb, scope, node, IrBinOpDivUnspecified);4250 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc);
3847 case BinOpTypeMod:4251 case BinOpTypeMod:
3848 return ir_gen_bin_op_id(irb, scope, node, IrBinOpRemUnspecified);4252 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc);
3849 case BinOpTypeArrayCat:4253 case BinOpTypeArrayCat:
3850 return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayCat);4254 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayCat), lval, result_loc);
3851 case BinOpTypeArrayMult:4255 case BinOpTypeArrayMult:
3852 return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult);4256 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult), lval, result_loc);
3853 case BinOpTypeMergeErrorSets:4257 case BinOpTypeMergeErrorSets:
3854 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);4258 return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets), lval, result_loc);
3855 case BinOpTypeUnwrapOptional:4259 case BinOpTypeUnwrapOptional:
3856 return ir_gen_orelse(irb, scope, node);4260 return ir_gen_orelse(irb, scope, node, lval, result_loc);
3857 case BinOpTypeErrorUnion:4261 case BinOpTypeErrorUnion:
3858 return ir_gen_error_union(irb, scope, node);4262 return ir_lval_wrap(irb, scope, ir_gen_error_union(irb, scope, node), lval, result_loc);
3859 }4263 }
3860 zig_unreachable();4264 zig_unreachable();
3861}4265}
...@@ -3900,12 +4304,12 @@ static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode...@@ -3900,12 +4304,12 @@ static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode
3900 TldVar *tld_var = allocate<TldVar>(1);4304 TldVar *tld_var = allocate<TldVar>(1);
3901 init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base);4305 init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base);
3902 tld_var->base.resolution = TldResolutionInvalid;4306 tld_var->base.resolution = TldResolutionInvalid;
3903 tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false, 4307 tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false,
3904 &g->invalid_instruction->value, &tld_var->base, g->builtin_types.entry_invalid);4308 &g->invalid_instruction->value, &tld_var->base, g->builtin_types.entry_invalid);
3905 scope_decls->decl_table.put(var_name, &tld_var->base);4309 scope_decls->decl_table.put(var_name, &tld_var->base);
3906}4310}
39074311
3908static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {4312static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
3909 Error err;4313 Error err;
3910 assert(node->type == NodeTypeSymbol);4314 assert(node->type == NodeTypeSymbol);
39114315
...@@ -3939,7 +4343,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3939,7 +4343,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
3939 if (lval == LValPtr) {4343 if (lval == LValPtr) {
3940 return ir_build_ref(irb, scope, node, value, false, false);4344 return ir_build_ref(irb, scope, node, value, false, false);
3941 } else {4345 } else {
3942 return value;4346 return ir_expr_wrap(irb, scope, value, result_loc);
3943 }4347 }
3944 }4348 }
39454349
...@@ -3947,15 +4351,22 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3947,15 +4351,22 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
3947 ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope);4351 ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope);
3948 if (var) {4352 if (var) {
3949 IrInstruction *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope);4353 IrInstruction *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope);
3950 if (lval == LValPtr)4354 if (lval == LValPtr) {
3951 return var_ptr;4355 return var_ptr;
3952 else4356 } else {
3953 return ir_build_load_ptr(irb, scope, node, var_ptr);4357 return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, var_ptr), result_loc);
4358 }
3954 }4359 }
39554360
3956 Tld *tld = find_decl(irb->codegen, scope, variable_name);4361 Tld *tld = find_decl(irb->codegen, scope, variable_name);
3957 if (tld)4362 if (tld) {
3958 return ir_build_decl_ref(irb, scope, node, tld, lval);4363 IrInstruction *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval);
4364 if (lval == LValPtr) {
4365 return decl_ref;
4366 } else {
4367 return ir_expr_wrap(irb, scope, decl_ref, result_loc);
4368 }
4369 }
39594370
3960 if (get_container_scope(node->owner)->any_imports_failed) {4371 if (get_container_scope(node->owner)->any_imports_failed) {
3961 // skip the error message since we had a failing import in this file4372 // skip the error message since we had a failing import in this file
...@@ -3966,11 +4377,13 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3966,11 +4377,13 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
3966 return ir_build_undeclared_identifier(irb, scope, node, variable_name);4377 return ir_build_undeclared_identifier(irb, scope, node, variable_name);
3967}4378}
39684379
3969static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {4380static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
4381 ResultLoc *result_loc)
4382{
3970 assert(node->type == NodeTypeArrayAccessExpr);4383 assert(node->type == NodeTypeArrayAccessExpr);
39714384
3972 AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr;4385 AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr;
3973 IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr);4386 IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr, nullptr);
3974 if (array_ref_instruction == irb->codegen->invalid_instruction)4387 if (array_ref_instruction == irb->codegen->invalid_instruction)
3975 return array_ref_instruction;4388 return array_ref_instruction;
39764389
...@@ -3980,11 +4393,12 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode...@@ -3980,11 +4393,12 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode
3980 return subscript_instruction;4393 return subscript_instruction;
39814394
3982 IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction,4395 IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction,
3983 subscript_instruction, true, PtrLenSingle);4396 subscript_instruction, true, PtrLenSingle, nullptr);
3984 if (lval == LValPtr)4397 if (lval == LValPtr)
3985 return ptr_instruction;4398 return ptr_instruction;
39864399
3987 return ir_build_load_ptr(irb, scope, node, ptr_instruction);4400 IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
4401 return ir_expr_wrap(irb, scope, load_ptr, result_loc);
3988}4402}
39894403
3990static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode *node) {4404static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -3993,11 +4407,11 @@ static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode...@@ -3993,11 +4407,11 @@ static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode
3993 AstNode *container_ref_node = node->data.field_access_expr.struct_expr;4407 AstNode *container_ref_node = node->data.field_access_expr.struct_expr;
3994 Buf *field_name = node->data.field_access_expr.field_name;4408 Buf *field_name = node->data.field_access_expr.field_name;
39954409
3996 IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr);4410 IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr, nullptr);
3997 if (container_ref_instruction == irb->codegen->invalid_instruction)4411 if (container_ref_instruction == irb->codegen->invalid_instruction)
3998 return container_ref_instruction;4412 return container_ref_instruction;
39994413
4000 return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name);4414 return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name, false);
4001}4415}
40024416
4003static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *node, IrOverflowOp op) {4417static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *node, IrOverflowOp op) {
...@@ -4028,6 +4442,33 @@ static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *...@@ -4028,6 +4442,33 @@ static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *
4028 return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr);4442 return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr);
4029}4443}
40304444
4445static IrInstruction *ir_gen_mul_add(IrBuilder *irb, Scope *scope, AstNode *node) {
4446 assert(node->type == NodeTypeFnCallExpr);
4447
4448 AstNode *type_node = node->data.fn_call_expr.params.at(0);
4449 AstNode *op1_node = node->data.fn_call_expr.params.at(1);
4450 AstNode *op2_node = node->data.fn_call_expr.params.at(2);
4451 AstNode *op3_node = node->data.fn_call_expr.params.at(3);
4452
4453 IrInstruction *type_value = ir_gen_node(irb, type_node, scope);
4454 if (type_value == irb->codegen->invalid_instruction)
4455 return irb->codegen->invalid_instruction;
4456
4457 IrInstruction *op1 = ir_gen_node(irb, op1_node, scope);
4458 if (op1 == irb->codegen->invalid_instruction)
4459 return irb->codegen->invalid_instruction;
4460
4461 IrInstruction *op2 = ir_gen_node(irb, op2_node, scope);
4462 if (op2 == irb->codegen->invalid_instruction)
4463 return irb->codegen->invalid_instruction;
4464
4465 IrInstruction *op3 = ir_gen_node(irb, op3_node, scope);
4466 if (op3 == irb->codegen->invalid_instruction)
4467 return irb->codegen->invalid_instruction;
4468
4469 return ir_build_mul_add(irb, scope, node, type_value, op1, op2, op3);
4470}
4471
4031static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *node) {4472static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *node) {
4032 for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) {4473 for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) {
4033 if (it_scope->id == ScopeIdDecls) {4474 if (it_scope->id == ScopeIdDecls) {
...@@ -4043,7 +4484,9 @@ static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *no...@@ -4043,7 +4484,9 @@ static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *no
4043 zig_unreachable();4484 zig_unreachable();
4044}4485}
40454486
4046static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {4487static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
4488 ResultLoc *result_loc)
4489{
4047 assert(node->type == NodeTypeFnCallExpr);4490 assert(node->type == NodeTypeFnCallExpr);
40484491
4049 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;4492 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
...@@ -4079,7 +4522,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4079,7 +4522,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4079 return arg;4522 return arg;
40804523
4081 IrInstruction *type_of = ir_build_typeof(irb, scope, node, arg);4524 IrInstruction *type_of = ir_build_typeof(irb, scope, node, arg);
4082 return ir_lval_wrap(irb, scope, type_of, lval);4525 return ir_lval_wrap(irb, scope, type_of, lval, result_loc);
4083 }4526 }
4084 case BuiltinFnIdSetCold:4527 case BuiltinFnIdSetCold:
4085 {4528 {
...@@ -4089,7 +4532,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4089,7 +4532,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4089 return arg0_value;4532 return arg0_value;
40904533
4091 IrInstruction *set_cold = ir_build_set_cold(irb, scope, node, arg0_value);4534 IrInstruction *set_cold = ir_build_set_cold(irb, scope, node, arg0_value);
4092 return ir_lval_wrap(irb, scope, set_cold, lval);4535 return ir_lval_wrap(irb, scope, set_cold, lval, result_loc);
4093 }4536 }
4094 case BuiltinFnIdSetRuntimeSafety:4537 case BuiltinFnIdSetRuntimeSafety:
4095 {4538 {
...@@ -4099,7 +4542,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4099,7 +4542,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4099 return arg0_value;4542 return arg0_value;
41004543
4101 IrInstruction *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value);4544 IrInstruction *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value);
4102 return ir_lval_wrap(irb, scope, set_safety, lval);4545 return ir_lval_wrap(irb, scope, set_safety, lval, result_loc);
4103 }4546 }
4104 case BuiltinFnIdSetFloatMode:4547 case BuiltinFnIdSetFloatMode:
4105 {4548 {
...@@ -4109,7 +4552,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4109,7 +4552,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4109 return arg0_value;4552 return arg0_value;
41104553
4111 IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value);4554 IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value);
4112 return ir_lval_wrap(irb, scope, set_float_mode, lval);4555 return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc);
4113 }4556 }
4114 case BuiltinFnIdSizeof:4557 case BuiltinFnIdSizeof:
4115 {4558 {
...@@ -4119,7 +4562,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4119,7 +4562,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4119 return arg0_value;4562 return arg0_value;
41204563
4121 IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value);4564 IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value);
4122 return ir_lval_wrap(irb, scope, size_of, lval);4565 return ir_lval_wrap(irb, scope, size_of, lval, result_loc);
4123 }4566 }
4124 case BuiltinFnIdImport:4567 case BuiltinFnIdImport:
4125 {4568 {
...@@ -4129,12 +4572,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4129,12 +4572,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4129 return arg0_value;4572 return arg0_value;
41304573
4131 IrInstruction *import = ir_build_import(irb, scope, node, arg0_value);4574 IrInstruction *import = ir_build_import(irb, scope, node, arg0_value);
4132 return ir_lval_wrap(irb, scope, import, lval);4575 return ir_lval_wrap(irb, scope, import, lval, result_loc);
4133 }4576 }
4134 case BuiltinFnIdCImport:4577 case BuiltinFnIdCImport:
4135 {4578 {
4136 IrInstruction *c_import = ir_build_c_import(irb, scope, node);4579 IrInstruction *c_import = ir_build_c_import(irb, scope, node);
4137 return ir_lval_wrap(irb, scope, c_import, lval);4580 return ir_lval_wrap(irb, scope, c_import, lval, result_loc);
4138 }4581 }
4139 case BuiltinFnIdCInclude:4582 case BuiltinFnIdCInclude:
4140 {4583 {
...@@ -4149,7 +4592,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4149,7 +4592,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4149 }4592 }
41504593
4151 IrInstruction *c_include = ir_build_c_include(irb, scope, node, arg0_value);4594 IrInstruction *c_include = ir_build_c_include(irb, scope, node, arg0_value);
4152 return ir_lval_wrap(irb, scope, c_include, lval);4595 return ir_lval_wrap(irb, scope, c_include, lval, result_loc);
4153 }4596 }
4154 case BuiltinFnIdCDefine:4597 case BuiltinFnIdCDefine:
4155 {4598 {
...@@ -4169,7 +4612,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4169,7 +4612,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4169 }4612 }
41704613
4171 IrInstruction *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value);4614 IrInstruction *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value);
4172 return ir_lval_wrap(irb, scope, c_define, lval);4615 return ir_lval_wrap(irb, scope, c_define, lval, result_loc);
4173 }4616 }
4174 case BuiltinFnIdCUndef:4617 case BuiltinFnIdCUndef:
4175 {4618 {
...@@ -4184,7 +4627,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4184,7 +4627,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4184 }4627 }
41854628
4186 IrInstruction *c_undef = ir_build_c_undef(irb, scope, node, arg0_value);4629 IrInstruction *c_undef = ir_build_c_undef(irb, scope, node, arg0_value);
4187 return ir_lval_wrap(irb, scope, c_undef, lval);4630 return ir_lval_wrap(irb, scope, c_undef, lval, result_loc);
4188 }4631 }
4189 case BuiltinFnIdCompileErr:4632 case BuiltinFnIdCompileErr:
4190 {4633 {
...@@ -4194,7 +4637,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4194,7 +4637,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4194 return arg0_value;4637 return arg0_value;
41954638
4196 IrInstruction *compile_err = ir_build_compile_err(irb, scope, node, arg0_value);4639 IrInstruction *compile_err = ir_build_compile_err(irb, scope, node, arg0_value);
4197 return ir_lval_wrap(irb, scope, compile_err, lval);4640 return ir_lval_wrap(irb, scope, compile_err, lval, result_loc);
4198 }4641 }
4199 case BuiltinFnIdCompileLog:4642 case BuiltinFnIdCompileLog:
4200 {4643 {
...@@ -4208,7 +4651,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4208,7 +4651,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4208 }4651 }
42094652
4210 IrInstruction *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args);4653 IrInstruction *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args);
4211 return ir_lval_wrap(irb, scope, compile_log, lval);4654 return ir_lval_wrap(irb, scope, compile_log, lval, result_loc);
4212 }4655 }
4213 case BuiltinFnIdErrName:4656 case BuiltinFnIdErrName:
4214 {4657 {
...@@ -4218,7 +4661,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4218,7 +4661,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4218 return arg0_value;4661 return arg0_value;
42194662
4220 IrInstruction *err_name = ir_build_err_name(irb, scope, node, arg0_value);4663 IrInstruction *err_name = ir_build_err_name(irb, scope, node, arg0_value);
4221 return ir_lval_wrap(irb, scope, err_name, lval);4664 return ir_lval_wrap(irb, scope, err_name, lval, result_loc);
4222 }4665 }
4223 case BuiltinFnIdEmbedFile:4666 case BuiltinFnIdEmbedFile:
4224 {4667 {
...@@ -4228,7 +4671,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4228,7 +4671,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4228 return arg0_value;4671 return arg0_value;
42294672
4230 IrInstruction *embed_file = ir_build_embed_file(irb, scope, node, arg0_value);4673 IrInstruction *embed_file = ir_build_embed_file(irb, scope, node, arg0_value);
4231 return ir_lval_wrap(irb, scope, embed_file, lval);4674 return ir_lval_wrap(irb, scope, embed_file, lval, result_loc);
4232 }4675 }
4233 case BuiltinFnIdCmpxchgWeak:4676 case BuiltinFnIdCmpxchgWeak:
4234 case BuiltinFnIdCmpxchgStrong:4677 case BuiltinFnIdCmpxchgStrong:
...@@ -4264,8 +4707,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4264,8 +4707,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4264 return arg5_value;4707 return arg5_value;
42654708
4266 IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,4709 IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
4267 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));4710 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),
4268 return ir_lval_wrap(irb, scope, cmpxchg, lval);4711 result_loc);
4712 return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc);
4269 }4713 }
4270 case BuiltinFnIdFence:4714 case BuiltinFnIdFence:
4271 {4715 {
...@@ -4275,7 +4719,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4275,7 +4719,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4275 return arg0_value;4719 return arg0_value;
42764720
4277 IrInstruction *fence = ir_build_fence(irb, scope, node, arg0_value, AtomicOrderUnordered);4721 IrInstruction *fence = ir_build_fence(irb, scope, node, arg0_value, AtomicOrderUnordered);
4278 return ir_lval_wrap(irb, scope, fence, lval);4722 return ir_lval_wrap(irb, scope, fence, lval, result_loc);
4279 }4723 }
4280 case BuiltinFnIdDivExact:4724 case BuiltinFnIdDivExact:
4281 {4725 {
...@@ -4290,7 +4734,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4290,7 +4734,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4290 return arg1_value;4734 return arg1_value;
42914735
4292 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true);4736 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true);
4293 return ir_lval_wrap(irb, scope, bin_op, lval);4737 return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
4294 }4738 }
4295 case BuiltinFnIdDivTrunc:4739 case BuiltinFnIdDivTrunc:
4296 {4740 {
...@@ -4305,7 +4749,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4305,7 +4749,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4305 return arg1_value;4749 return arg1_value;
43064750
4307 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true);4751 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true);
4308 return ir_lval_wrap(irb, scope, bin_op, lval);4752 return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
4309 }4753 }
4310 case BuiltinFnIdDivFloor:4754 case BuiltinFnIdDivFloor:
4311 {4755 {
...@@ -4320,7 +4764,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4320,7 +4764,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4320 return arg1_value;4764 return arg1_value;
43214765
4322 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true);4766 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true);
4323 return ir_lval_wrap(irb, scope, bin_op, lval);4767 return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
4324 }4768 }
4325 case BuiltinFnIdRem:4769 case BuiltinFnIdRem:
4326 {4770 {
...@@ -4335,7 +4779,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4335,7 +4779,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4335 return arg1_value;4779 return arg1_value;
43364780
4337 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true);4781 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true);
4338 return ir_lval_wrap(irb, scope, bin_op, lval);4782 return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
4339 }4783 }
4340 case BuiltinFnIdMod:4784 case BuiltinFnIdMod:
4341 {4785 {
...@@ -4350,9 +4794,22 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4350,9 +4794,22 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4350 return arg1_value;4794 return arg1_value;
43514795
4352 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true);4796 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true);
4353 return ir_lval_wrap(irb, scope, bin_op, lval);4797 return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
4354 }4798 }
4355 case BuiltinFnIdSqrt:4799 case BuiltinFnIdSqrt:
4800 case BuiltinFnIdSin:
4801 case BuiltinFnIdCos:
4802 case BuiltinFnIdExp:
4803 case BuiltinFnIdExp2:
4804 case BuiltinFnIdLn:
4805 case BuiltinFnIdLog2:
4806 case BuiltinFnIdLog10:
4807 case BuiltinFnIdFabs:
4808 case BuiltinFnIdFloor:
4809 case BuiltinFnIdCeil:
4810 case BuiltinFnIdTrunc:
4811 case BuiltinFnIdNearbyInt:
4812 case BuiltinFnIdRound:
4356 {4813 {
4357 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4814 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4358 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);4815 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
...@@ -4364,8 +4821,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4364,8 +4821,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4364 if (arg1_value == irb->codegen->invalid_instruction)4821 if (arg1_value == irb->codegen->invalid_instruction)
4365 return arg1_value;4822 return arg1_value;
43664823
4367 IrInstruction *ir_sqrt = ir_build_sqrt(irb, scope, node, arg0_value, arg1_value);4824 IrInstruction *ir_sqrt = ir_build_float_op(irb, scope, node, arg0_value, arg1_value, builtin_fn->id);
4368 return ir_lval_wrap(irb, scope, ir_sqrt, lval);4825 return ir_lval_wrap(irb, scope, ir_sqrt, lval, result_loc);
4369 }4826 }
4370 case BuiltinFnIdTruncate:4827 case BuiltinFnIdTruncate:
4371 {4828 {
...@@ -4380,7 +4837,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4380,7 +4837,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4380 return arg1_value;4837 return arg1_value;
43814838
4382 IrInstruction *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value);4839 IrInstruction *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value);
4383 return ir_lval_wrap(irb, scope, truncate, lval);4840 return ir_lval_wrap(irb, scope, truncate, lval, result_loc);
4384 }4841 }
4385 case BuiltinFnIdIntCast:4842 case BuiltinFnIdIntCast:
4386 {4843 {
...@@ -4395,7 +4852,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4395,7 +4852,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4395 return arg1_value;4852 return arg1_value;
43964853
4397 IrInstruction *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value);4854 IrInstruction *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value);
4398 return ir_lval_wrap(irb, scope, result, lval);4855 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4399 }4856 }
4400 case BuiltinFnIdFloatCast:4857 case BuiltinFnIdFloatCast:
4401 {4858 {
...@@ -4410,7 +4867,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4410,7 +4867,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4410 return arg1_value;4867 return arg1_value;
44114868
4412 IrInstruction *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value);4869 IrInstruction *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value);
4413 return ir_lval_wrap(irb, scope, result, lval);4870 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4414 }4871 }
4415 case BuiltinFnIdErrSetCast:4872 case BuiltinFnIdErrSetCast:
4416 {4873 {
...@@ -4425,7 +4882,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4425,7 +4882,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4425 return arg1_value;4882 return arg1_value;
44264883
4427 IrInstruction *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value);4884 IrInstruction *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value);
4428 return ir_lval_wrap(irb, scope, result, lval);4885 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4429 }4886 }
4430 case BuiltinFnIdFromBytes:4887 case BuiltinFnIdFromBytes:
4431 {4888 {
...@@ -4439,8 +4896,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4439,8 +4896,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4439 if (arg1_value == irb->codegen->invalid_instruction)4896 if (arg1_value == irb->codegen->invalid_instruction)
4440 return arg1_value;4897 return arg1_value;
44414898
4442 IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value);4899 IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value, result_loc);
4443 return ir_lval_wrap(irb, scope, result, lval);4900 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4444 }4901 }
4445 case BuiltinFnIdToBytes:4902 case BuiltinFnIdToBytes:
4446 {4903 {
...@@ -4449,8 +4906,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4449,8 +4906,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4449 if (arg0_value == irb->codegen->invalid_instruction)4906 if (arg0_value == irb->codegen->invalid_instruction)
4450 return arg0_value;4907 return arg0_value;
44514908
4452 IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value);4909 IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value, result_loc);
4453 return ir_lval_wrap(irb, scope, result, lval);4910 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4454 }4911 }
4455 case BuiltinFnIdIntToFloat:4912 case BuiltinFnIdIntToFloat:
4456 {4913 {
...@@ -4465,7 +4922,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4465,7 +4922,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4465 return arg1_value;4922 return arg1_value;
44664923
4467 IrInstruction *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value);4924 IrInstruction *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value);
4468 return ir_lval_wrap(irb, scope, result, lval);4925 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4469 }4926 }
4470 case BuiltinFnIdFloatToInt:4927 case BuiltinFnIdFloatToInt:
4471 {4928 {
...@@ -4480,7 +4937,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4480,7 +4937,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4480 return arg1_value;4937 return arg1_value;
44814938
4482 IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);4939 IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);
4483 return ir_lval_wrap(irb, scope, result, lval);4940 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4484 }4941 }
4485 case BuiltinFnIdErrToInt:4942 case BuiltinFnIdErrToInt:
4486 {4943 {
...@@ -4490,7 +4947,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4490,7 +4947,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4490 return arg0_value;4947 return arg0_value;
44914948
4492 IrInstruction *result = ir_build_err_to_int(irb, scope, node, arg0_value);4949 IrInstruction *result = ir_build_err_to_int(irb, scope, node, arg0_value);
4493 return ir_lval_wrap(irb, scope, result, lval);4950 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4494 }4951 }
4495 case BuiltinFnIdIntToErr:4952 case BuiltinFnIdIntToErr:
4496 {4953 {
...@@ -4500,7 +4957,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4500,7 +4957,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4500 return arg0_value;4957 return arg0_value;
45014958
4502 IrInstruction *result = ir_build_int_to_err(irb, scope, node, arg0_value);4959 IrInstruction *result = ir_build_int_to_err(irb, scope, node, arg0_value);
4503 return ir_lval_wrap(irb, scope, result, lval);4960 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4504 }4961 }
4505 case BuiltinFnIdBoolToInt:4962 case BuiltinFnIdBoolToInt:
4506 {4963 {
...@@ -4510,7 +4967,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4510,7 +4967,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4510 return arg0_value;4967 return arg0_value;
45114968
4512 IrInstruction *result = ir_build_bool_to_int(irb, scope, node, arg0_value);4969 IrInstruction *result = ir_build_bool_to_int(irb, scope, node, arg0_value);
4513 return ir_lval_wrap(irb, scope, result, lval);4970 return ir_lval_wrap(irb, scope, result, lval, result_loc);
4514 }4971 }
4515 case BuiltinFnIdIntType:4972 case BuiltinFnIdIntType:
4516 {4973 {
...@@ -4525,7 +4982,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4525,7 +4982,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4525 return arg1_value;4982 return arg1_value;
45264983
4527 IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);4984 IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
4528 return ir_lval_wrap(irb, scope, int_type, lval);4985 return ir_lval_wrap(irb, scope, int_type, lval, result_loc);
4529 }4986 }
4530 case BuiltinFnIdVectorType:4987 case BuiltinFnIdVectorType:
4531 {4988 {
...@@ -4540,7 +4997,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4540,7 +4997,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4540 return arg1_value;4997 return arg1_value;
45414998
4542 IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);4999 IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);
4543 return ir_lval_wrap(irb, scope, vector_type, lval);5000 return ir_lval_wrap(irb, scope, vector_type, lval, result_loc);
4544 }5001 }
4545 case BuiltinFnIdMemcpy:5002 case BuiltinFnIdMemcpy:
4546 {5003 {
...@@ -4560,7 +5017,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4560,7 +5017,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4560 return arg2_value;5017 return arg2_value;
45615018
4562 IrInstruction *ir_memcpy = ir_build_memcpy(irb, scope, node, arg0_value, arg1_value, arg2_value);5019 IrInstruction *ir_memcpy = ir_build_memcpy(irb, scope, node, arg0_value, arg1_value, arg2_value);
4563 return ir_lval_wrap(irb, scope, ir_memcpy, lval);5020 return ir_lval_wrap(irb, scope, ir_memcpy, lval, result_loc);
4564 }5021 }
4565 case BuiltinFnIdMemset:5022 case BuiltinFnIdMemset:
4566 {5023 {
...@@ -4580,7 +5037,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4580,7 +5037,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4580 return arg2_value;5037 return arg2_value;
45815038
4582 IrInstruction *ir_memset = ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value);5039 IrInstruction *ir_memset = ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value);
4583 return ir_lval_wrap(irb, scope, ir_memset, lval);5040 return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc);
4584 }5041 }
4585 case BuiltinFnIdMemberCount:5042 case BuiltinFnIdMemberCount:
4586 {5043 {
...@@ -4590,7 +5047,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4590,7 +5047,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4590 return arg0_value;5047 return arg0_value;
45915048
4592 IrInstruction *member_count = ir_build_member_count(irb, scope, node, arg0_value);5049 IrInstruction *member_count = ir_build_member_count(irb, scope, node, arg0_value);
4593 return ir_lval_wrap(irb, scope, member_count, lval);5050 return ir_lval_wrap(irb, scope, member_count, lval, result_loc);
4594 }5051 }
4595 case BuiltinFnIdMemberType:5052 case BuiltinFnIdMemberType:
4596 {5053 {
...@@ -4606,7 +5063,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4606,7 +5063,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
46065063
46075064
4608 IrInstruction *member_type = ir_build_member_type(irb, scope, node, arg0_value, arg1_value);5065 IrInstruction *member_type = ir_build_member_type(irb, scope, node, arg0_value, arg1_value);
4609 return ir_lval_wrap(irb, scope, member_type, lval);5066 return ir_lval_wrap(irb, scope, member_type, lval, result_loc);
4610 }5067 }
4611 case BuiltinFnIdMemberName:5068 case BuiltinFnIdMemberName:
4612 {5069 {
...@@ -4622,12 +5079,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4622,12 +5079,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
46225079
46235080
4624 IrInstruction *member_name = ir_build_member_name(irb, scope, node, arg0_value, arg1_value);5081 IrInstruction *member_name = ir_build_member_name(irb, scope, node, arg0_value, arg1_value);
4625 return ir_lval_wrap(irb, scope, member_name, lval);5082 return ir_lval_wrap(irb, scope, member_name, lval, result_loc);
4626 }5083 }
4627 case BuiltinFnIdField:5084 case BuiltinFnIdField:
4628 {5085 {
4629 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);5086 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4630 IrInstruction *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr);5087 IrInstruction *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr, nullptr);
4631 if (arg0_value == irb->codegen->invalid_instruction)5088 if (arg0_value == irb->codegen->invalid_instruction)
4632 return arg0_value;5089 return arg0_value;
46335090
...@@ -4641,7 +5098,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4641,7 +5098,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4641 if (lval == LValPtr)5098 if (lval == LValPtr)
4642 return ptr_instruction;5099 return ptr_instruction;
46435100
4644 return ir_build_load_ptr(irb, scope, node, ptr_instruction);5101 IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
5102 return ir_expr_wrap(irb, scope, load_ptr, result_loc);
4645 }5103 }
4646 case BuiltinFnIdTypeInfo:5104 case BuiltinFnIdTypeInfo:
4647 {5105 {
...@@ -4651,14 +5109,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4651,14 +5109,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4651 return arg0_value;5109 return arg0_value;
46525110
4653 IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);5111 IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value);
4654 return ir_lval_wrap(irb, scope, type_info, lval);5112 return ir_lval_wrap(irb, scope, type_info, lval, result_loc);
4655 }5113 }
4656 case BuiltinFnIdBreakpoint:5114 case BuiltinFnIdBreakpoint:
4657 return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval);5115 return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc);
4658 case BuiltinFnIdReturnAddress:5116 case BuiltinFnIdReturnAddress:
4659 return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval);5117 return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval, result_loc);
4660 case BuiltinFnIdFrameAddress:5118 case BuiltinFnIdFrameAddress:
4661 return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval);5119 return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval, result_loc);
4662 case BuiltinFnIdHandle:5120 case BuiltinFnIdHandle:
4663 if (!irb->exec->fn_entry) {5121 if (!irb->exec->fn_entry) {
4664 add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition"));5122 add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition"));
...@@ -4668,7 +5126,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4668,7 +5126,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4668 add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function"));5126 add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function"));
4669 return irb->codegen->invalid_instruction;5127 return irb->codegen->invalid_instruction;
4670 }5128 }
4671 return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval);5129 return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval, result_loc);
4672 case BuiltinFnIdAlignOf:5130 case BuiltinFnIdAlignOf:
4673 {5131 {
4674 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);5132 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -4677,16 +5135,18 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4677,16 +5135,18 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4677 return arg0_value;5135 return arg0_value;
46785136
4679 IrInstruction *align_of = ir_build_align_of(irb, scope, node, arg0_value);5137 IrInstruction *align_of = ir_build_align_of(irb, scope, node, arg0_value);
4680 return ir_lval_wrap(irb, scope, align_of, lval);5138 return ir_lval_wrap(irb, scope, align_of, lval, result_loc);
4681 }5139 }
4682 case BuiltinFnIdAddWithOverflow:5140 case BuiltinFnIdAddWithOverflow:
4683 return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval);5141 return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval, result_loc);
4684 case BuiltinFnIdSubWithOverflow:5142 case BuiltinFnIdSubWithOverflow:
4685 return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval);5143 return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval, result_loc);
4686 case BuiltinFnIdMulWithOverflow:5144 case BuiltinFnIdMulWithOverflow:
4687 return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval);5145 return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval, result_loc);
4688 case BuiltinFnIdShlWithOverflow:5146 case BuiltinFnIdShlWithOverflow:
4689 return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval);5147 return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval, result_loc);
5148 case BuiltinFnIdMulAdd:
5149 return ir_lval_wrap(irb, scope, ir_gen_mul_add(irb, scope, node), lval, result_loc);
4690 case BuiltinFnIdTypeName:5150 case BuiltinFnIdTypeName:
4691 {5151 {
4692 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);5152 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -4695,7 +5155,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4695,7 +5155,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4695 return arg0_value;5155 return arg0_value;
46965156
4697 IrInstruction *type_name = ir_build_type_name(irb, scope, node, arg0_value);5157 IrInstruction *type_name = ir_build_type_name(irb, scope, node, arg0_value);
4698 return ir_lval_wrap(irb, scope, type_name, lval);5158 return ir_lval_wrap(irb, scope, type_name, lval, result_loc);
4699 }5159 }
4700 case BuiltinFnIdPanic:5160 case BuiltinFnIdPanic:
4701 {5161 {
...@@ -4705,7 +5165,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4705,7 +5165,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4705 return arg0_value;5165 return arg0_value;
47065166
4707 IrInstruction *panic = ir_build_panic(irb, scope, node, arg0_value);5167 IrInstruction *panic = ir_build_panic(irb, scope, node, arg0_value);
4708 return ir_lval_wrap(irb, scope, panic, lval);5168 return ir_lval_wrap(irb, scope, panic, lval, result_loc);
4709 }5169 }
4710 case BuiltinFnIdPtrCast:5170 case BuiltinFnIdPtrCast:
4711 {5171 {
...@@ -4720,22 +5180,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4720,22 +5180,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4720 return arg1_value;5180 return arg1_value;
47215181
4722 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true);5182 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true);
4723 return ir_lval_wrap(irb, scope, ptr_cast, lval);5183 return ir_lval_wrap(irb, scope, ptr_cast, lval, result_loc);
4724 }5184 }
4725 case BuiltinFnIdBitCast:5185 case BuiltinFnIdBitCast:
4726 {5186 {
4727 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);5187 AstNode *dest_type_node = node->data.fn_call_expr.params.at(0);
4728 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);5188 IrInstruction *dest_type = ir_gen_node(irb, dest_type_node, scope);
4729 if (arg0_value == irb->codegen->invalid_instruction)5189 if (dest_type == irb->codegen->invalid_instruction)
4730 return arg0_value;5190 return dest_type;
5191
5192 ResultLocBitCast *result_loc_bit_cast = allocate<ResultLocBitCast>(1);
5193 result_loc_bit_cast->base.id = ResultLocIdBitCast;
5194 result_loc_bit_cast->base.source_instruction = dest_type;
5195 ir_ref_instruction(dest_type, irb->current_basic_block);
5196 result_loc_bit_cast->parent = result_loc;
5197
5198 ir_build_reset_result(irb, scope, node, &result_loc_bit_cast->base);
47315199
4732 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);5200 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4733 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);5201 IrInstruction *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone,
5202 &result_loc_bit_cast->base);
4734 if (arg1_value == irb->codegen->invalid_instruction)5203 if (arg1_value == irb->codegen->invalid_instruction)
4735 return arg1_value;5204 return arg1_value;
47365205
4737 IrInstruction *bit_cast = ir_build_bit_cast(irb, scope, node, arg0_value, arg1_value);5206 IrInstruction *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast);
4738 return ir_lval_wrap(irb, scope, bit_cast, lval);5207 return ir_lval_wrap(irb, scope, bitcast, lval, result_loc);
4739 }5208 }
4740 case BuiltinFnIdIntToPtr:5209 case BuiltinFnIdIntToPtr:
4741 {5210 {
...@@ -4750,7 +5219,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4750,7 +5219,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4750 return arg1_value;5219 return arg1_value;
47515220
4752 IrInstruction *int_to_ptr = ir_build_int_to_ptr(irb, scope, node, arg0_value, arg1_value);5221 IrInstruction *int_to_ptr = ir_build_int_to_ptr(irb, scope, node, arg0_value, arg1_value);
4753 return ir_lval_wrap(irb, scope, int_to_ptr, lval);5222 return ir_lval_wrap(irb, scope, int_to_ptr, lval, result_loc);
4754 }5223 }
4755 case BuiltinFnIdPtrToInt:5224 case BuiltinFnIdPtrToInt:
4756 {5225 {
...@@ -4760,7 +5229,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4760,7 +5229,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4760 return arg0_value;5229 return arg0_value;
47615230
4762 IrInstruction *ptr_to_int = ir_build_ptr_to_int(irb, scope, node, arg0_value);5231 IrInstruction *ptr_to_int = ir_build_ptr_to_int(irb, scope, node, arg0_value);
4763 return ir_lval_wrap(irb, scope, ptr_to_int, lval);5232 return ir_lval_wrap(irb, scope, ptr_to_int, lval, result_loc);
4764 }5233 }
4765 case BuiltinFnIdTagName:5234 case BuiltinFnIdTagName:
4766 {5235 {
...@@ -4771,7 +5240,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4771,7 +5240,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
47715240
4772 IrInstruction *actual_tag = ir_build_union_tag(irb, scope, node, arg0_value);5241 IrInstruction *actual_tag = ir_build_union_tag(irb, scope, node, arg0_value);
4773 IrInstruction *tag_name = ir_build_tag_name(irb, scope, node, actual_tag);5242 IrInstruction *tag_name = ir_build_tag_name(irb, scope, node, actual_tag);
4774 return ir_lval_wrap(irb, scope, tag_name, lval);5243 return ir_lval_wrap(irb, scope, tag_name, lval, result_loc);
4775 }5244 }
4776 case BuiltinFnIdTagType:5245 case BuiltinFnIdTagType:
4777 {5246 {
...@@ -4781,7 +5250,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4781,7 +5250,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4781 return arg0_value;5250 return arg0_value;
47825251
4783 IrInstruction *tag_type = ir_build_tag_type(irb, scope, node, arg0_value);5252 IrInstruction *tag_type = ir_build_tag_type(irb, scope, node, arg0_value);
4784 return ir_lval_wrap(irb, scope, tag_type, lval);5253 return ir_lval_wrap(irb, scope, tag_type, lval, result_loc);
4785 }5254 }
4786 case BuiltinFnIdFieldParentPtr:5255 case BuiltinFnIdFieldParentPtr:
4787 {5256 {
...@@ -4801,7 +5270,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4801,7 +5270,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4801 return arg2_value;5270 return arg2_value;
48025271
4803 IrInstruction *field_parent_ptr = ir_build_field_parent_ptr(irb, scope, node, arg0_value, arg1_value, arg2_value, nullptr);5272 IrInstruction *field_parent_ptr = ir_build_field_parent_ptr(irb, scope, node, arg0_value, arg1_value, arg2_value, nullptr);
4804 return ir_lval_wrap(irb, scope, field_parent_ptr, lval);5273 return ir_lval_wrap(irb, scope, field_parent_ptr, lval, result_loc);
4805 }5274 }
4806 case BuiltinFnIdByteOffsetOf:5275 case BuiltinFnIdByteOffsetOf:
4807 {5276 {
...@@ -4816,7 +5285,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4816,7 +5285,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4816 return arg1_value;5285 return arg1_value;
48175286
4818 IrInstruction *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value);5287 IrInstruction *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value);
4819 return ir_lval_wrap(irb, scope, offset_of, lval);5288 return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
4820 }5289 }
4821 case BuiltinFnIdBitOffsetOf:5290 case BuiltinFnIdBitOffsetOf:
4822 {5291 {
...@@ -4831,7 +5300,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4831,7 +5300,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4831 return arg1_value;5300 return arg1_value;
48325301
4833 IrInstruction *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value);5302 IrInstruction *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value);
4834 return ir_lval_wrap(irb, scope, offset_of, lval);5303 return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
4835 }5304 }
4836 case BuiltinFnIdInlineCall:5305 case BuiltinFnIdInlineCall:
4837 case BuiltinFnIdNoInlineCall:5306 case BuiltinFnIdNoInlineCall:
...@@ -4857,8 +5326,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4857,8 +5326,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4857 }5326 }
4858 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;5327 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;
48595328
4860 IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr, nullptr);5329 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
4861 return ir_lval_wrap(irb, scope, call, lval);5330 fn_inline, false, nullptr, nullptr, result_loc);
5331 return ir_lval_wrap(irb, scope, call, lval, result_loc);
4862 }5332 }
4863 case BuiltinFnIdNewStackCall:5333 case BuiltinFnIdNewStackCall:
4864 {5334 {
...@@ -4887,8 +5357,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4887,8 +5357,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4887 return args[i];5357 return args[i];
4888 }5358 }
48895359
4890 IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, false, nullptr, new_stack);5360 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
4891 return ir_lval_wrap(irb, scope, call, lval);5361 FnInlineAuto, false, nullptr, new_stack, result_loc);
5362 return ir_lval_wrap(irb, scope, call, lval, result_loc);
4892 }5363 }
4893 case BuiltinFnIdTypeId:5364 case BuiltinFnIdTypeId:
4894 {5365 {
...@@ -4898,7 +5369,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4898,7 +5369,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4898 return arg0_value;5369 return arg0_value;
48995370
4900 IrInstruction *type_id = ir_build_type_id(irb, scope, node, arg0_value);5371 IrInstruction *type_id = ir_build_type_id(irb, scope, node, arg0_value);
4901 return ir_lval_wrap(irb, scope, type_id, lval);5372 return ir_lval_wrap(irb, scope, type_id, lval, result_loc);
4902 }5373 }
4903 case BuiltinFnIdShlExact:5374 case BuiltinFnIdShlExact:
4904 {5375 {
...@@ -4913,7 +5384,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4913,7 +5384,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4913 return arg1_value;5384 return arg1_value;
49145385
4915 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true);5386 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true);
4916 return ir_lval_wrap(irb, scope, bin_op, lval);5387 return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
4917 }5388 }
4918 case BuiltinFnIdShrExact:5389 case BuiltinFnIdShrExact:
4919 {5390 {
...@@ -4928,7 +5399,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4928,7 +5399,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4928 return arg1_value;5399 return arg1_value;
49295400
4930 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true);5401 IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true);
4931 return ir_lval_wrap(irb, scope, bin_op, lval);5402 return ir_lval_wrap(irb, scope, bin_op, lval, result_loc);
4932 }5403 }
4933 case BuiltinFnIdSetEvalBranchQuota:5404 case BuiltinFnIdSetEvalBranchQuota:
4934 {5405 {
...@@ -4938,7 +5409,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4938,7 +5409,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4938 return arg0_value;5409 return arg0_value;
49395410
4940 IrInstruction *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value);5411 IrInstruction *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value);
4941 return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval);5412 return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval, result_loc);
4942 }5413 }
4943 case BuiltinFnIdAlignCast:5414 case BuiltinFnIdAlignCast:
4944 {5415 {
...@@ -4953,17 +5424,17 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4953,17 +5424,17 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4953 return arg1_value;5424 return arg1_value;
49545425
4955 IrInstruction *align_cast = ir_build_align_cast(irb, scope, node, arg0_value, arg1_value);5426 IrInstruction *align_cast = ir_build_align_cast(irb, scope, node, arg0_value, arg1_value);
4956 return ir_lval_wrap(irb, scope, align_cast, lval);5427 return ir_lval_wrap(irb, scope, align_cast, lval, result_loc);
4957 }5428 }
4958 case BuiltinFnIdOpaqueType:5429 case BuiltinFnIdOpaqueType:
4959 {5430 {
4960 IrInstruction *opaque_type = ir_build_opaque_type(irb, scope, node);5431 IrInstruction *opaque_type = ir_build_opaque_type(irb, scope, node);
4961 return ir_lval_wrap(irb, scope, opaque_type, lval);5432 return ir_lval_wrap(irb, scope, opaque_type, lval, result_loc);
4962 }5433 }
4963 case BuiltinFnIdThis:5434 case BuiltinFnIdThis:
4964 {5435 {
4965 IrInstruction *this_inst = ir_gen_this(irb, scope, node);5436 IrInstruction *this_inst = ir_gen_this(irb, scope, node);
4966 return ir_lval_wrap(irb, scope, this_inst, lval);5437 return ir_lval_wrap(irb, scope, this_inst, lval, result_loc);
4967 }5438 }
4968 case BuiltinFnIdSetAlignStack:5439 case BuiltinFnIdSetAlignStack:
4969 {5440 {
...@@ -4973,7 +5444,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4973,7 +5444,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4973 return arg0_value;5444 return arg0_value;
49745445
4975 IrInstruction *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value);5446 IrInstruction *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value);
4976 return ir_lval_wrap(irb, scope, set_align_stack, lval);5447 return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc);
4977 }5448 }
4978 case BuiltinFnIdArgType:5449 case BuiltinFnIdArgType:
4979 {5450 {
...@@ -4988,7 +5459,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4988,7 +5459,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4988 return arg1_value;5459 return arg1_value;
49895460
4990 IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value);5461 IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value);
4991 return ir_lval_wrap(irb, scope, arg_type, lval);5462 return ir_lval_wrap(irb, scope, arg_type, lval, result_loc);
4992 }5463 }
4993 case BuiltinFnIdExport:5464 case BuiltinFnIdExport:
4994 {5465 {
...@@ -5008,12 +5479,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5008,12 +5479,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5008 return arg2_value;5479 return arg2_value;
50095480
5010 IrInstruction *ir_export = ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value);5481 IrInstruction *ir_export = ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value);
5011 return ir_lval_wrap(irb, scope, ir_export, lval);5482 return ir_lval_wrap(irb, scope, ir_export, lval, result_loc);
5012 }5483 }
5013 case BuiltinFnIdErrorReturnTrace:5484 case BuiltinFnIdErrorReturnTrace:
5014 {5485 {
5015 IrInstruction *error_return_trace = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::Null);5486 IrInstruction *error_return_trace = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::Null);
5016 return ir_lval_wrap(irb, scope, error_return_trace, lval);5487 return ir_lval_wrap(irb, scope, error_return_trace, lval, result_loc);
5017 }5488 }
5018 case BuiltinFnIdAtomicRmw:5489 case BuiltinFnIdAtomicRmw:
5019 {5490 {
...@@ -5042,10 +5513,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5042,10 +5513,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5042 if (arg4_value == irb->codegen->invalid_instruction)5513 if (arg4_value == irb->codegen->invalid_instruction)
5043 return arg4_value;5514 return arg4_value;
50445515
5045 return ir_build_atomic_rmw(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value,5516 IrInstruction *inst = ir_build_atomic_rmw(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value,
5046 arg4_value,5517 arg4_value,
5047 // these 2 values don't mean anything since we passed non-null values for other args5518 // these 2 values don't mean anything since we passed non-null values for other args
5048 AtomicRmwOp_xchg, AtomicOrderMonotonic);5519 AtomicRmwOp_xchg, AtomicOrderMonotonic);
5520 return ir_lval_wrap(irb, scope, inst, lval, result_loc);
5049 }5521 }
5050 case BuiltinFnIdAtomicLoad:5522 case BuiltinFnIdAtomicLoad:
5051 {5523 {
...@@ -5064,9 +5536,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5064,9 +5536,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5064 if (arg2_value == irb->codegen->invalid_instruction)5536 if (arg2_value == irb->codegen->invalid_instruction)
5065 return arg2_value;5537 return arg2_value;
50665538
5067 return ir_build_atomic_load(irb, scope, node, arg0_value, arg1_value, arg2_value,5539 IrInstruction *inst = ir_build_atomic_load(irb, scope, node, arg0_value, arg1_value, arg2_value,
5068 // this value does not mean anything since we passed non-null values for other arg5540 // this value does not mean anything since we passed non-null values for other arg
5069 AtomicOrderMonotonic);5541 AtomicOrderMonotonic);
5542 return ir_lval_wrap(irb, scope, inst, lval, result_loc);
5070 }5543 }
5071 case BuiltinFnIdIntToEnum:5544 case BuiltinFnIdIntToEnum:
5072 {5545 {
...@@ -5081,7 +5554,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5081,7 +5554,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5081 return arg1_value;5554 return arg1_value;
50825555
5083 IrInstruction *result = ir_build_int_to_enum(irb, scope, node, arg0_value, arg1_value);5556 IrInstruction *result = ir_build_int_to_enum(irb, scope, node, arg0_value, arg1_value);
5084 return ir_lval_wrap(irb, scope, result, lval);5557 return ir_lval_wrap(irb, scope, result, lval, result_loc);
5085 }5558 }
5086 case BuiltinFnIdEnumToInt:5559 case BuiltinFnIdEnumToInt:
5087 {5560 {
...@@ -5091,7 +5564,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5091,7 +5564,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5091 return arg0_value;5564 return arg0_value;
50925565
5093 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);5566 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
5094 return ir_lval_wrap(irb, scope, result, lval);5567 return ir_lval_wrap(irb, scope, result, lval, result_loc);
5095 }5568 }
5096 case BuiltinFnIdCtz:5569 case BuiltinFnIdCtz:
5097 case BuiltinFnIdPopCount:5570 case BuiltinFnIdPopCount:
...@@ -5129,7 +5602,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5129,7 +5602,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5129 default:5602 default:
5130 zig_unreachable();5603 zig_unreachable();
5131 }5604 }
5132 return ir_lval_wrap(irb, scope, result, lval);5605 return ir_lval_wrap(irb, scope, result, lval, result_loc);
5133 }5606 }
5134 case BuiltinFnIdHasDecl:5607 case BuiltinFnIdHasDecl:
5135 {5608 {
...@@ -5144,17 +5617,19 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5144,17 +5617,19 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5144 return arg1_value;5617 return arg1_value;
51455618
5146 IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value);5619 IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value);
5147 return ir_lval_wrap(irb, scope, has_decl, lval);5620 return ir_lval_wrap(irb, scope, has_decl, lval, result_loc);
5148 }5621 }
5149 }5622 }
5150 zig_unreachable();5623 zig_unreachable();
5151}5624}
51525625
5153static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {5626static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
5627 ResultLoc *result_loc)
5628{
5154 assert(node->type == NodeTypeFnCallExpr);5629 assert(node->type == NodeTypeFnCallExpr);
51555630
5156 if (node->data.fn_call_expr.is_builtin)5631 if (node->data.fn_call_expr.is_builtin)
5157 return ir_gen_builtin_fn_call(irb, scope, node, lval);5632 return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);
51585633
5159 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;5634 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
5160 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);5635 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
...@@ -5180,12 +5655,14 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -5180,12 +5655,14 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
5180 }5655 }
5181 }5656 }
51825657
5183 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,5658 IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
5184 is_async, async_allocator, nullptr);5659 is_async, async_allocator, nullptr, result_loc);
5185 return ir_lval_wrap(irb, scope, fn_call, lval);5660 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
5186}5661}
51875662
5188static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) {5663static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
5664 ResultLoc *result_loc)
5665{
5189 assert(node->type == NodeTypeIfBoolExpr);5666 assert(node->type == NodeTypeIfBoolExpr);
51905667
5191 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);5668 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
...@@ -5206,12 +5683,16 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -5206,12 +5683,16 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
5206 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "Else");5683 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "Else");
5207 IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "EndIf");5684 IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "EndIf");
52085685
5209 ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_comptime);5686 IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, condition,
5687 then_block, else_block, is_comptime);
5688 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
5689 result_loc, is_comptime);
52105690
5211 ir_set_cursor_at_end_and_append_block(irb, then_block);5691 ir_set_cursor_at_end_and_append_block(irb, then_block);
52125692
5213 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);5693 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
5214 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);5694 IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval,
5695 &peer_parent->peers.at(0)->base);
5215 if (then_expr_result == irb->codegen->invalid_instruction)5696 if (then_expr_result == irb->codegen->invalid_instruction)
5216 return irb->codegen->invalid_instruction;5697 return irb->codegen->invalid_instruction;
5217 IrBasicBlock *after_then_block = irb->current_basic_block;5698 IrBasicBlock *after_then_block = irb->current_basic_block;
...@@ -5221,11 +5702,12 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -5221,11 +5702,12 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
5221 ir_set_cursor_at_end_and_append_block(irb, else_block);5702 ir_set_cursor_at_end_and_append_block(irb, else_block);
5222 IrInstruction *else_expr_result;5703 IrInstruction *else_expr_result;
5223 if (else_node) {5704 if (else_node) {
5224 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);5705 else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
5225 if (else_expr_result == irb->codegen->invalid_instruction)5706 if (else_expr_result == irb->codegen->invalid_instruction)
5226 return irb->codegen->invalid_instruction;5707 return irb->codegen->invalid_instruction;
5227 } else {5708 } else {
5228 else_expr_result = ir_build_const_void(irb, scope, node);5709 else_expr_result = ir_build_const_void(irb, scope, node);
5710 ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
5229 }5711 }
5230 IrBasicBlock *after_else_block = irb->current_basic_block;5712 IrBasicBlock *after_else_block = irb->current_basic_block;
5231 if (!instr_is_unreachable(else_expr_result))5713 if (!instr_is_unreachable(else_expr_result))
...@@ -5239,14 +5721,15 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -5239,14 +5721,15 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
5239 incoming_blocks[0] = after_then_block;5721 incoming_blocks[0] = after_then_block;
5240 incoming_blocks[1] = after_else_block;5722 incoming_blocks[1] = after_else_block;
52415723
5242 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);5724 IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent);
5725 return ir_expr_wrap(irb, scope, phi, result_loc);
5243}5726}
52445727
5245static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {5728static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
5246 assert(node->type == NodeTypePrefixOpExpr);5729 assert(node->type == NodeTypePrefixOpExpr);
5247 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;5730 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
52485731
5249 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);5732 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr);
5250 if (value == irb->codegen->invalid_instruction)5733 if (value == irb->codegen->invalid_instruction)
5251 return value;5734 return value;
52525735
...@@ -5257,15 +5740,34 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode...@@ -5257,15 +5740,34 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode
5257 return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValNone);5740 return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValNone);
5258}5741}
52595742
5260static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval) {5743static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc) {
5261 if (lval != LValPtr)5744 ir_build_end_expr(irb, scope, inst->source_node, inst, result_loc);
5745 return inst;
5746}
5747
5748static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval,
5749 ResultLoc *result_loc)
5750{
5751 // This logic must be kept in sync with
5752 // [STMT_EXPR_TEST_THING] <--- (search this token)
5753 if (value == irb->codegen->invalid_instruction ||
5754 instr_is_unreachable(value) ||
5755 value->source_node->type == NodeTypeDefer ||
5756 value->id == IrInstructionIdDeclVarSrc)
5757 {
5262 return value;5758 return value;
5263 if (value == irb->codegen->invalid_instruction)5759 }
5760
5761 if (lval == LValPtr) {
5762 // We needed a pointer to a value, but we got a value. So we create
5763 // an instruction which just makes a pointer of it.
5764 return ir_build_ref(irb, scope, value->source_node, value, false, false);
5765 } else if (result_loc != nullptr) {
5766 return ir_expr_wrap(irb, scope, value, result_loc);
5767 } else {
5264 return value;5768 return value;
5769 }
52655770
5266 // We needed a pointer to a value, but we got a value. So we create
5267 // an instruction which just makes a const pointer of it.
5268 return ir_build_ref(irb, scope, value->source_node, value, false, false);
5269}5771}
52705772
5271static PtrLen star_token_to_ptr_len(TokenId token_id) {5773static PtrLen star_token_to_ptr_len(TokenId token_id) {
...@@ -5338,21 +5840,22 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -5338,21 +5840,22 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
5338 ptr_len, align_value, bit_offset_start, host_int_bytes, is_allow_zero);5840 ptr_len, align_value, bit_offset_start, host_int_bytes, is_allow_zero);
5339}5841}
53405842
5341static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,5843static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node,
5342 LVal lval)5844 AstNode *expr_node, LVal lval, ResultLoc *result_loc)
5343{5845{
5344 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);5846 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
5345 if (err_union_ptr == irb->codegen->invalid_instruction)5847 if (err_union_ptr == irb->codegen->invalid_instruction)
5346 return irb->codegen->invalid_instruction;5848 return irb->codegen->invalid_instruction;
53475849
5348 IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, source_node, err_union_ptr, true);5850 IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, source_node, err_union_ptr, true, false);
5349 if (payload_ptr == irb->codegen->invalid_instruction)5851 if (payload_ptr == irb->codegen->invalid_instruction)
5350 return irb->codegen->invalid_instruction;5852 return irb->codegen->invalid_instruction;
53515853
5352 if (lval == LValPtr)5854 if (lval == LValPtr)
5353 return payload_ptr;5855 return payload_ptr;
53545856
5355 return ir_build_load_ptr(irb, scope, source_node, payload_ptr);5857 IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, source_node, payload_ptr);
5858 return ir_expr_wrap(irb, scope, load_ptr, result_loc);
5356}5859}
53575860
5358static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *node) {5861static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -5366,7 +5869,9 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5366,7 +5869,9 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod
5366 return ir_build_bool_not(irb, scope, node, value);5869 return ir_build_bool_not(irb, scope, node, value);
5367}5870}
53685871
5369static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {5872static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
5873 ResultLoc *result_loc)
5874{
5370 assert(node->type == NodeTypePrefixOpExpr);5875 assert(node->type == NodeTypePrefixOpExpr);
53715876
5372 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;5877 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
...@@ -5375,24 +5880,26 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod...@@ -5375,24 +5880,26 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
5375 case PrefixOpInvalid:5880 case PrefixOpInvalid:
5376 zig_unreachable();5881 zig_unreachable();
5377 case PrefixOpBoolNot:5882 case PrefixOpBoolNot:
5378 return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval);5883 return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval, result_loc);
5379 case PrefixOpBinNot:5884 case PrefixOpBinNot:
5380 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval);5885 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval, result_loc);
5381 case PrefixOpNegation:5886 case PrefixOpNegation:
5382 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval);5887 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval, result_loc);
5383 case PrefixOpNegationWrap:5888 case PrefixOpNegationWrap:
5384 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval);5889 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval, result_loc);
5385 case PrefixOpOptional:5890 case PrefixOpOptional:
5386 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval);5891 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval, result_loc);
5387 case PrefixOpAddrOf: {5892 case PrefixOpAddrOf: {
5388 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;5893 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
5389 return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr), lval);5894 return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr), lval, result_loc);
5390 }5895 }
5391 }5896 }
5392 zig_unreachable();5897 zig_unreachable();
5393}5898}
53945899
5395static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node) {5900static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
5901 ResultLoc *parent_result_loc)
5902{
5396 assert(node->type == NodeTypeContainerInitExpr);5903 assert(node->type == NodeTypeContainerInitExpr);
53975904
5398 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;5905 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
...@@ -5410,45 +5917,104 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -5410,45 +5917,104 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
5410 return container_type;5917 return container_type;
5411 }5918 }
54125919
5413 if (kind == ContainerInitKindStruct) {5920 switch (kind) {
5414 if (elem_type != nullptr) {5921 case ContainerInitKindStruct: {
5415 add_node_error(irb->codegen, container_init_expr->type,5922 if (elem_type != nullptr) {
5416 buf_sprintf("initializing array with struct syntax"));5923 add_node_error(irb->codegen, container_init_expr->type,
5417 return irb->codegen->invalid_instruction;5924 buf_sprintf("initializing array with struct syntax"));
5418 }5925 return irb->codegen->invalid_instruction;
5926 }
5927
5928 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
5929 container_type);
5930
5931 size_t field_count = container_init_expr->entries.length;
5932 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
5933 for (size_t i = 0; i < field_count; i += 1) {
5934 AstNode *entry_node = container_init_expr->entries.at(i);
5935 assert(entry_node->type == NodeTypeStructValueField);
54195936
5420 size_t field_count = container_init_expr->entries.length;5937 Buf *name = entry_node->data.struct_val_field.name;
5421 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);5938 AstNode *expr_node = entry_node->data.struct_val_field.expr;
5422 for (size_t i = 0; i < field_count; i += 1) {
5423 AstNode *entry_node = container_init_expr->entries.at(i);
5424 assert(entry_node->type == NodeTypeStructValueField);
54255939
5426 Buf *name = entry_node->data.struct_val_field.name;5940 IrInstruction *field_ptr = ir_build_field_ptr(irb, scope, entry_node, container_ptr, name, true);
5427 AstNode *expr_node = entry_node->data.struct_val_field.expr;5941 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5428 IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);5942 result_loc_inst->base.id = ResultLocIdInstruction;
5429 if (expr_value == irb->codegen->invalid_instruction)5943 result_loc_inst->base.source_instruction = field_ptr;
5430 return expr_value;5944 ir_ref_instruction(field_ptr, irb->current_basic_block);
5945 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
54315946
5432 fields[i].name = name;5947 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
5433 fields[i].value = expr_value;5948 &result_loc_inst->base);
5434 fields[i].source_node = entry_node;5949 if (expr_value == irb->codegen->invalid_instruction)
5950 return expr_value;
5951
5952 fields[i].name = name;
5953 fields[i].source_node = entry_node;
5954 fields[i].result_loc = field_ptr;
5955 }
5956 IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,
5957 field_count, fields, container_ptr);
5958
5959 return ir_lval_wrap(irb, scope, init_fields, lval, parent_result_loc);
5435 }5960 }
5436 return ir_build_container_init_fields(irb, scope, node, container_type, field_count, fields);5961 case ContainerInitKindArray: {
5437 } else if (kind == ContainerInitKindArray) {5962 size_t item_count = container_init_expr->entries.length;
5438 size_t item_count = container_init_expr->entries.length;5963
5439 IrInstruction **values = allocate<IrInstruction *>(item_count);5964 if (container_type == nullptr) {
5440 for (size_t i = 0; i < item_count; i += 1) {5965 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
5441 AstNode *expr_node = container_init_expr->entries.at(i);5966 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
5442 IrInstruction *expr_value = ir_gen_node(irb, expr_node, scope);5967 }
5443 if (expr_value == irb->codegen->invalid_instruction)5968
5444 return expr_value;5969 IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
5970 container_type);
5971
5972 IrInstruction **result_locs = allocate<IrInstruction *>(item_count);
5973 for (size_t i = 0; i < item_count; i += 1) {
5974 AstNode *expr_node = container_init_expr->entries.at(i);
5975
5976 IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i);
5977 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index,
5978 false, PtrLenSingle, container_type);
5979 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
5980 result_loc_inst->base.id = ResultLocIdInstruction;
5981 result_loc_inst->base.source_instruction = elem_ptr;
5982 ir_ref_instruction(elem_ptr, irb->current_basic_block);
5983 ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base);
54455984
5446 values[i] = expr_value;5985 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone,
5986 &result_loc_inst->base);
5987 if (expr_value == irb->codegen->invalid_instruction)
5988 return expr_value;
5989
5990 result_locs[i] = elem_ptr;
5991 }
5992 IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,
5993 item_count, result_locs, container_ptr);
5994 return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);
5447 }5995 }
5448 return ir_build_container_init_list(irb, scope, node, container_type, elem_type, item_count, values);
5449 } else {
5450 zig_unreachable();
5451 }5996 }
5997 zig_unreachable();
5998}
5999
6000static ResultLocVar *ir_build_var_result_loc(IrBuilder *irb, IrInstruction *alloca, ZigVar *var) {
6001 ResultLocVar *result_loc_var = allocate<ResultLocVar>(1);
6002 result_loc_var->base.id = ResultLocIdVar;
6003 result_loc_var->base.source_instruction = alloca;
6004 result_loc_var->var = var;
6005
6006 ir_build_reset_result(irb, alloca->scope, alloca->source_node, &result_loc_var->base);
6007
6008 return result_loc_var;
6009}
6010
6011static void build_decl_var_and_init(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var,
6012 IrInstruction *init, const char *name_hint, IrInstruction *is_comptime)
6013{
6014 IrInstruction *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime);
6015 ResultLocVar *var_result_loc = ir_build_var_result_loc(irb, alloca, var);
6016 ir_build_end_expr(irb, scope, source_node, init, &var_result_loc->base);
6017 ir_build_var_decl_src(irb, scope, source_node, var, nullptr, alloca);
5452}6018}
54536019
5454static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *node) {6020static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -5461,9 +6027,12 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5461,9 +6027,12 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5461 return irb->codegen->invalid_instruction;6027 return irb->codegen->invalid_instruction;
5462 }6028 }
54636029
6030 // Used for the type expr and the align expr
6031 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
6032
5464 IrInstruction *type_instruction;6033 IrInstruction *type_instruction;
5465 if (variable_declaration->type != nullptr) {6034 if (variable_declaration->type != nullptr) {
5466 type_instruction = ir_gen_node(irb, variable_declaration->type, scope);6035 type_instruction = ir_gen_node(irb, variable_declaration->type, comptime_scope);
5467 if (type_instruction == irb->codegen->invalid_instruction)6036 if (type_instruction == irb->codegen->invalid_instruction)
5468 return type_instruction;6037 return type_instruction;
5469 } else {6038 } else {
...@@ -5474,8 +6043,8 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5474,8 +6043,8 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5474 bool is_const = variable_declaration->is_const;6043 bool is_const = variable_declaration->is_const;
5475 bool is_extern = variable_declaration->is_extern;6044 bool is_extern = variable_declaration->is_extern;
54766045
5477 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,6046 bool is_comptime_scalar = ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime;
5478 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);6047 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, is_comptime_scalar);
5479 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,6048 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
5480 is_const, is_const, is_shadowable, is_comptime);6049 is_const, is_const, is_shadowable, is_comptime);
5481 // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node6050 // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node
...@@ -5489,7 +6058,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5489,7 +6058,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
54896058
5490 IrInstruction *align_value = nullptr;6059 IrInstruction *align_value = nullptr;
5491 if (variable_declaration->align_expr != nullptr) {6060 if (variable_declaration->align_expr != nullptr) {
5492 align_value = ir_gen_node(irb, variable_declaration->align_expr, scope);6061 align_value = ir_gen_node(irb, variable_declaration->align_expr, comptime_scope);
5493 if (align_value == irb->codegen->invalid_instruction)6062 if (align_value == irb->codegen->invalid_instruction)
5494 return align_value;6063 return align_value;
5495 }6064 }
...@@ -5502,20 +6071,39 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5502,20 +6071,39 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5502 // Parser should ensure that this never happens6071 // Parser should ensure that this never happens
5503 assert(variable_declaration->threadlocal_tok == nullptr);6072 assert(variable_declaration->threadlocal_tok == nullptr);
55046073
6074 IrInstruction *alloca = ir_build_alloca_src(irb, scope, node, align_value,
6075 buf_ptr(variable_declaration->symbol), is_comptime);
6076
6077 // Create a result location for the initialization expression.
6078 ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var);
6079 ResultLoc *init_result_loc = (type_instruction == nullptr) ? &result_loc_var->base : nullptr;
6080
6081 Scope *init_scope = is_comptime_scalar ?
6082 create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope;
6083
5505 // Temporarily set the name of the IrExecutable to the VariableDeclaration6084 // Temporarily set the name of the IrExecutable to the VariableDeclaration
5506 // so that the struct or enum from the init expression inherits the name.6085 // so that the struct or enum from the init expression inherits the name.
5507 Buf *old_exec_name = irb->exec->name;6086 Buf *old_exec_name = irb->exec->name;
5508 irb->exec->name = variable_declaration->symbol;6087 irb->exec->name = variable_declaration->symbol;
5509 IrInstruction *init_value = ir_gen_node(irb, variable_declaration->expr, scope);6088 IrInstruction *init_value = ir_gen_node_extra(irb, variable_declaration->expr, init_scope,
6089 LValNone, init_result_loc);
5510 irb->exec->name = old_exec_name;6090 irb->exec->name = old_exec_name;
55116091
5512 if (init_value == irb->codegen->invalid_instruction)6092 if (init_value == irb->codegen->invalid_instruction)
5513 return init_value;6093 return irb->codegen->invalid_instruction;
6094
6095 if (type_instruction != nullptr) {
6096 IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, node, type_instruction, init_value,
6097 &result_loc_var->base);
6098 ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base);
6099 }
55146100
5515 return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value);6101 return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca);
5516}6102}
55176103
5518static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {6104static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
6105 ResultLoc *result_loc)
6106{
5519 assert(node->type == NodeTypeWhileExpr);6107 assert(node->type == NodeTypeWhileExpr);
55206108
5521 AstNode *continue_expr_node = node->data.while_expr.continue_expr;6109 AstNode *continue_expr_node = node->data.while_expr.continue_expr;
...@@ -5550,25 +6138,33 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5550,25 +6138,33 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5550 } else {6138 } else {
5551 payload_scope = subexpr_scope;6139 payload_scope = subexpr_scope;
5552 }6140 }
5553 IrInstruction *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr);6141 IrInstruction *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,
6142 LValPtr, nullptr);
5554 if (err_val_ptr == irb->codegen->invalid_instruction)6143 if (err_val_ptr == irb->codegen->invalid_instruction)
5555 return err_val_ptr;6144 return err_val_ptr;
5556 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, err_val_ptr);6145 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, true);
5557 IrInstruction *is_err = ir_build_test_err(irb, scope, node->data.while_expr.condition, err_val);
5558 IrBasicBlock *after_cond_block = irb->current_basic_block;6146 IrBasicBlock *after_cond_block = irb->current_basic_block;
5559 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));6147 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
6148 IrInstruction *cond_br_inst;
5560 if (!instr_is_unreachable(is_err)) {6149 if (!instr_is_unreachable(is_err)) {
5561 ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err,6150 cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err,
5562 else_block, body_block, is_comptime));6151 else_block, body_block, is_comptime);
6152 cond_br_inst->is_gen = true;
6153 } else {
6154 // for the purposes of the source instruction to ir_build_result_peers
6155 cond_br_inst = irb->current_basic_block->instruction_list.last();
5563 }6156 }
55646157
6158 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
6159 is_comptime);
6160
5565 ir_set_cursor_at_end_and_append_block(irb, body_block);6161 ir_set_cursor_at_end_and_append_block(irb, body_block);
5566 if (var_symbol) {6162 if (var_symbol) {
5567 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,6163 IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,
5568 err_val_ptr, false);6164 err_val_ptr, false, false);
5569 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?6165 IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ?
5570 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);6166 ir_build_ref(irb, payload_scope, symbol_node, payload_ptr, true, false) : payload_ptr;
5571 ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);6167 ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_ptr);
5572 }6168 }
55736169
5574 ZigList<IrInstruction *> incoming_values = {0};6170 ZigList<IrInstruction *> incoming_values = {0};
...@@ -5580,7 +6176,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5580,7 +6176,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5580 loop_scope->is_comptime = is_comptime;6176 loop_scope->is_comptime = is_comptime;
5581 loop_scope->incoming_blocks = &incoming_blocks;6177 loop_scope->incoming_blocks = &incoming_blocks;
5582 loop_scope->incoming_values = &incoming_values;6178 loop_scope->incoming_values = &incoming_values;
6179 loop_scope->lval = lval;
6180 loop_scope->peer_parent = peer_parent;
55836181
6182 // Note the body block of the loop is not the place that lval and result_loc are used -
6183 // it's actually in break statements, handled similarly to return statements.
6184 // That is why we set those values in loop_scope above and not in this ir_gen_node call.
5584 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);6185 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
5585 if (body_result == irb->codegen->invalid_instruction)6186 if (body_result == irb->codegen->invalid_instruction)
5586 return body_result;6187 return body_result;
...@@ -5609,10 +6210,15 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5609,10 +6210,15 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5609 ZigVar *err_var = ir_create_var(irb, err_symbol_node, scope, err_symbol,6210 ZigVar *err_var = ir_create_var(irb, err_symbol_node, scope, err_symbol,
5610 true, false, false, is_comptime);6211 true, false, false, is_comptime);
5611 Scope *err_scope = err_var->child_scope;6212 Scope *err_scope = err_var->child_scope;
5612 IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);6213 IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
5613 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);6214 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr);
56146215
5615 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);6216 if (peer_parent->peers.length != 0) {
6217 peer_parent->peers.last()->next_bb = else_block;
6218 }
6219 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6220 peer_parent->peers.append(peer_result);
6221 IrInstruction *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base);
5616 if (else_result == irb->codegen->invalid_instruction)6222 if (else_result == irb->codegen->invalid_instruction)
5617 return else_result;6223 return else_result;
5618 if (!instr_is_unreachable(else_result))6224 if (!instr_is_unreachable(else_result))
...@@ -5626,8 +6232,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5626,8 +6232,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5626 incoming_blocks.append(after_cond_block);6232 incoming_blocks.append(after_cond_block);
5627 incoming_values.append(void_else_result);6233 incoming_values.append(void_else_result);
5628 }6234 }
6235 if (peer_parent->peers.length != 0) {
6236 peer_parent->peers.last()->next_bb = end_block;
6237 }
56296238
5630 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);6239 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
6240 incoming_blocks.items, incoming_values.items, peer_parent);
6241 return ir_expr_wrap(irb, scope, phi, result_loc);
5631 } else if (var_symbol != nullptr) {6242 } else if (var_symbol != nullptr) {
5632 ir_set_cursor_at_end_and_append_block(irb, cond_block);6243 ir_set_cursor_at_end_and_append_block(irb, cond_block);
5633 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);6244 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
...@@ -5637,23 +6248,32 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5637,23 +6248,32 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5637 ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol,6248 ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol,
5638 true, false, false, is_comptime);6249 true, false, false, is_comptime);
5639 Scope *child_scope = payload_var->child_scope;6250 Scope *child_scope = payload_var->child_scope;
5640 IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr);6251 IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,
6252 LValPtr, nullptr);
5641 if (maybe_val_ptr == irb->codegen->invalid_instruction)6253 if (maybe_val_ptr == irb->codegen->invalid_instruction)
5642 return maybe_val_ptr;6254 return maybe_val_ptr;
5643 IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr);6255 IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr);
5644 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node->data.while_expr.condition, maybe_val);6256 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node->data.while_expr.condition, maybe_val);
5645 IrBasicBlock *after_cond_block = irb->current_basic_block;6257 IrBasicBlock *after_cond_block = irb->current_basic_block;
5646 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));6258 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
6259 IrInstruction *cond_br_inst;
5647 if (!instr_is_unreachable(is_non_null)) {6260 if (!instr_is_unreachable(is_non_null)) {
5648 ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null,6261 cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null,
5649 body_block, else_block, is_comptime));6262 body_block, else_block, is_comptime);
6263 cond_br_inst->is_gen = true;
6264 } else {
6265 // for the purposes of the source instruction to ir_build_result_peers
6266 cond_br_inst = irb->current_basic_block->instruction_list.last();
5650 }6267 }
56516268
6269 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
6270 is_comptime);
6271
5652 ir_set_cursor_at_end_and_append_block(irb, body_block);6272 ir_set_cursor_at_end_and_append_block(irb, body_block);
5653 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);6273 IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false, false);
5654 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?6274 IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ?
5655 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);6275 ir_build_ref(irb, child_scope, symbol_node, payload_ptr, true, false) : payload_ptr;
5656 ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);6276 ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_ptr);
56576277
5658 ZigList<IrInstruction *> incoming_values = {0};6278 ZigList<IrInstruction *> incoming_values = {0};
5659 ZigList<IrBasicBlock *> incoming_blocks = {0};6279 ZigList<IrBasicBlock *> incoming_blocks = {0};
...@@ -5664,7 +6284,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5664,7 +6284,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5664 loop_scope->is_comptime = is_comptime;6284 loop_scope->is_comptime = is_comptime;
5665 loop_scope->incoming_blocks = &incoming_blocks;6285 loop_scope->incoming_blocks = &incoming_blocks;
5666 loop_scope->incoming_values = &incoming_values;6286 loop_scope->incoming_values = &incoming_values;
6287 loop_scope->lval = lval;
6288 loop_scope->peer_parent = peer_parent;
56676289
6290 // Note the body block of the loop is not the place that lval and result_loc are used -
6291 // it's actually in break statements, handled similarly to return statements.
6292 // That is why we set those values in loop_scope above and not in this ir_gen_node call.
5668 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);6293 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
5669 if (body_result == irb->codegen->invalid_instruction)6294 if (body_result == irb->codegen->invalid_instruction)
5670 return body_result;6295 return body_result;
...@@ -5689,7 +6314,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5689,7 +6314,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5689 if (else_node) {6314 if (else_node) {
5690 ir_set_cursor_at_end_and_append_block(irb, else_block);6315 ir_set_cursor_at_end_and_append_block(irb, else_block);
56916316
5692 else_result = ir_gen_node(irb, else_node, scope);6317 if (peer_parent->peers.length != 0) {
6318 peer_parent->peers.last()->next_bb = else_block;
6319 }
6320 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6321 peer_parent->peers.append(peer_result);
6322 else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_result->base);
5693 if (else_result == irb->codegen->invalid_instruction)6323 if (else_result == irb->codegen->invalid_instruction)
5694 return else_result;6324 return else_result;
5695 if (!instr_is_unreachable(else_result))6325 if (!instr_is_unreachable(else_result))
...@@ -5704,8 +6334,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5704,8 +6334,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5704 incoming_blocks.append(after_cond_block);6334 incoming_blocks.append(after_cond_block);
5705 incoming_values.append(void_else_result);6335 incoming_values.append(void_else_result);
5706 }6336 }
6337 if (peer_parent->peers.length != 0) {
6338 peer_parent->peers.last()->next_bb = end_block;
6339 }
57076340
5708 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);6341 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
6342 incoming_blocks.items, incoming_values.items, peer_parent);
6343 return ir_expr_wrap(irb, scope, phi, result_loc);
5709 } else {6344 } else {
5710 ir_set_cursor_at_end_and_append_block(irb, cond_block);6345 ir_set_cursor_at_end_and_append_block(irb, cond_block);
5711 IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope);6346 IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope);
...@@ -5713,11 +6348,18 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5713,11 +6348,18 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5713 return cond_val;6348 return cond_val;
5714 IrBasicBlock *after_cond_block = irb->current_basic_block;6349 IrBasicBlock *after_cond_block = irb->current_basic_block;
5715 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));6350 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
6351 IrInstruction *cond_br_inst;
5716 if (!instr_is_unreachable(cond_val)) {6352 if (!instr_is_unreachable(cond_val)) {
5717 ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val,6353 cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val,
5718 body_block, else_block, is_comptime));6354 body_block, else_block, is_comptime);
6355 cond_br_inst->is_gen = true;
6356 } else {
6357 // for the purposes of the source instruction to ir_build_result_peers
6358 cond_br_inst = irb->current_basic_block->instruction_list.last();
5719 }6359 }
57206360
6361 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc,
6362 is_comptime);
5721 ir_set_cursor_at_end_and_append_block(irb, body_block);6363 ir_set_cursor_at_end_and_append_block(irb, body_block);
57226364
5723 ZigList<IrInstruction *> incoming_values = {0};6365 ZigList<IrInstruction *> incoming_values = {0};
...@@ -5731,7 +6373,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5731,7 +6373,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5731 loop_scope->is_comptime = is_comptime;6373 loop_scope->is_comptime = is_comptime;
5732 loop_scope->incoming_blocks = &incoming_blocks;6374 loop_scope->incoming_blocks = &incoming_blocks;
5733 loop_scope->incoming_values = &incoming_values;6375 loop_scope->incoming_values = &incoming_values;
6376 loop_scope->lval = lval;
6377 loop_scope->peer_parent = peer_parent;
57346378
6379 // Note the body block of the loop is not the place that lval and result_loc are used -
6380 // it's actually in break statements, handled similarly to return statements.
6381 // That is why we set those values in loop_scope above and not in this ir_gen_node call.
5735 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);6382 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
5736 if (body_result == irb->codegen->invalid_instruction)6383 if (body_result == irb->codegen->invalid_instruction)
5737 return body_result;6384 return body_result;
...@@ -5756,7 +6403,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5756,7 +6403,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5756 if (else_node) {6403 if (else_node) {
5757 ir_set_cursor_at_end_and_append_block(irb, else_block);6404 ir_set_cursor_at_end_and_append_block(irb, else_block);
57586405
5759 else_result = ir_gen_node(irb, else_node, subexpr_scope);6406 if (peer_parent->peers.length != 0) {
6407 peer_parent->peers.last()->next_bb = else_block;
6408 }
6409 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6410 peer_parent->peers.append(peer_result);
6411
6412 else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_result->base);
5760 if (else_result == irb->codegen->invalid_instruction)6413 if (else_result == irb->codegen->invalid_instruction)
5761 return else_result;6414 return else_result;
5762 if (!instr_is_unreachable(else_result))6415 if (!instr_is_unreachable(else_result))
...@@ -5771,12 +6424,19 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5771,12 +6424,19 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5771 incoming_blocks.append(after_cond_block);6424 incoming_blocks.append(after_cond_block);
5772 incoming_values.append(void_else_result);6425 incoming_values.append(void_else_result);
5773 }6426 }
6427 if (peer_parent->peers.length != 0) {
6428 peer_parent->peers.last()->next_bb = end_block;
6429 }
57746430
5775 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);6431 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length,
6432 incoming_blocks.items, incoming_values.items, peer_parent);
6433 return ir_expr_wrap(irb, scope, phi, result_loc);
5776 }6434 }
5777}6435}
57786436
5779static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNode *node) {6437static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,
6438 ResultLoc *result_loc)
6439{
5780 assert(node->type == NodeTypeForExpr);6440 assert(node->type == NodeTypeForExpr);
57816441
5782 AstNode *array_node = node->data.for_expr.array_expr;6442 AstNode *array_node = node->data.for_expr.array_expr;
...@@ -5791,76 +6451,67 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5791,76 +6451,67 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5791 }6451 }
5792 assert(elem_node->type == NodeTypeSymbol);6452 assert(elem_node->type == NodeTypeSymbol);
57936453
5794 IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LValPtr);6454 IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LValPtr, nullptr);
5795 if (array_val_ptr == irb->codegen->invalid_instruction)6455 if (array_val_ptr == irb->codegen->invalid_instruction)
5796 return array_val_ptr;6456 return array_val_ptr;
57976457
5798 IrInstruction *pointer_type = ir_build_to_ptr_type(irb, parent_scope, array_node, array_val_ptr);
5799 IrInstruction *elem_var_type;
5800 if (node->data.for_expr.elem_is_ptr) {
5801 elem_var_type = pointer_type;
5802 } else {
5803 elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);
5804 }
5805
5806 IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,6458 IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,
5807 ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline);6459 ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline);
58086460
5809 // TODO make it an error to write to element variable or i variable.
5810 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
5811 ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
5812 Scope *child_scope = elem_var->child_scope;
5813
5814 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
5815 ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
5816 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
5817
5818 AstNode *index_var_source_node;6461 AstNode *index_var_source_node;
5819 ZigVar *index_var;6462 ZigVar *index_var;
6463 const char *index_var_name;
5820 if (index_node) {6464 if (index_node) {
5821 index_var_source_node = index_node;6465 index_var_source_node = index_node;
5822 Buf *index_var_name = index_node->data.symbol_expr.symbol;6466 Buf *index_var_name_buf = index_node->data.symbol_expr.symbol;
5823 index_var = ir_create_var(irb, index_node, child_scope, index_var_name, true, false, false, is_comptime);6467 index_var = ir_create_var(irb, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime);
6468 index_var_name = buf_ptr(index_var_name_buf);
5824 } else {6469 } else {
5825 index_var_source_node = node;6470 index_var_source_node = node;
5826 index_var = ir_create_var(irb, node, child_scope, nullptr, true, false, true, is_comptime);6471 index_var = ir_create_var(irb, node, parent_scope, nullptr, true, false, true, is_comptime);
6472 index_var_name = "i";
5827 }6473 }
5828 child_scope = index_var->child_scope;
58296474
5830 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);6475 IrInstruction *zero = ir_build_const_usize(irb, parent_scope, node, 0);
5831 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);6476 build_decl_var_and_init(irb, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime);
5832 IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);6477 parent_scope = index_var->child_scope;
5833 ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);6478
5834 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);6479 IrInstruction *one = ir_build_const_usize(irb, parent_scope, node, 1);
6480 IrInstruction *index_ptr = ir_build_var_ptr(irb, parent_scope, node, index_var);
58356481
58366482
5837 IrBasicBlock *cond_block = ir_create_basic_block(irb, child_scope, "ForCond");6483 IrBasicBlock *cond_block = ir_create_basic_block(irb, parent_scope, "ForCond");
5838 IrBasicBlock *body_block = ir_create_basic_block(irb, child_scope, "ForBody");6484 IrBasicBlock *body_block = ir_create_basic_block(irb, parent_scope, "ForBody");
5839 IrBasicBlock *end_block = ir_create_basic_block(irb, child_scope, "ForEnd");6485 IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "ForEnd");
5840 IrBasicBlock *else_block = else_node ? ir_create_basic_block(irb, child_scope, "ForElse") : end_block;6486 IrBasicBlock *else_block = else_node ? ir_create_basic_block(irb, parent_scope, "ForElse") : end_block;
5841 IrBasicBlock *continue_block = ir_create_basic_block(irb, child_scope, "ForContinue");6487 IrBasicBlock *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue");
58426488
5843 Buf *len_field_name = buf_create_from_str("len");6489 Buf *len_field_name = buf_create_from_str("len");
5844 IrInstruction *len_ref = ir_build_field_ptr(irb, child_scope, node, array_val_ptr, len_field_name);6490 IrInstruction *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false);
5845 IrInstruction *len_val = ir_build_load_ptr(irb, child_scope, node, len_ref);6491 IrInstruction *len_val = ir_build_load_ptr(irb, parent_scope, node, len_ref);
5846 ir_build_br(irb, child_scope, node, cond_block, is_comptime);6492 ir_build_br(irb, parent_scope, node, cond_block, is_comptime);
58476493
5848 ir_set_cursor_at_end_and_append_block(irb, cond_block);6494 ir_set_cursor_at_end_and_append_block(irb, cond_block);
5849 IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);6495 IrInstruction *index_val = ir_build_load_ptr(irb, parent_scope, node, index_ptr);
5850 IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);6496 IrInstruction *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
5851 IrBasicBlock *after_cond_block = irb->current_basic_block;6497 IrBasicBlock *after_cond_block = irb->current_basic_block;
5852 IrInstruction *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node));6498 IrInstruction *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node));
5853 ir_mark_gen(ir_build_cond_br(irb, child_scope, node, cond, body_block, else_block, is_comptime));6499 IrInstruction *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond,
6500 body_block, else_block, is_comptime));
6501
6502 ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime);
58546503
5855 ir_set_cursor_at_end_and_append_block(irb, body_block);6504 ir_set_cursor_at_end_and_append_block(irb, body_block);
5856 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false, PtrLenSingle);6505 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false,
5857 IrInstruction *elem_val;6506 PtrLenSingle, nullptr);
5858 if (node->data.for_expr.elem_is_ptr) {6507 // TODO make it an error to write to element variable or i variable.
5859 elem_val = elem_ptr;6508 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
5860 } else {6509 ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
5861 elem_val = ir_build_load_ptr(irb, child_scope, node, elem_ptr);6510 Scope *child_scope = elem_var->child_scope;
5862 }6511
5863 ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val));6512 IrInstruction *var_ptr = node->data.for_expr.elem_is_ptr ?
6513 ir_build_ref(irb, parent_scope, elem_node, elem_ptr, true, false) : elem_ptr;
6514 ir_build_var_decl_src(irb, parent_scope, elem_node, elem_var, nullptr, var_ptr);
58646515
5865 ZigList<IrInstruction *> incoming_values = {0};6516 ZigList<IrInstruction *> incoming_values = {0};
5866 ZigList<IrBasicBlock *> incoming_blocks = {0};6517 ZigList<IrBasicBlock *> incoming_blocks = {0};
...@@ -5870,7 +6521,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5870,7 +6521,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5870 loop_scope->is_comptime = is_comptime;6521 loop_scope->is_comptime = is_comptime;
5871 loop_scope->incoming_blocks = &incoming_blocks;6522 loop_scope->incoming_blocks = &incoming_blocks;
5872 loop_scope->incoming_values = &incoming_values;6523 loop_scope->incoming_values = &incoming_values;
6524 loop_scope->lval = LValNone;
6525 loop_scope->peer_parent = peer_parent;
58736526
6527 // Note the body block of the loop is not the place that lval and result_loc are used -
6528 // it's actually in break statements, handled similarly to return statements.
6529 // That is why we set those values in loop_scope above and not in this ir_gen_node call.
5874 IrInstruction *body_result = ir_gen_node(irb, body_node, &loop_scope->base);6530 IrInstruction *body_result = ir_gen_node(irb, body_node, &loop_scope->base);
58756531
5876 if (!instr_is_unreachable(body_result)) {6532 if (!instr_is_unreachable(body_result)) {
...@@ -5887,7 +6543,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5887,7 +6543,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5887 if (else_node) {6543 if (else_node) {
5888 ir_set_cursor_at_end_and_append_block(irb, else_block);6544 ir_set_cursor_at_end_and_append_block(irb, else_block);
58896545
5890 else_result = ir_gen_node(irb, else_node, parent_scope);6546 if (peer_parent->peers.length != 0) {
6547 peer_parent->peers.last()->next_bb = else_block;
6548 }
6549 ResultLocPeer *peer_result = create_peer_result(peer_parent);
6550 peer_parent->peers.append(peer_result);
6551 else_result = ir_gen_node_extra(irb, else_node, parent_scope, LValNone, &peer_result->base);
5891 if (else_result == irb->codegen->invalid_instruction)6552 if (else_result == irb->codegen->invalid_instruction)
5892 return else_result;6553 return else_result;
5893 if (!instr_is_unreachable(else_result))6554 if (!instr_is_unreachable(else_result))
...@@ -5903,8 +6564,13 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5903,8 +6564,13 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5903 incoming_blocks.append(after_cond_block);6564 incoming_blocks.append(after_cond_block);
5904 incoming_values.append(void_else_value);6565 incoming_values.append(void_else_value);
5905 }6566 }
6567 if (peer_parent->peers.length != 0) {
6568 peer_parent->peers.last()->next_bb = end_block;
6569 }
59066570
5907 return ir_build_phi(irb, parent_scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);6571 IrInstruction *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length,
6572 incoming_blocks.items, incoming_values.items, peer_parent);
6573 return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc);
5908}6574}
59096575
5910static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, Scope *scope, AstNode *node) {6576static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -6189,7 +6855,9 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -6189,7 +6855,9 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
6189 input_list, output_types, output_vars, return_count, is_volatile);6855 input_list, output_types, output_vars, return_count, is_volatile);
6190}6856}
61916857
6192static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) {6858static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
6859 ResultLoc *result_loc)
6860{
6193 assert(node->type == NodeTypeIfOptional);6861 assert(node->type == NodeTypeIfOptional);
61946862
6195 Buf *var_symbol = node->data.test_expr.var_symbol;6863 Buf *var_symbol = node->data.test_expr.var_symbol;
...@@ -6198,7 +6866,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN...@@ -6198,7 +6866,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
6198 AstNode *else_node = node->data.test_expr.else_node;6866 AstNode *else_node = node->data.test_expr.else_node;
6199 bool var_is_ptr = node->data.test_expr.var_is_ptr;6867 bool var_is_ptr = node->data.test_expr.var_is_ptr;
62006868
6201 IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);6869 IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
6202 if (maybe_val_ptr == irb->codegen->invalid_instruction)6870 if (maybe_val_ptr == irb->codegen->invalid_instruction)
6203 return maybe_val_ptr;6871 return maybe_val_ptr;
62046872
...@@ -6215,27 +6883,31 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN...@@ -6215,27 +6883,31 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
6215 } else {6883 } else {
6216 is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);6884 is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);
6217 }6885 }
6218 ir_build_cond_br(irb, scope, node, is_non_null, then_block, else_block, is_comptime);6886 IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null,
6887 then_block, else_block, is_comptime);
6888
6889 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
6890 result_loc, is_comptime);
62196891
6220 ir_set_cursor_at_end_and_append_block(irb, then_block);6892 ir_set_cursor_at_end_and_append_block(irb, then_block);
62216893
6222 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);6894 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
6223 Scope *var_scope;6895 Scope *var_scope;
6224 if (var_symbol) {6896 if (var_symbol) {
6225 IrInstruction *var_type = nullptr;
6226 bool is_shadowable = false;6897 bool is_shadowable = false;
6227 bool is_const = true;6898 bool is_const = true;
6228 ZigVar *var = ir_create_var(irb, node, subexpr_scope,6899 ZigVar *var = ir_create_var(irb, node, subexpr_scope,
6229 var_symbol, is_const, is_const, is_shadowable, is_comptime);6900 var_symbol, is_const, is_const, is_shadowable, is_comptime);
62306901
6231 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false);6902 IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false, false);
6232 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);6903 IrInstruction *var_ptr = var_is_ptr ? ir_build_ref(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr;
6233 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);6904 ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr);
6234 var_scope = var->child_scope;6905 var_scope = var->child_scope;
6235 } else {6906 } else {
6236 var_scope = subexpr_scope;6907 var_scope = subexpr_scope;
6237 }6908 }
6238 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope);6909 IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,
6910 &peer_parent->peers.at(0)->base);
6239 if (then_expr_result == irb->codegen->invalid_instruction)6911 if (then_expr_result == irb->codegen->invalid_instruction)
6240 return then_expr_result;6912 return then_expr_result;
6241 IrBasicBlock *after_then_block = irb->current_basic_block;6913 IrBasicBlock *after_then_block = irb->current_basic_block;
...@@ -6245,11 +6917,12 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN...@@ -6245,11 +6917,12 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
6245 ir_set_cursor_at_end_and_append_block(irb, else_block);6917 ir_set_cursor_at_end_and_append_block(irb, else_block);
6246 IrInstruction *else_expr_result;6918 IrInstruction *else_expr_result;
6247 if (else_node) {6919 if (else_node) {
6248 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);6920 else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base);
6249 if (else_expr_result == irb->codegen->invalid_instruction)6921 if (else_expr_result == irb->codegen->invalid_instruction)
6250 return else_expr_result;6922 return else_expr_result;
6251 } else {6923 } else {
6252 else_expr_result = ir_build_const_void(irb, scope, node);6924 else_expr_result = ir_build_const_void(irb, scope, node);
6925 ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
6253 }6926 }
6254 IrBasicBlock *after_else_block = irb->current_basic_block;6927 IrBasicBlock *after_else_block = irb->current_basic_block;
6255 if (!instr_is_unreachable(else_expr_result))6928 if (!instr_is_unreachable(else_expr_result))
...@@ -6263,10 +6936,13 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN...@@ -6263,10 +6936,13 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
6263 incoming_blocks[0] = after_then_block;6936 incoming_blocks[0] = after_then_block;
6264 incoming_blocks[1] = after_else_block;6937 incoming_blocks[1] = after_else_block;
62656938
6266 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);6939 IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent);
6940 return ir_expr_wrap(irb, scope, phi, result_loc);
6267}6941}
62686942
6269static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *node) {6943static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
6944 ResultLoc *result_loc)
6945{
6270 assert(node->type == NodeTypeIfErrorExpr);6946 assert(node->type == NodeTypeIfErrorExpr);
62716947
6272 AstNode *target_node = node->data.if_err_expr.target_node;6948 AstNode *target_node = node->data.if_err_expr.target_node;
...@@ -6277,12 +6953,12 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6277,12 +6953,12 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
6277 Buf *var_symbol = node->data.if_err_expr.var_symbol;6953 Buf *var_symbol = node->data.if_err_expr.var_symbol;
6278 Buf *err_symbol = node->data.if_err_expr.err_symbol;6954 Buf *err_symbol = node->data.if_err_expr.err_symbol;
62796955
6280 IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr);6956 IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr);
6281 if (err_val_ptr == irb->codegen->invalid_instruction)6957 if (err_val_ptr == irb->codegen->invalid_instruction)
6282 return err_val_ptr;6958 return err_val_ptr;
62836959
6284 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);6960 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
6285 IrInstruction *is_err = ir_build_test_err(irb, scope, node, err_val);6961 IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true);
62866962
6287 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");6963 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");
6288 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");6964 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");
...@@ -6290,27 +6966,31 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6290,27 +6966,31 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
62906966
6291 bool force_comptime = ir_should_inline(irb->exec, scope);6967 bool force_comptime = ir_should_inline(irb->exec, scope);
6292 IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err);6968 IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err);
6293 ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);6969 IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);
6970
6971 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
6972 result_loc, is_comptime);
62946973
6295 ir_set_cursor_at_end_and_append_block(irb, ok_block);6974 ir_set_cursor_at_end_and_append_block(irb, ok_block);
62966975
6297 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);6976 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
6298 Scope *var_scope;6977 Scope *var_scope;
6299 if (var_symbol) {6978 if (var_symbol) {
6300 IrInstruction *var_type = nullptr;
6301 bool is_shadowable = false;6979 bool is_shadowable = false;
6302 IrInstruction *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val);6980 IrInstruction *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val);
6303 ZigVar *var = ir_create_var(irb, node, subexpr_scope,6981 ZigVar *var = ir_create_var(irb, node, subexpr_scope,
6304 var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime);6982 var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime);
63056983
6306 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);6984 IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false, false);
6307 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);6985 IrInstruction *var_ptr = var_is_ptr ?
6308 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);6986 ir_build_ref(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr;
6987 ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr);
6309 var_scope = var->child_scope;6988 var_scope = var->child_scope;
6310 } else {6989 } else {
6311 var_scope = subexpr_scope;6990 var_scope = subexpr_scope;
6312 }6991 }
6313 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope);6992 IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval,
6993 &peer_parent->peers.at(0)->base);
6314 if (then_expr_result == irb->codegen->invalid_instruction)6994 if (then_expr_result == irb->codegen->invalid_instruction)
6315 return then_expr_result;6995 return then_expr_result;
6316 IrBasicBlock *after_then_block = irb->current_basic_block;6996 IrBasicBlock *after_then_block = irb->current_basic_block;
...@@ -6323,23 +7003,23 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6323,23 +7003,23 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
6323 if (else_node) {7003 if (else_node) {
6324 Scope *err_var_scope;7004 Scope *err_var_scope;
6325 if (err_symbol) {7005 if (err_symbol) {
6326 IrInstruction *var_type = nullptr;
6327 bool is_shadowable = false;7006 bool is_shadowable = false;
6328 bool is_const = true;7007 bool is_const = true;
6329 ZigVar *var = ir_create_var(irb, node, subexpr_scope,7008 ZigVar *var = ir_create_var(irb, node, subexpr_scope,
6330 err_symbol, is_const, is_const, is_shadowable, is_comptime);7009 err_symbol, is_const, is_const, is_shadowable, is_comptime);
63317010
6332 IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);7011 IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
6333 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);7012 ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, err_ptr);
6334 err_var_scope = var->child_scope;7013 err_var_scope = var->child_scope;
6335 } else {7014 } else {
6336 err_var_scope = subexpr_scope;7015 err_var_scope = subexpr_scope;
6337 }7016 }
6338 else_expr_result = ir_gen_node(irb, else_node, err_var_scope);7017 else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base);
6339 if (else_expr_result == irb->codegen->invalid_instruction)7018 if (else_expr_result == irb->codegen->invalid_instruction)
6340 return else_expr_result;7019 return else_expr_result;
6341 } else {7020 } else {
6342 else_expr_result = ir_build_const_void(irb, scope, node);7021 else_expr_result = ir_build_const_void(irb, scope, node);
7022 ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base);
6343 }7023 }
6344 IrBasicBlock *after_else_block = irb->current_basic_block;7024 IrBasicBlock *after_else_block = irb->current_basic_block;
6345 if (!instr_is_unreachable(else_expr_result))7025 if (!instr_is_unreachable(else_expr_result))
...@@ -6353,14 +7033,15 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6353,14 +7033,15 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
6353 incoming_blocks[0] = after_then_block;7033 incoming_blocks[0] = after_then_block;
6354 incoming_blocks[1] = after_else_block;7034 incoming_blocks[1] = after_else_block;
63557035
6356 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);7036 IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent);
7037 return ir_expr_wrap(irb, scope, phi, result_loc);
6357}7038}
63587039
6359static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,7040static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,
6360 IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime,7041 IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime,
6361 IrInstruction *target_value_ptr, IrInstruction **prong_values, size_t prong_values_len,7042 IrInstruction *target_value_ptr, IrInstruction **prong_values, size_t prong_values_len,
6362 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values,7043 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values,
6363 IrInstructionSwitchElseVar **out_switch_else_var)7044 IrInstructionSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc)
6364{7045{
6365 assert(switch_node->type == NodeTypeSwitchExpr);7046 assert(switch_node->type == NodeTypeSwitchExpr);
6366 assert(prong_node->type == NodeTypeSwitchProng);7047 assert(prong_node->type == NodeTypeSwitchProng);
...@@ -6378,28 +7059,27 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit...@@ -6378,28 +7059,27 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
6378 ZigVar *var = ir_create_var(irb, var_symbol_node, scope,7059 ZigVar *var = ir_create_var(irb, var_symbol_node, scope,
6379 var_name, is_const, is_const, is_shadowable, var_is_comptime);7060 var_name, is_const, is_const, is_shadowable, var_is_comptime);
6380 child_scope = var->child_scope;7061 child_scope = var->child_scope;
6381 IrInstruction *var_value;7062 IrInstruction *var_ptr;
6382 if (out_switch_else_var != nullptr) {7063 if (out_switch_else_var != nullptr) {
6383 IrInstructionSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node,7064 IrInstructionSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node,
6384 target_value_ptr);7065 target_value_ptr);
6385 *out_switch_else_var = switch_else_var;7066 *out_switch_else_var = switch_else_var;
6386 IrInstruction *var_ptr_value = &switch_else_var->base;7067 IrInstruction *payload_ptr = &switch_else_var->base;
6387 var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value);7068 var_ptr = var_is_ptr ? ir_build_ref(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr;
6388 } else if (prong_values != nullptr) {7069 } else if (prong_values != nullptr) {
6389 IrInstruction *var_ptr_value = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr,7070 IrInstruction *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr,
6390 prong_values, prong_values_len);7071 prong_values, prong_values_len);
6391 var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value);7072 var_ptr = var_is_ptr ? ir_build_ref(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr;
6392 } else {7073 } else {
6393 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, 7074 var_ptr = var_is_ptr ?
6394target_value_ptr);7075 ir_build_ref(irb, scope, var_symbol_node, target_value_ptr, true, false) : target_value_ptr;
6395 }7076 }
6396 IrInstruction *var_type = nullptr; // infer the type7077 ir_build_var_decl_src(irb, scope, var_symbol_node, var, nullptr, var_ptr);
6397 ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
6398 } else {7078 } else {
6399 child_scope = scope;7079 child_scope = scope;
6400 }7080 }
64017081
6402 IrInstruction *expr_result = ir_gen_node(irb, expr_node, child_scope);7082 IrInstruction *expr_result = ir_gen_node_extra(irb, expr_node, child_scope, lval, result_loc);
6403 if (expr_result == irb->codegen->invalid_instruction)7083 if (expr_result == irb->codegen->invalid_instruction)
6404 return false;7084 return false;
6405 if (!instr_is_unreachable(expr_result))7085 if (!instr_is_unreachable(expr_result))
...@@ -6409,11 +7089,13 @@ target_value_ptr);...@@ -6409,11 +7089,13 @@ target_value_ptr);
6409 return true;7089 return true;
6410}7090}
64117091
6412static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node) {7092static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
7093 ResultLoc *result_loc)
7094{
6413 assert(node->type == NodeTypeSwitchExpr);7095 assert(node->type == NodeTypeSwitchExpr);
64147096
6415 AstNode *target_node = node->data.switch_expr.expr;7097 AstNode *target_node = node->data.switch_expr.expr;
6416 IrInstruction *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr);7098 IrInstruction *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr);
6417 if (target_value_ptr == irb->codegen->invalid_instruction)7099 if (target_value_ptr == irb->codegen->invalid_instruction)
6418 return target_value_ptr;7100 return target_value_ptr;
6419 IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr);7101 IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr);
...@@ -6440,6 +7122,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6440,6 +7122,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
64407122
6441 IrInstructionSwitchElseVar *switch_else_var = nullptr;7123 IrInstructionSwitchElseVar *switch_else_var = nullptr;
64427124
7125 ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);
7126 peer_parent->base.id = ResultLocIdPeerParent;
7127 peer_parent->end_bb = end_block;
7128 peer_parent->is_comptime = is_comptime;
7129 peer_parent->parent = result_loc;
7130
7131 ir_build_reset_result(irb, scope, node, &peer_parent->base);
7132
6443 // First do the else and the ranges7133 // First do the else and the ranges
6444 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);7134 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
6445 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);7135 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
...@@ -6448,6 +7138,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6448,6 +7138,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6448 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);7138 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
6449 size_t prong_item_count = prong_node->data.switch_prong.items.length;7139 size_t prong_item_count = prong_node->data.switch_prong.items.length;
6450 if (prong_item_count == 0) {7140 if (prong_item_count == 0) {
7141 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
6451 if (else_prong) {7142 if (else_prong) {
6452 ErrorMsg *msg = add_node_error(irb->codegen, prong_node,7143 ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
6453 buf_sprintf("multiple else prongs in switch expression"));7144 buf_sprintf("multiple else prongs in switch expression"));
...@@ -6458,15 +7149,21 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6458,15 +7149,21 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6458 else_prong = prong_node;7149 else_prong = prong_node;
64597150
6460 IrBasicBlock *prev_block = irb->current_basic_block;7151 IrBasicBlock *prev_block = irb->current_basic_block;
7152 if (peer_parent->peers.length > 0) {
7153 peer_parent->peers.last()->next_bb = else_block;
7154 }
7155 peer_parent->peers.append(this_peer_result_loc);
6461 ir_set_cursor_at_end_and_append_block(irb, else_block);7156 ir_set_cursor_at_end_and_append_block(irb, else_block);
6462 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,7157 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
6463 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,7158 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,
6464 &switch_else_var))7159 &switch_else_var, LValNone, &this_peer_result_loc->base))
6465 {7160 {
6466 return irb->codegen->invalid_instruction;7161 return irb->codegen->invalid_instruction;
6467 }7162 }
6468 ir_set_cursor_at_end(irb, prev_block);7163 ir_set_cursor_at_end(irb, prev_block);
6469 } else if (prong_node->data.switch_prong.any_items_are_range) {7164 } else if (prong_node->data.switch_prong.any_items_are_range) {
7165 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
7166
6470 IrInstruction *ok_bit = nullptr;7167 IrInstruction *ok_bit = nullptr;
6471 AstNode *last_item_node = nullptr;7168 AstNode *last_item_node = nullptr;
6472 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {7169 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
...@@ -6523,13 +7220,20 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6523,13 +7220,20 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
65237220
6524 assert(ok_bit);7221 assert(ok_bit);
6525 assert(last_item_node);7222 assert(last_item_node);
6526 ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes,7223 IrInstruction *br_inst = ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit,
6527 range_block_no, is_comptime));7224 range_block_yes, range_block_no, is_comptime));
7225 if (peer_parent->base.source_instruction == nullptr) {
7226 peer_parent->base.source_instruction = br_inst;
7227 }
65287228
7229 if (peer_parent->peers.length > 0) {
7230 peer_parent->peers.last()->next_bb = range_block_yes;
7231 }
7232 peer_parent->peers.append(this_peer_result_loc);
6529 ir_set_cursor_at_end_and_append_block(irb, range_block_yes);7233 ir_set_cursor_at_end_and_append_block(irb, range_block_yes);
6530 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,7234 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
6531 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0,7235 is_comptime, var_is_comptime, target_value_ptr, nullptr, 0,
6532 &incoming_blocks, &incoming_values, nullptr))7236 &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base))
6533 {7237 {
6534 return irb->codegen->invalid_instruction;7238 return irb->codegen->invalid_instruction;
6535 }7239 }
...@@ -6547,6 +7251,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6547,6 +7251,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6547 if (prong_node->data.switch_prong.any_items_are_range)7251 if (prong_node->data.switch_prong.any_items_are_range)
6548 continue;7252 continue;
65497253
7254 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
7255
6550 IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng");7256 IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng");
6551 IrInstruction **items = allocate<IrInstruction *>(prong_item_count);7257 IrInstruction **items = allocate<IrInstruction *>(prong_item_count);
65527258
...@@ -6570,10 +7276,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6570,10 +7276,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6570 }7276 }
65717277
6572 IrBasicBlock *prev_block = irb->current_basic_block;7278 IrBasicBlock *prev_block = irb->current_basic_block;
7279 if (peer_parent->peers.length > 0) {
7280 peer_parent->peers.last()->next_bb = prong_block;
7281 }
7282 peer_parent->peers.append(this_peer_result_loc);
6573 ir_set_cursor_at_end_and_append_block(irb, prong_block);7283 ir_set_cursor_at_end_and_append_block(irb, prong_block);
6574 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,7284 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
6575 is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count,7285 is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count,
6576 &incoming_blocks, &incoming_values, nullptr))7286 &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base))
6577 {7287 {
6578 return irb->codegen->invalid_instruction;7288 return irb->codegen->invalid_instruction;
6579 }7289 }
...@@ -6582,38 +7292,57 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6582,38 +7292,57 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
65827292
6583 }7293 }
65847294
6585 IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, check_ranges.items, check_ranges.length,7295 IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value,
6586 else_prong != nullptr);7296 check_ranges.items, check_ranges.length, else_prong != nullptr);
65877297
7298 IrInstruction *br_instruction;
6588 if (cases.length == 0) {7299 if (cases.length == 0) {
6589 ir_build_br(irb, scope, node, else_block, is_comptime);7300 br_instruction = ir_build_br(irb, scope, node, else_block, is_comptime);
6590 } else {7301 } else {
6591 IrInstructionSwitchBr *switch_br = ir_build_switch_br(irb, scope, node, target_value, else_block,7302 IrInstructionSwitchBr *switch_br = ir_build_switch_br(irb, scope, node, target_value, else_block,
6592 cases.length, cases.items, is_comptime, switch_prongs_void);7303 cases.length, cases.items, is_comptime, switch_prongs_void);
6593 if (switch_else_var != nullptr) {7304 if (switch_else_var != nullptr) {
6594 switch_else_var->switch_br = switch_br;7305 switch_else_var->switch_br = switch_br;
6595 }7306 }
7307 br_instruction = &switch_br->base;
7308 }
7309 if (peer_parent->base.source_instruction == nullptr) {
7310 peer_parent->base.source_instruction = br_instruction;
7311 }
7312 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
7313 peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction;
6596 }7314 }
65977315
6598 if (!else_prong) {7316 if (!else_prong) {
7317 if (peer_parent->peers.length != 0) {
7318 peer_parent->peers.last()->next_bb = else_block;
7319 }
6599 ir_set_cursor_at_end_and_append_block(irb, else_block);7320 ir_set_cursor_at_end_and_append_block(irb, else_block);
6600 ir_build_unreachable(irb, scope, node);7321 ir_build_unreachable(irb, scope, node);
7322 } else {
7323 if (peer_parent->peers.length != 0) {
7324 peer_parent->peers.last()->next_bb = end_block;
7325 }
6601 }7326 }
66027327
6603 ir_set_cursor_at_end_and_append_block(irb, end_block);7328 ir_set_cursor_at_end_and_append_block(irb, end_block);
6604 assert(incoming_blocks.length == incoming_values.length);7329 assert(incoming_blocks.length == incoming_values.length);
7330 IrInstruction *result_instruction;
6605 if (incoming_blocks.length == 0) {7331 if (incoming_blocks.length == 0) {
6606 return ir_build_const_void(irb, scope, node);7332 result_instruction = ir_build_const_void(irb, scope, node);
6607 } else {7333 } else {
6608 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);7334 result_instruction = ir_build_phi(irb, scope, node, incoming_blocks.length,
7335 incoming_blocks.items, incoming_values.items, peer_parent);
6609 }7336 }
7337 return ir_lval_wrap(irb, scope, result_instruction, lval, result_loc);
6610}7338}
66117339
6612static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval) {7340static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval) {
6613 assert(node->type == NodeTypeCompTime);7341 assert(node->type == NodeTypeCompTime);
66147342
6615 Scope *child_scope = create_comptime_scope(irb->codegen, node, parent_scope);7343 Scope *child_scope = create_comptime_scope(irb->codegen, node, parent_scope);
6616 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval);7344 // purposefully pass null for result_loc and let EndExpr handle it
7345 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);
6617}7346}
66187347
6619static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {7348static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {
...@@ -6626,7 +7355,11 @@ static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scop...@@ -6626,7 +7355,11 @@ static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scop
66267355
6627 IrInstruction *result_value;7356 IrInstruction *result_value;
6628 if (node->data.break_expr.expr) {7357 if (node->data.break_expr.expr) {
6629 result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope);7358 ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent);
7359 block_scope->peer_parent->peers.append(peer_result);
7360
7361 result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, block_scope->lval,
7362 &peer_result->base);
6630 if (result_value == irb->codegen->invalid_instruction)7363 if (result_value == irb->codegen->invalid_instruction)
6631 return irb->codegen->invalid_instruction;7364 return irb->codegen->invalid_instruction;
6632 } else {7365 } else {
...@@ -6696,7 +7429,11 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *...@@ -6696,7 +7429,11 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *
66967429
6697 IrInstruction *result_value;7430 IrInstruction *result_value;
6698 if (node->data.break_expr.expr) {7431 if (node->data.break_expr.expr) {
6699 result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope);7432 ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent);
7433 loop_scope->peer_parent->peers.append(peer_result);
7434
7435 result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope,
7436 loop_scope->lval, &peer_result->base);
6700 if (result_value == irb->codegen->invalid_instruction)7437 if (result_value == irb->codegen->invalid_instruction)
6701 return irb->codegen->invalid_instruction;7438 return irb->codegen->invalid_instruction;
6702 } else {7439 } else {
...@@ -6784,7 +7521,7 @@ static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -6784,7 +7521,7 @@ static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode
6784 return ir_build_const_void(irb, parent_scope, node);7521 return ir_build_const_void(irb, parent_scope, node);
6785}7522}
67867523
6787static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) {7524static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) {
6788 assert(node->type == NodeTypeSliceExpr);7525 assert(node->type == NodeTypeSliceExpr);
67897526
6790 AstNodeSliceExpr *slice_expr = &node->data.slice_expr;7527 AstNodeSliceExpr *slice_expr = &node->data.slice_expr;
...@@ -6792,7 +7529,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -6792,7 +7529,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
6792 AstNode *start_node = slice_expr->start;7529 AstNode *start_node = slice_expr->start;
6793 AstNode *end_node = slice_expr->end;7530 AstNode *end_node = slice_expr->end;
67947531
6795 IrInstruction *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr);7532 IrInstruction *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr, nullptr);
6796 if (ptr_value == irb->codegen->invalid_instruction)7533 if (ptr_value == irb->codegen->invalid_instruction)
6797 return irb->codegen->invalid_instruction;7534 return irb->codegen->invalid_instruction;
67987535
...@@ -6809,11 +7546,14 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -6809,11 +7546,14 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
6809 end_value = nullptr;7546 end_value = nullptr;
6810 }7547 }
68117548
6812 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);7549 IrInstruction *slice = ir_build_slice_src(irb, scope, node, ptr_value, start_value, end_value, true, result_loc);
7550 return ir_lval_wrap(irb, scope, slice, lval, result_loc);
6813}7551}
68147552
6815static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) {7553static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval,
6816 assert(node->type == NodeTypeUnwrapErrorExpr);7554 ResultLoc *result_loc)
7555{
7556 assert(node->type == NodeTypeCatchExpr);
68177557
6818 AstNode *op1_node = node->data.unwrap_err_expr.op1;7558 AstNode *op1_node = node->data.unwrap_err_expr.op1;
6819 AstNode *op2_node = node->data.unwrap_err_expr.op2;7559 AstNode *op2_node = node->data.unwrap_err_expr.op2;
...@@ -6826,16 +7566,15 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -6826,16 +7566,15 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
6826 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));7566 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
6827 return irb->codegen->invalid_instruction;7567 return irb->codegen->invalid_instruction;
6828 }7568 }
6829 return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone);7569 return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, lval, result_loc);
6830 }7570 }
68317571
68327572
6833 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr);7573 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr);
6834 if (err_union_ptr == irb->codegen->invalid_instruction)7574 if (err_union_ptr == irb->codegen->invalid_instruction)
6835 return irb->codegen->invalid_instruction;7575 return irb->codegen->invalid_instruction;
68367576
6837 IrInstruction *err_union_val = ir_build_load_ptr(irb, parent_scope, node, err_union_ptr);7577 IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true);
6838 IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_val);
68397578
6840 IrInstruction *is_comptime;7579 IrInstruction *is_comptime;
6841 if (ir_should_inline(irb->exec, parent_scope)) {7580 if (ir_should_inline(irb->exec, parent_scope)) {
...@@ -6847,7 +7586,10 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -6847,7 +7586,10 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
6847 IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk");7586 IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk");
6848 IrBasicBlock *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError");7587 IrBasicBlock *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError");
6849 IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd");7588 IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd");
6850 ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime);7589 IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime);
7590
7591 ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc,
7592 is_comptime);
68517593
6852 ir_set_cursor_at_end_and_append_block(irb, err_block);7594 ir_set_cursor_at_end_and_append_block(irb, err_block);
6853 Scope *err_scope;7595 Scope *err_scope;
...@@ -6859,12 +7601,12 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -6859,12 +7601,12 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
6859 ZigVar *var = ir_create_var(irb, node, parent_scope, var_name,7601 ZigVar *var = ir_create_var(irb, node, parent_scope, var_name,
6860 is_const, is_const, is_shadowable, is_comptime);7602 is_const, is_const, is_shadowable, is_comptime);
6861 err_scope = var->child_scope;7603 err_scope = var->child_scope;
6862 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);7604 IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
6863 ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val);7605 ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, err_ptr);
6864 } else {7606 } else {
6865 err_scope = parent_scope;7607 err_scope = parent_scope;
6866 }7608 }
6867 IrInstruction *err_result = ir_gen_node(irb, op2_node, err_scope);7609 IrInstruction *err_result = ir_gen_node_extra(irb, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base);
6868 if (err_result == irb->codegen->invalid_instruction)7610 if (err_result == irb->codegen->invalid_instruction)
6869 return irb->codegen->invalid_instruction;7611 return irb->codegen->invalid_instruction;
6870 IrBasicBlock *after_err_block = irb->current_basic_block;7612 IrBasicBlock *after_err_block = irb->current_basic_block;
...@@ -6872,8 +7614,9 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -6872,8 +7614,9 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
6872 ir_mark_gen(ir_build_br(irb, err_scope, node, end_block, is_comptime));7614 ir_mark_gen(ir_build_br(irb, err_scope, node, end_block, is_comptime));
68737615
6874 ir_set_cursor_at_end_and_append_block(irb, ok_block);7616 ir_set_cursor_at_end_and_append_block(irb, ok_block);
6875 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false);7617 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false, false);
6876 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);7618 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
7619 ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base);
6877 IrBasicBlock *after_ok_block = irb->current_basic_block;7620 IrBasicBlock *after_ok_block = irb->current_basic_block;
6878 ir_build_br(irb, parent_scope, node, end_block, is_comptime);7621 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
68797622
...@@ -6884,7 +7627,8 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -6884,7 +7627,8 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
6884 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);7627 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
6885 incoming_blocks[0] = after_err_block;7628 incoming_blocks[0] = after_err_block;
6886 incoming_blocks[1] = after_ok_block;7629 incoming_blocks[1] = after_ok_block;
6887 return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);7630 IrInstruction *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent);
7631 return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc);
6888}7632}
68897633
6890static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *outer_scope, Scope *inner_scope) {7634static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *outer_scope, Scope *inner_scope) {
...@@ -7160,7 +7904,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode...@@ -7160,7 +7904,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
7160 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);7904 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
7161 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);7905 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
7162 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,7906 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
7163 atomic_state_field_name);7907 atomic_state_field_name, false);
71647908
7165 // set the is_canceled bit7909 // set the is_canceled bit
7166 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,7910 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
...@@ -7239,7 +7983,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode...@@ -7239,7 +7983,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
7239 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);7983 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
7240 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);7984 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
7241 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,7985 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
7242 atomic_state_field_name);7986 atomic_state_field_name, false);
72437987
7244 // clear the is_suspended bit7988 // clear the is_suspended bit
7245 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,7989 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
...@@ -7306,12 +8050,12 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7306,12 +8050,12 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
73068050
7307 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, target_inst);8051 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, target_inst);
7308 Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);8052 Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
7309 IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);8053 IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name, false);
73108054
7311 if (irb->codegen->have_err_ret_tracing) {8055 if (irb->codegen->have_err_ret_tracing) {
7312 IrInstruction *err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);8056 IrInstruction *err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);
7313 Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);8057 Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
7314 IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);8058 IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name, false);
7315 ir_build_store_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);8059 ir_build_store_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);
7316 }8060 }
73178061
...@@ -7333,11 +8077,11 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7333,11 +8077,11 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
73338077
7334 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);8078 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
7335 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,8079 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
7336 atomic_state_field_name);8080 atomic_state_field_name, false);
73378081
7338 IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_promise);8082 IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_promise);
7339 IrInstruction *const_bool_false = ir_build_const_bool(irb, scope, node, false);8083 IrInstruction *const_bool_false = ir_build_const_bool(irb, scope, node, false);
7340 IrInstruction *undefined_value = ir_build_const_undefined(irb, scope, node);8084 IrInstruction *undef = ir_build_const_undefined(irb, scope, node);
7341 IrInstruction *usize_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize);8085 IrInstruction *usize_type_val = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize);
7342 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);8086 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
7343 IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, scope, node, 0x7); // 0b1118087 IrInstruction *inverted_ptr_mask = ir_build_const_usize(irb, scope, node, 0x7); // 0b111
...@@ -7351,7 +8095,8 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7351,7 +8095,8 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
7351 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);8095 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
7352 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);8096 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
7353 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);8097 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
7354 ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);8098 IrInstruction *undef_promise_result = ir_build_implicit_cast(irb, scope, node, promise_result_type, undef, nullptr);
8099 build_decl_var_and_init(irb, scope, node, result_var, undef_promise_result, "result", const_bool_false);
7355 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);8100 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
7356 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);8101 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
7357 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);8102 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
...@@ -7386,12 +8131,12 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7386,12 +8131,12 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
7386 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);8131 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
7387 if (irb->codegen->have_err_ret_tracing) {8132 if (irb->codegen->have_err_ret_tracing) {
7388 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);8133 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
7389 IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);8134 IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name, false);
7390 IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);8135 IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::NonNull);
7391 ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);8136 ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
7392 }8137 }
7393 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);8138 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
7394 IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);8139 IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name, false);
7395 // If the type of the result handle_is_ptr then this does not actually perform a load. But we need it to,8140 // If the type of the result handle_is_ptr then this does not actually perform a load. But we need it to,
7396 // because we're about to destroy the memory. So we store it into our result variable.8141 // because we're about to destroy the memory. So we store it into our result variable.
7397 IrInstruction *no_suspend_result = ir_build_load_ptr(irb, scope, node, promise_result_ptr);8142 IrInstruction *no_suspend_result = ir_build_load_ptr(irb, scope, node, promise_result_ptr);
...@@ -7567,7 +8312,8 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod...@@ -7567,7 +8312,8 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
7567 incoming_values[0] = const_bool_true;8312 incoming_values[0] = const_bool_true;
7568 incoming_blocks[1] = post_cancel_awaiter_block;8313 incoming_blocks[1] = post_cancel_awaiter_block;
7569 incoming_values[1] = const_bool_false;8314 incoming_values[1] = const_bool_false;
7570 IrInstruction *destroy_ourselves = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);8315 IrInstruction *destroy_ourselves = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values,
8316 nullptr);
7571 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);8317 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
7572 ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, destroy_ourselves, irb->exec->coro_final_cleanup_block, irb->exec->coro_early_final, const_bool_false));8318 ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, destroy_ourselves, irb->exec->coro_final_cleanup_block, irb->exec->coro_early_final, const_bool_false));
75738319
...@@ -7576,7 +8322,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod...@@ -7576,7 +8322,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
7576}8322}
75778323
7578static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,8324static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
7579 LVal lval)8325 LVal lval, ResultLoc *result_loc)
7580{8326{
7581 assert(scope);8327 assert(scope);
7582 switch (node->type) {8328 switch (node->type) {
...@@ -7590,37 +8336,37 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7590,37 +8336,37 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7590 case NodeTypeTestDecl:8336 case NodeTypeTestDecl:
7591 zig_unreachable();8337 zig_unreachable();
7592 case NodeTypeBlock:8338 case NodeTypeBlock:
7593 return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval);8339 return ir_gen_block(irb, scope, node, lval, result_loc);
7594 case NodeTypeGroupedExpr:8340 case NodeTypeGroupedExpr:
7595 return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval);8341 return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc);
7596 case NodeTypeBinOpExpr:8342 case NodeTypeBinOpExpr:
7597 return ir_lval_wrap(irb, scope, ir_gen_bin_op(irb, scope, node), lval);8343 return ir_gen_bin_op(irb, scope, node, lval, result_loc);
7598 case NodeTypeIntLiteral:8344 case NodeTypeIntLiteral:
7599 return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval);8345 return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval, result_loc);
7600 case NodeTypeFloatLiteral:8346 case NodeTypeFloatLiteral:
7601 return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval);8347 return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval, result_loc);
7602 case NodeTypeCharLiteral:8348 case NodeTypeCharLiteral:
7603 return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval);8349 return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval, result_loc);
7604 case NodeTypeSymbol:8350 case NodeTypeSymbol:
7605 return ir_gen_symbol(irb, scope, node, lval);8351 return ir_gen_symbol(irb, scope, node, lval, result_loc);
7606 case NodeTypeFnCallExpr:8352 case NodeTypeFnCallExpr:
7607 return ir_gen_fn_call(irb, scope, node, lval);8353 return ir_gen_fn_call(irb, scope, node, lval, result_loc);
7608 case NodeTypeIfBoolExpr:8354 case NodeTypeIfBoolExpr:
7609 return ir_lval_wrap(irb, scope, ir_gen_if_bool_expr(irb, scope, node), lval);8355 return ir_gen_if_bool_expr(irb, scope, node, lval, result_loc);
7610 case NodeTypePrefixOpExpr:8356 case NodeTypePrefixOpExpr:
7611 return ir_gen_prefix_op_expr(irb, scope, node, lval);8357 return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc);
7612 case NodeTypeContainerInitExpr:8358 case NodeTypeContainerInitExpr:
7613 return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval);8359 return ir_gen_container_init_expr(irb, scope, node, lval, result_loc);
7614 case NodeTypeVariableDeclaration:8360 case NodeTypeVariableDeclaration:
7615 return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval);8361 return ir_gen_var_decl(irb, scope, node);
7616 case NodeTypeWhileExpr:8362 case NodeTypeWhileExpr:
7617 return ir_lval_wrap(irb, scope, ir_gen_while_expr(irb, scope, node), lval);8363 return ir_gen_while_expr(irb, scope, node, lval, result_loc);
7618 case NodeTypeForExpr:8364 case NodeTypeForExpr:
7619 return ir_lval_wrap(irb, scope, ir_gen_for_expr(irb, scope, node), lval);8365 return ir_gen_for_expr(irb, scope, node, lval, result_loc);
7620 case NodeTypeArrayAccessExpr:8366 case NodeTypeArrayAccessExpr:
7621 return ir_gen_array_access(irb, scope, node, lval);8367 return ir_gen_array_access(irb, scope, node, lval, result_loc);
7622 case NodeTypeReturnExpr:8368 case NodeTypeReturnExpr:
7623 return ir_gen_return(irb, scope, node, lval);8369 return ir_gen_return(irb, scope, node, lval, result_loc);
7624 case NodeTypeFieldAccessExpr:8370 case NodeTypeFieldAccessExpr:
7625 {8371 {
7626 IrInstruction *ptr_instruction = ir_gen_field_access(irb, scope, node);8372 IrInstruction *ptr_instruction = ir_gen_field_access(irb, scope, node);
...@@ -7629,86 +8375,89 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7629,86 +8375,89 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7629 if (lval == LValPtr)8375 if (lval == LValPtr)
7630 return ptr_instruction;8376 return ptr_instruction;
76318377
7632 return ir_build_load_ptr(irb, scope, node, ptr_instruction);8378 IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
8379 return ir_expr_wrap(irb, scope, load_ptr, result_loc);
7633 }8380 }
7634 case NodeTypePtrDeref: {8381 case NodeTypePtrDeref: {
7635 AstNode *expr_node = node->data.ptr_deref_expr.target;8382 AstNode *expr_node = node->data.ptr_deref_expr.target;
7636 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);8383 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr);
7637 if (value == irb->codegen->invalid_instruction)8384 if (value == irb->codegen->invalid_instruction)
7638 return value;8385 return value;
76398386
7640 // We essentially just converted any lvalue from &(x.*) to (&x).*;8387 // We essentially just converted any lvalue from &(x.*) to (&x).*;
7641 // this inhibits checking that x is a pointer later, so we directly8388 // this inhibits checking that x is a pointer later, so we directly
7642 // record whether the pointer check is needed8389 // record whether the pointer check is needed
7643 return ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval);8390 IrInstruction *un_op = ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval, result_loc);
8391 return ir_expr_wrap(irb, scope, un_op, result_loc);
7644 }8392 }
7645 case NodeTypeUnwrapOptional: {8393 case NodeTypeUnwrapOptional: {
7646 AstNode *expr_node = node->data.unwrap_optional.expr;8394 AstNode *expr_node = node->data.unwrap_optional.expr;
76478395
7648 IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);8396 IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
7649 if (maybe_ptr == irb->codegen->invalid_instruction)8397 if (maybe_ptr == irb->codegen->invalid_instruction)
7650 return irb->codegen->invalid_instruction;8398 return irb->codegen->invalid_instruction;
76518399
7652 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true);8400 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true, false);
7653 if (lval == LValPtr)8401 if (lval == LValPtr)
7654 return unwrapped_ptr;8402 return unwrapped_ptr;
76558403
7656 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);8404 IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
8405 return ir_expr_wrap(irb, scope, load_ptr, result_loc);
7657 }8406 }
7658 case NodeTypeBoolLiteral:8407 case NodeTypeBoolLiteral:
7659 return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);8408 return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval, result_loc);
7660 case NodeTypeArrayType:8409 case NodeTypeArrayType:
7661 return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval);8410 return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval, result_loc);
7662 case NodeTypePointerType:8411 case NodeTypePointerType:
7663 return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval);8412 return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval, result_loc);
7664 case NodeTypePromiseType:8413 case NodeTypePromiseType:
7665 return ir_lval_wrap(irb, scope, ir_gen_promise_type(irb, scope, node), lval);8414 return ir_lval_wrap(irb, scope, ir_gen_promise_type(irb, scope, node), lval, result_loc);
7666 case NodeTypeStringLiteral:8415 case NodeTypeStringLiteral:
7667 return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval);8416 return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval, result_loc);
7668 case NodeTypeUndefinedLiteral:8417 case NodeTypeUndefinedLiteral:
7669 return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval);8418 return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval, result_loc);
7670 case NodeTypeAsmExpr:8419 case NodeTypeAsmExpr:
7671 return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval);8420 return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval, result_loc);
7672 case NodeTypeNullLiteral:8421 case NodeTypeNullLiteral:
7673 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);8422 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval, result_loc);
7674 case NodeTypeIfErrorExpr:8423 case NodeTypeIfErrorExpr:
7675 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);8424 return ir_gen_if_err_expr(irb, scope, node, lval, result_loc);
7676 case NodeTypeIfOptional:8425 case NodeTypeIfOptional:
7677 return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);8426 return ir_gen_if_optional_expr(irb, scope, node, lval, result_loc);
7678 case NodeTypeSwitchExpr:8427 case NodeTypeSwitchExpr:
7679 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);8428 return ir_gen_switch_expr(irb, scope, node, lval, result_loc);
7680 case NodeTypeCompTime:8429 case NodeTypeCompTime:
7681 return ir_gen_comptime(irb, scope, node, lval);8430 return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc);
7682 case NodeTypeErrorType:8431 case NodeTypeErrorType:
7683 return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval);8432 return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc);
7684 case NodeTypeBreak:8433 case NodeTypeBreak:
7685 return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval);8434 return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval, result_loc);
7686 case NodeTypeContinue:8435 case NodeTypeContinue:
7687 return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval);8436 return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval, result_loc);
7688 case NodeTypeUnreachable:8437 case NodeTypeUnreachable:
7689 return ir_lval_wrap(irb, scope, ir_build_unreachable(irb, scope, node), lval);8438 return ir_build_unreachable(irb, scope, node);
7690 case NodeTypeDefer:8439 case NodeTypeDefer:
7691 return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval);8440 return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval, result_loc);
7692 case NodeTypeSliceExpr:8441 case NodeTypeSliceExpr:
7693 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);8442 return ir_gen_slice(irb, scope, node, lval, result_loc);
7694 case NodeTypeUnwrapErrorExpr:8443 case NodeTypeCatchExpr:
7695 return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval);8444 return ir_gen_catch(irb, scope, node, lval, result_loc);
7696 case NodeTypeContainerDecl:8445 case NodeTypeContainerDecl:
7697 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);8446 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval, result_loc);
7698 case NodeTypeFnProto:8447 case NodeTypeFnProto:
7699 return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval);8448 return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc);
7700 case NodeTypeErrorSetDecl:8449 case NodeTypeErrorSetDecl:
7701 return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval);8450 return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval, result_loc);
7702 case NodeTypeCancel:8451 case NodeTypeCancel:
7703 return ir_lval_wrap(irb, scope, ir_gen_cancel(irb, scope, node), lval);8452 return ir_lval_wrap(irb, scope, ir_gen_cancel(irb, scope, node), lval, result_loc);
7704 case NodeTypeResume:8453 case NodeTypeResume:
7705 return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval);8454 return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc);
7706 case NodeTypeAwaitExpr:8455 case NodeTypeAwaitExpr:
7707 return ir_lval_wrap(irb, scope, ir_gen_await_expr(irb, scope, node), lval);8456 return ir_lval_wrap(irb, scope, ir_gen_await_expr(irb, scope, node), lval, result_loc);
7708 case NodeTypeSuspend:8457 case NodeTypeSuspend:
7709 return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval);8458 return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval, result_loc);
7710 case NodeTypeEnumLiteral:8459 case NodeTypeEnumLiteral:
7711 return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval);8460 return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval, result_loc);
7712 case NodeTypeInferredArrayType:8461 case NodeTypeInferredArrayType:
7713 add_node_error(irb->codegen, node,8462 add_node_error(irb->codegen, node,
7714 buf_sprintf("inferred array size invalid here"));8463 buf_sprintf("inferred array size invalid here"));
...@@ -7717,14 +8466,28 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7717,14 +8466,28 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7717 zig_unreachable();8466 zig_unreachable();
7718}8467}
77198468
7720static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval) {8469static ResultLoc *no_result_loc(void) {
7721 IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval);8470 ResultLocNone *result_loc_none = allocate<ResultLocNone>(1);
8471 result_loc_none->base.id = ResultLocIdNone;
8472 return &result_loc_none->base;
8473}
8474
8475static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
8476 ResultLoc *result_loc)
8477{
8478 if (result_loc == nullptr) {
8479 // Create a result location indicating there is none - but if one gets created
8480 // it will be properly distributed.
8481 result_loc = no_result_loc();
8482 ir_build_reset_result(irb, scope, node, result_loc);
8483 }
8484 IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval, result_loc);
7722 irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction);8485 irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction);
7723 return result;8486 return result;
7724}8487}
77258488
7726static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) {8489static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) {
7727 return ir_gen_node_extra(irb, node, scope, LValNone);8490 return ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
7728}8491}
77298492
7730static void invalidate_exec(IrExecutable *exec) {8493static void invalidate_exec(IrExecutable *exec) {
...@@ -7775,17 +8538,19 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7775,17 +8538,19 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
77758538
7776 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;8539 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
7777 IrInstruction *undef = ir_build_const_undefined(irb, coro_scope, node);8540 IrInstruction *undef = ir_build_const_undefined(irb, coro_scope, node);
8541 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
7778 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);8542 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
7779 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);8543 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
7780 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa8544 IrInstruction *undef_coro_frame = ir_build_implicit_cast(irb, coro_scope, node, coro_frame_type_value, undef, nullptr);
7781 ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);8545 build_decl_var_and_init(irb, coro_scope, node, promise_var, undef_coro_frame, "promise", const_bool_false);
7782 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);8546 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
77838547
7784 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);8548 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7785 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);8549 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
7786 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,8550 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
7787 get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));8551 get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
7788 ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);8552 IrInstruction *null_await_handle = ir_build_implicit_cast(irb, coro_scope, node, await_handle_type_val, null_value, nullptr);
8553 build_decl_var_and_init(irb, coro_scope, node, await_handle_var, null_await_handle, "await_handle", const_bool_false);
7789 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);8554 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
77908555
7791 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,8556 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
...@@ -7795,13 +8560,14 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7795,13 +8560,14 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7795 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);8560 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
7796 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);8561 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7797 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);8562 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
7798 ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);8563 build_decl_var_and_init(irb, coro_scope, node, coro_size_var, coro_size, "coro_size", const_bool_false);
7799 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,8564 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
7800 ImplicitAllocatorIdArg);8565 ImplicitAllocatorIdArg);
7801 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);8566 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
7802 ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);8567 build_decl_var_and_init(irb, coro_scope, node, irb->exec->coro_allocator_var, implicit_allocator_ptr,
8568 "allocator", const_bool_false);
7803 Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);8569 Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);
7804 IrInstruction *realloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, realloc_field_name);8570 IrInstruction *realloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, realloc_field_name, false);
7805 IrInstruction *realloc_fn = ir_build_load_ptr(irb, coro_scope, node, realloc_fn_ptr);8571 IrInstruction *realloc_fn = ir_build_load_ptr(irb, coro_scope, node, realloc_fn_ptr);
7806 IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, coro_scope, node, realloc_fn, coro_size);8572 IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, coro_scope, node, realloc_fn, coro_size);
7807 IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, coro_scope, node, maybe_coro_mem_ptr);8573 IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, coro_scope, node, maybe_coro_mem_ptr);
...@@ -7821,32 +8587,32 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7821,32 +8587,32 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
78218587
7822 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);8588 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
7823 irb->exec->atomic_state_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,8589 irb->exec->atomic_state_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
7824 atomic_state_field_name);8590 atomic_state_field_name, false);
7825 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);8591 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
7826 ir_build_store_ptr(irb, scope, node, irb->exec->atomic_state_field_ptr, zero);8592 ir_build_store_ptr(irb, scope, node, irb->exec->atomic_state_field_ptr, zero);
7827 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);8593 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
7828 irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);8594 irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name, false);
7829 result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);8595 result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
7830 irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);8596 irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name, false);
7831 ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);8597 ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);
7832 if (irb->codegen->have_err_ret_tracing) {8598 if (irb->codegen->have_err_ret_tracing) {
7833 // initialize the error return trace8599 // initialize the error return trace
7834 Buf *return_addresses_field_name = buf_create_from_str(RETURN_ADDRESSES_FIELD_NAME);8600 Buf *return_addresses_field_name = buf_create_from_str(RETURN_ADDRESSES_FIELD_NAME);
7835 IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name);8601 IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name, false);
78368602
7837 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);8603 Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
7838 err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);8604 err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name, false);
7839 ir_build_mark_err_ret_trace_ptr(irb, scope, node, err_ret_trace_ptr);8605 ir_build_mark_err_ret_trace_ptr(irb, scope, node, err_ret_trace_ptr);
78408606
7841 // coordinate with builtin.zig8607 // coordinate with builtin.zig
7842 Buf *index_name = buf_create_from_str("index");8608 Buf *index_name = buf_create_from_str("index");
7843 IrInstruction *index_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, index_name);8609 IrInstruction *index_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, index_name, false);
7844 ir_build_store_ptr(irb, scope, node, index_ptr, zero);8610 ir_build_store_ptr(irb, scope, node, index_ptr, zero);
78458611
7846 Buf *instruction_addresses_name = buf_create_from_str("instruction_addresses");8612 Buf *instruction_addresses_name = buf_create_from_str("instruction_addresses");
7847 IrInstruction *addrs_slice_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, instruction_addresses_name);8613 IrInstruction *addrs_slice_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, instruction_addresses_name, false);
78488614
7849 IrInstruction *slice_value = ir_build_slice(irb, scope, node, return_addresses_ptr, zero, nullptr, false);8615 IrInstruction *slice_value = ir_build_slice_src(irb, scope, node, return_addresses_ptr, zero, nullptr, false, no_result_loc());
7850 ir_build_store_ptr(irb, scope, node, addrs_slice_ptr, slice_value);8616 ir_build_store_ptr(irb, scope, node, addrs_slice_ptr, slice_value);
7851 }8617 }
78528618
...@@ -7857,7 +8623,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7857,7 +8623,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7857 irb->exec->coro_final_cleanup_block = ir_create_basic_block(irb, scope, "FinalCleanup");8623 irb->exec->coro_final_cleanup_block = ir_create_basic_block(irb, scope, "FinalCleanup");
7858 }8624 }
78598625
7860 IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone);8626 IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
7861 assert(result);8627 assert(result);
7862 if (irb->exec->invalid)8628 if (irb->exec->invalid)
7863 return false;8629 return false;
...@@ -7905,7 +8671,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7905,7 +8671,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7905 }8671 }
7906 if (irb->codegen->have_err_ret_tracing) {8672 if (irb->codegen->have_err_ret_tracing) {
7907 Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);8673 Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
7908 IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);8674 IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name, false);
7909 IrInstruction *dest_err_ret_trace_ptr = ir_build_load_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr);8675 IrInstruction *dest_err_ret_trace_ptr = ir_build_load_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr);
7910 ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr, dest_err_ret_trace_ptr);8676 ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr, dest_err_ret_trace_ptr);
7911 }8677 }
...@@ -7913,7 +8679,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7913,7 +8679,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7913 // a register or local variable which does not get spilled into the frame,8679 // a register or local variable which does not get spilled into the frame,
7914 // otherwise llvm tries to access memory inside the destroyed frame.8680 // otherwise llvm tries to access memory inside the destroyed frame.
7915 IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node,8681 IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node,
7916 irb->exec->await_handle_var_ptr, false);8682 irb->exec->await_handle_var_ptr, false, false);
7917 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);8683 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
7918 ir_build_br(irb, scope, node, check_free_block, const_bool_false);8684 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
79198685
...@@ -7927,7 +8693,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7927,7 +8693,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7927 incoming_values[0] = const_bool_false;8693 incoming_values[0] = const_bool_false;
7928 incoming_blocks[1] = irb->exec->coro_normal_final;8694 incoming_blocks[1] = irb->exec->coro_normal_final;
7929 incoming_values[1] = const_bool_true;8695 incoming_values[1] = const_bool_true;
7930 IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);8696 IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
79318697
7932 IrBasicBlock **merge_incoming_blocks = allocate<IrBasicBlock *>(2);8698 IrBasicBlock **merge_incoming_blocks = allocate<IrBasicBlock *>(2);
7933 IrInstruction **merge_incoming_values = allocate<IrInstruction *>(2);8699 IrInstruction **merge_incoming_values = allocate<IrInstruction *>(2);
...@@ -7935,12 +8701,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7935,12 +8701,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7935 merge_incoming_values[0] = ir_build_const_undefined(irb, scope, node);8701 merge_incoming_values[0] = ir_build_const_undefined(irb, scope, node);
7936 merge_incoming_blocks[1] = irb->exec->coro_normal_final;8702 merge_incoming_blocks[1] = irb->exec->coro_normal_final;
7937 merge_incoming_values[1] = await_handle_in_block;8703 merge_incoming_values[1] = await_handle_in_block;
7938 IrInstruction *awaiter_handle = ir_build_phi(irb, scope, node, 2, merge_incoming_blocks, merge_incoming_values);8704 IrInstruction *awaiter_handle = ir_build_phi(irb, scope, node, 2, merge_incoming_blocks, merge_incoming_values, nullptr);
79398705
7940 Buf *shrink_field_name = buf_create_from_str(ASYNC_SHRINK_FIELD_NAME);8706 Buf *shrink_field_name = buf_create_from_str(ASYNC_SHRINK_FIELD_NAME);
7941 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,8707 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
7942 ImplicitAllocatorIdLocalVar);8708 ImplicitAllocatorIdLocalVar);
7943 IrInstruction *shrink_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, shrink_field_name);8709 IrInstruction *shrink_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, shrink_field_name, false);
7944 IrInstruction *shrink_fn = ir_build_load_ptr(irb, scope, node, shrink_fn_ptr);8710 IrInstruction *shrink_fn = ir_build_load_ptr(irb, scope, node, shrink_fn_ptr);
7945 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);8711 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
7946 IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);8712 IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
...@@ -7952,7 +8718,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7952,7 +8718,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7952 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);8718 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
7953 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);8719 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
7954 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);8720 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
7955 IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false);8721 IrInstruction *mem_slice = ir_build_slice_src(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false,
8722 no_result_loc());
7956 size_t arg_count = 5;8723 size_t arg_count = 5;
7957 IrInstruction **args = allocate<IrInstruction *>(arg_count);8724 IrInstruction **args = allocate<IrInstruction *>(arg_count);
7958 args[0] = implicit_allocator_ptr; // self8725 args[0] = implicit_allocator_ptr; // self
...@@ -7966,7 +8733,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7966,7 +8733,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7966 // non-allocating. Basically coroutines are not supported right now until they are reworked.8733 // non-allocating. Basically coroutines are not supported right now until they are reworked.
7967 args[3] = ir_build_const_usize(irb, scope, node, 1); // new_size8734 args[3] = ir_build_const_usize(irb, scope, node, 1); // new_size
7968 args[4] = ir_build_const_usize(irb, scope, node, 1); // new_align8735 args[4] = ir_build_const_usize(irb, scope, node, 1); // new_align
7969 ir_build_call(irb, scope, node, nullptr, shrink_fn, arg_count, args, false, FnInlineAuto, false, nullptr, nullptr);8736 ir_build_call_src(irb, scope, node, nullptr, shrink_fn, arg_count, args, false, FnInlineAuto, false, nullptr,
8737 nullptr, no_result_loc());
79708738
7971 IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");8739 IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");
7972 ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);8740 ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);
...@@ -8073,6 +8841,15 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec...@@ -8073,6 +8841,15 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
8073 }8841 }
8074 return &value->value;8842 return &value->value;
8075 } else if (ir_has_side_effects(instruction)) {8843 } else if (ir_has_side_effects(instruction)) {
8844 if (instr_is_comptime(instruction)) {
8845 switch (instruction->id) {
8846 case IrInstructionIdUnwrapErrPayload:
8847 case IrInstructionIdUnionFieldPtr:
8848 continue;
8849 default:
8850 break;
8851 }
8852 }
8076 exec_add_error_node(codegen, exec, instruction->source_node,8853 exec_add_error_node(codegen, exec, instruction->source_node,
8077 buf_sprintf("unable to evaluate constant expression"));8854 buf_sprintf("unable to evaluate constant expression"));
8078 return &codegen->invalid_instruction->value;8855 return &codegen->invalid_instruction->value;
...@@ -9050,15 +9827,6 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -9050,15 +9827,6 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
9050 return false;9827 return false;
9051}9828}
90529829
9053static bool is_slice(ZigType *type) {
9054 return type->id == ZigTypeIdStruct && type->data.structure.is_slice;
9055}
9056
9057static bool slice_is_const(ZigType *type) {
9058 assert(is_slice(type));
9059 return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
9060}
9061
9062static bool is_tagged_union(ZigType *type) {9830static bool is_tagged_union(ZigType *type) {
9063 if (type->id != ZigTypeIdUnion)9831 if (type->id != ZigTypeIdUnion)
9064 return false;9832 return false;
...@@ -9429,9 +10197,21 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9429,9 +10197,21 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
9429{10197{
9430 Error err;10198 Error err;
9431 assert(instruction_count >= 1);10199 assert(instruction_count >= 1);
9432 IrInstruction *prev_inst = instructions[0];10200 IrInstruction *prev_inst;
9433 if (type_is_invalid(prev_inst->value.type)) {10201 size_t i = 0;
9434 return ira->codegen->builtin_types.entry_invalid;10202 for (;;) {
10203 prev_inst = instructions[i];
10204 if (type_is_invalid(prev_inst->value.type)) {
10205 return ira->codegen->builtin_types.entry_invalid;
10206 }
10207 if (prev_inst->value.type->id == ZigTypeIdUnreachable) {
10208 i += 1;
10209 if (i == instruction_count) {
10210 return prev_inst->value.type;
10211 }
10212 continue;
10213 }
10214 break;
9435 }10215 }
9436 ErrorTableEntry **errors = nullptr;10216 ErrorTableEntry **errors = nullptr;
9437 size_t errors_count = 0;10217 size_t errors_count = 0;
...@@ -9456,7 +10236,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9456,7 +10236,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
945610236
9457 bool any_are_null = (prev_inst->value.type->id == ZigTypeIdNull);10237 bool any_are_null = (prev_inst->value.type->id == ZigTypeIdNull);
9458 bool convert_to_const_slice = false;10238 bool convert_to_const_slice = false;
9459 for (size_t i = 1; i < instruction_count; i += 1) {10239 for (; i < instruction_count; i += 1) {
9460 IrInstruction *cur_inst = instructions[i];10240 IrInstruction *cur_inst = instructions[i];
9461 ZigType *cur_type = cur_inst->value.type;10241 ZigType *cur_type = cur_inst->value.type;
9462 ZigType *prev_type = prev_inst->value.type;10242 ZigType *prev_type = prev_inst->value.type;
...@@ -9475,7 +10255,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9475,7 +10255,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
9475 }10255 }
947610256
9477 if (prev_type->id == ZigTypeIdErrorSet) {10257 if (prev_type->id == ZigTypeIdErrorSet) {
9478 assert(err_set_type != nullptr);10258 ir_assert(err_set_type != nullptr, prev_inst);
9479 if (cur_type->id == ZigTypeIdErrorSet) {10259 if (cur_type->id == ZigTypeIdErrorSet) {
9480 if (type_is_global_error_set(err_set_type)) {10260 if (type_is_global_error_set(err_set_type)) {
9481 continue;10261 continue;
...@@ -9735,6 +10515,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9735,6 +10515,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
973510515
9736 if (prev_type->id == ZigTypeIdNull) {10516 if (prev_type->id == ZigTypeIdNull) {
9737 prev_inst = cur_inst;10517 prev_inst = cur_inst;
10518 any_are_null = true;
9738 continue;10519 continue;
9739 }10520 }
974010521
...@@ -10049,6 +10830,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10049,6 +10830,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10049 } else if (prev_inst->value.type->id == ZigTypeIdOptional) {10830 } else if (prev_inst->value.type->id == ZigTypeIdOptional) {
10050 return prev_inst->value.type;10831 return prev_inst->value.type;
10051 } else {10832 } else {
10833 if ((err = type_resolve(ira->codegen, prev_inst->value.type, ResolveStatusSizeKnown)))
10834 return ira->codegen->builtin_types.entry_invalid;
10052 return get_optional_type(ira->codegen, prev_inst->value.type);10835 return get_optional_type(ira->codegen, prev_inst->value.type);
10053 }10836 }
10054 } else {10837 } else {
...@@ -10056,24 +10839,18 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10056,24 +10839,18 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10056 }10839 }
10057}10840}
1005810841
10059static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry) {
10060 if (type_has_bits(type_entry) && handle_is_ptr(type_entry)) {
10061 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
10062 if (fn_entry != nullptr) {
10063 fn_entry->alloca_list.append(instruction);
10064 }
10065 }
10066}
10067
10068static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {10842static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {
10069 ConstGlobalRefs *global_refs = dest->global_refs;10843 ConstGlobalRefs *global_refs = dest->global_refs;
10070 assert(!same_global_refs || src->global_refs != nullptr);10844 memcpy(dest, src, sizeof(ConstExprValue));
10071 *dest = *src;
10072 if (!same_global_refs) {10845 if (!same_global_refs) {
10073 dest->global_refs = global_refs;10846 dest->global_refs = global_refs;
10847 if (src->special == ConstValSpecialUndef)
10848 return;
10074 if (dest->type->id == ZigTypeIdStruct) {10849 if (dest->type->id == ZigTypeIdStruct) {
10075 dest->data.x_struct.fields = allocate_nonzero<ConstExprValue>(dest->type->data.structure.src_field_count);10850 dest->data.x_struct.fields = create_const_vals(dest->type->data.structure.src_field_count);
10076 memcpy(dest->data.x_struct.fields, src->data.x_struct.fields, sizeof(ConstExprValue) * dest->type->data.structure.src_field_count);10851 for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
10852 copy_const_val(&dest->data.x_struct.fields[i], &src->data.x_struct.fields[i], false);
10853 }
10077 }10854 }
10078 }10855 }
10079}10856}
...@@ -10091,7 +10868,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -10091,7 +10868,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
10091 zig_unreachable();10868 zig_unreachable();
10092 case CastOpErrSet:10869 case CastOpErrSet:
10093 case CastOpBitCast:10870 case CastOpBitCast:
10094 case CastOpPtrOfArrayToSlice:
10095 zig_panic("TODO");10871 zig_panic("TODO");
10096 case CastOpNoop:10872 case CastOpNoop:
10097 {10873 {
...@@ -10191,7 +10967,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z...@@ -10191,7 +10967,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z
10191}10967}
1019210968
10193static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,10969static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
10194 ZigType *wanted_type, CastOp cast_op, bool need_alloca)10970 ZigType *wanted_type, CastOp cast_op)
10195{10971{
10196 if (instr_is_comptime(value) || !type_has_bits(wanted_type)) {10972 if (instr_is_comptime(value) || !type_has_bits(wanted_type)) {
10197 IrInstruction *result = ir_const(ira, source_instr, wanted_type);10973 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
...@@ -10204,9 +10980,6 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10204,9 +10980,6 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
10204 } else {10980 } else {
10205 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, cast_op);10981 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, cast_op);
10206 result->value.type = wanted_type;10982 result->value.type = wanted_type;
10207 if (need_alloca) {
10208 ir_add_alloca(ira, result, wanted_type);
10209 }
10210 return result;10983 return result;
10211 }10984 }
10212}10985}
...@@ -10248,7 +11021,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,...@@ -10248,7 +11021,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
10248}11021}
1024911022
10250static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,11023static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
10251 IrInstruction *value, ZigType *wanted_type)11024 IrInstruction *value, ZigType *wanted_type, ResultLoc *result_loc)
10252{11025{
10253 Error err;11026 Error err;
1025411027
...@@ -10279,11 +11052,12 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc...@@ -10279,11 +11052,12 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
10279 }11052 }
10280 }11053 }
1028111054
10282 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node,11055 if (result_loc == nullptr) result_loc = no_result_loc();
10283 wanted_type, value, CastOpPtrOfArrayToSlice);11056 IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
10284 result->value.type = wanted_type;11057 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
10285 ir_add_alloca(ira, result, wanted_type);11058 return result_loc_inst;
10286 return result;11059 }
11060 return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, value, result_loc_inst);
10287}11061}
1028811062
10289static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {11063static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
...@@ -10315,51 +11089,136 @@ static IrBasicBlock *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlock *old_bb,...@@ -10315,51 +11089,136 @@ static IrBasicBlock *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlock *old_bb,
10315}11089}
1031611090
10317static void ir_start_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrBasicBlock *const_predecessor_bb) {11091static void ir_start_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrBasicBlock *const_predecessor_bb) {
11092 assert(!old_bb->suspended);
10318 ira->instruction_index = 0;11093 ira->instruction_index = 0;
10319 ira->old_irb.current_basic_block = old_bb;11094 ira->old_irb.current_basic_block = old_bb;
10320 ira->const_predecessor_bb = const_predecessor_bb;11095 ira->const_predecessor_bb = const_predecessor_bb;
11096 ira->old_bb_index = old_bb->index;
10321}11097}
1032211098
10323static void ir_finish_bb(IrAnalyze *ira) {11099static IrInstruction *ira_suspend(IrAnalyze *ira, IrInstruction *old_instruction, IrBasicBlock *next_bb,
10324 ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);11100 IrSuspendPosition *suspend_pos)
10325 ira->instruction_index += 1;11101{
10326 while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {11102 if (ira->codegen->verbose_ir) {
10327 IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);11103 fprintf(stderr, "suspend %s_%zu %s_%zu #%zu (%zu,%zu)\n", ira->old_irb.current_basic_block->name_hint,
10328 if (!next_instruction->is_gen) {11104 ira->old_irb.current_basic_block->debug_id,
10329 ir_add_error(ira, next_instruction, buf_sprintf("unreachable code"));11105 ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->name_hint,
10330 break;11106 ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->debug_id,
10331 }11107 ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index)->debug_id,
10332 ira->instruction_index += 1;11108 ira->old_bb_index, ira->instruction_index);
11109 }
11110 suspend_pos->basic_block_index = ira->old_bb_index;
11111 suspend_pos->instruction_index = ira->instruction_index;
11112
11113 ira->old_irb.current_basic_block->suspended = true;
11114
11115 // null next_bb means that the caller plans to call ira_resume before returning
11116 if (next_bb != nullptr) {
11117 ira->old_bb_index = next_bb->index;
11118 ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);
11119 assert(ira->old_irb.current_basic_block == next_bb);
11120 ira->instruction_index = 0;
11121 ira->const_predecessor_bb = nullptr;
11122 next_bb->other = ir_get_new_bb_runtime(ira, next_bb, old_instruction);
11123 ira->new_irb.current_basic_block = next_bb->other;
10333 }11124 }
11125 return ira->codegen->unreach_instruction;
11126}
11127
11128static IrInstruction *ira_resume(IrAnalyze *ira) {
11129 IrSuspendPosition pos = ira->resume_stack.pop();
11130 if (ira->codegen->verbose_ir) {
11131 fprintf(stderr, "resume (%zu,%zu) ", pos.basic_block_index, pos.instruction_index);
11132 }
11133 ira->old_bb_index = pos.basic_block_index;
11134 ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);
11135 assert(ira->old_irb.current_basic_block->in_resume_stack);
11136 ira->old_irb.current_basic_block->in_resume_stack = false;
11137 ira->old_irb.current_basic_block->suspended = false;
11138 ira->instruction_index = pos.instruction_index;
11139 assert(pos.instruction_index < ira->old_irb.current_basic_block->instruction_list.length);
11140 if (ira->codegen->verbose_ir) {
11141 fprintf(stderr, "%s_%zu #%zu\n", ira->old_irb.current_basic_block->name_hint,
11142 ira->old_irb.current_basic_block->debug_id,
11143 ira->old_irb.current_basic_block->instruction_list.at(pos.instruction_index)->debug_id);
11144 }
11145 ira->const_predecessor_bb = nullptr;
11146 ira->new_irb.current_basic_block = ira->old_irb.current_basic_block->other;
11147 assert(ira->new_irb.current_basic_block != nullptr);
11148 return ira->codegen->unreach_instruction;
11149}
1033411150
10335 size_t my_old_bb_index = ira->old_bb_index;11151static void ir_start_next_bb(IrAnalyze *ira) {
10336 ira->old_bb_index += 1;11152 ira->old_bb_index += 1;
1033711153
10338 bool need_repeat = true;11154 bool need_repeat = true;
10339 for (;;) {11155 for (;;) {
10340 while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) {11156 while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) {
10341 IrBasicBlock *old_bb = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);11157 IrBasicBlock *old_bb = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);
10342 if (old_bb->other == nullptr) {11158 if (old_bb->other == nullptr && old_bb->suspend_instruction_ref == nullptr) {
10343 ira->old_bb_index += 1;11159 ira->old_bb_index += 1;
10344 continue;11160 continue;
10345 }11161 }
10346 if (old_bb->other->instruction_list.length != 0 || ira->old_bb_index == my_old_bb_index) {11162 // if it's already started, or
11163 // if it's a suspended block,
11164 // then skip it
11165 if (old_bb->suspended ||
11166 (old_bb->other != nullptr && old_bb->other->instruction_list.length != 0) ||
11167 (old_bb->other != nullptr && old_bb->other->already_appended))
11168 {
10347 ira->old_bb_index += 1;11169 ira->old_bb_index += 1;
10348 continue;11170 continue;
10349 }11171 }
10350 ira->new_irb.current_basic_block = old_bb->other;
1035111172
11173 // if there is a resume_stack, pop one from there rather than moving on.
11174 // the last item of the resume stack will be a basic block that will
11175 // move on to the next one below
11176 if (ira->resume_stack.length != 0) {
11177 ira_resume(ira);
11178 return;
11179 }
11180
11181 if (old_bb->other == nullptr) {
11182 old_bb->other = ir_get_new_bb_runtime(ira, old_bb, old_bb->suspend_instruction_ref);
11183 }
11184 ira->new_irb.current_basic_block = old_bb->other;
10352 ir_start_bb(ira, old_bb, nullptr);11185 ir_start_bb(ira, old_bb, nullptr);
10353 return;11186 return;
10354 }11187 }
10355 if (!need_repeat)11188 if (!need_repeat) {
11189 if (ira->resume_stack.length != 0) {
11190 ira_resume(ira);
11191 }
10356 return;11192 return;
11193 }
10357 need_repeat = false;11194 need_repeat = false;
10358 ira->old_bb_index = 0;11195 ira->old_bb_index = 0;
10359 continue;11196 continue;
10360 }11197 }
10361}11198}
1036211199
11200static void ir_finish_bb(IrAnalyze *ira) {
11201 if (!ira->new_irb.current_basic_block->already_appended) {
11202 ira->new_irb.current_basic_block->already_appended = true;
11203 if (ira->codegen->verbose_ir) {
11204 fprintf(stderr, "append new bb %s_%zu\n", ira->new_irb.current_basic_block->name_hint,
11205 ira->new_irb.current_basic_block->debug_id);
11206 }
11207 ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
11208 }
11209 ira->instruction_index += 1;
11210 while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {
11211 IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
11212 if (!next_instruction->is_gen) {
11213 ir_add_error(ira, next_instruction, buf_sprintf("unreachable code"));
11214 break;
11215 }
11216 ira->instruction_index += 1;
11217 }
11218
11219 ir_start_next_bb(ira);
11220}
11221
10363static IrInstruction *ir_unreach_error(IrAnalyze *ira) {11222static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
10364 ira->old_bb_index = SIZE_MAX;11223 ira->old_bb_index = SIZE_MAX;
10365 ira->new_irb.exec->invalid = true;11224 ira->new_irb.exec->invalid = true;
...@@ -10420,6 +11279,12 @@ static IrInstruction *ir_const_undef(IrAnalyze *ira, IrInstruction *source_instr...@@ -10420,6 +11279,12 @@ static IrInstruction *ir_const_undef(IrAnalyze *ira, IrInstruction *source_instr
10420 return result;11279 return result;
10421}11280}
1042211281
11282static IrInstruction *ir_const_unreachable(IrAnalyze *ira, IrInstruction *source_instruction) {
11283 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_unreachable);
11284 result->value.special = ConstValSpecialStatic;
11285 return result;
11286}
11287
10423static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) {11288static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) {
10424 return ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_void);11289 return ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_void);
10425}11290}
...@@ -10617,7 +11482,7 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {...@@ -10617,7 +11482,7 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
10617}11482}
1061811483
10619static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,11484static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
10620 ZigType *wanted_type)11485 ZigType *wanted_type, ResultLoc *result_loc)
10621{11486{
10622 assert(wanted_type->id == ZigTypeIdOptional);11487 assert(wanted_type->id == ZigTypeIdOptional);
1062311488
...@@ -10643,20 +11508,29 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so...@@ -10643,20 +11508,29 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
10643 return &const_instruction->base;11508 return &const_instruction->base;
10644 }11509 }
1064511510
10646 IrInstruction *result = ir_build_maybe_wrap(&ira->new_irb, source_instr->scope, source_instr->source_node, value);11511 if (result_loc == nullptr && handle_is_ptr(wanted_type)) {
10647 result->value.type = wanted_type;11512 result_loc = no_result_loc();
11513 }
11514 IrInstruction *result_loc_inst = nullptr;
11515 if (result_loc != nullptr) {
11516 result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
11517 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
11518 return result_loc_inst;
11519 }
11520 }
11521 IrInstruction *result = ir_build_optional_wrap(ira, source_instr, wanted_type, value, result_loc_inst);
10648 result->value.data.rh_maybe = RuntimeHintOptionalNonNull;11522 result->value.data.rh_maybe = RuntimeHintOptionalNonNull;
10649 ir_add_alloca(ira, result, wanted_type);
10650 return result;11523 return result;
10651}11524}
1065211525
10653static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instr,11526static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instr,
10654 IrInstruction *value, ZigType *wanted_type)11527 IrInstruction *value, ZigType *wanted_type, ResultLoc *result_loc)
10655{11528{
10656 assert(wanted_type->id == ZigTypeIdErrorUnion);11529 assert(wanted_type->id == ZigTypeIdErrorUnion);
1065711530
11531 ZigType *payload_type = wanted_type->data.error_union.payload_type;
11532 ZigType *err_set_type = wanted_type->data.error_union.err_set_type;
10658 if (instr_is_comptime(value)) {11533 if (instr_is_comptime(value)) {
10659 ZigType *payload_type = wanted_type->data.error_union.payload_type;
10660 IrInstruction *casted_payload = ir_implicit_cast(ira, value, payload_type);11534 IrInstruction *casted_payload = ir_implicit_cast(ira, value, payload_type);
10661 if (type_is_invalid(casted_payload->value.type))11535 if (type_is_invalid(casted_payload->value.type))
10662 return ira->codegen->invalid_instruction;11536 return ira->codegen->invalid_instruction;
...@@ -10666,7 +11540,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction...@@ -10666,7 +11540,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
10666 return ira->codegen->invalid_instruction;11540 return ira->codegen->invalid_instruction;
1066711541
10668 ConstExprValue *err_set_val = create_const_vals(1);11542 ConstExprValue *err_set_val = create_const_vals(1);
10669 err_set_val->type = wanted_type->data.error_union.err_set_type;11543 err_set_val->type = err_set_type;
10670 err_set_val->special = ConstValSpecialStatic;11544 err_set_val->special = ConstValSpecialStatic;
10671 err_set_val->data.x_err_set = nullptr;11545 err_set_val->data.x_err_set = nullptr;
1067211546
...@@ -10679,10 +11553,19 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction...@@ -10679,10 +11553,19 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
10679 return &const_instruction->base;11553 return &const_instruction->base;
10680 }11554 }
1068111555
10682 IrInstruction *result = ir_build_err_wrap_payload(&ira->new_irb, source_instr->scope, source_instr->source_node, value);11556 IrInstruction *result_loc_inst;
10683 result->value.type = wanted_type;11557 if (handle_is_ptr(wanted_type)) {
11558 if (result_loc == nullptr) result_loc = no_result_loc();
11559 result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
11560 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
11561 return result_loc_inst;
11562 }
11563 } else {
11564 result_loc_inst = nullptr;
11565 }
11566
11567 IrInstruction *result = ir_build_err_wrap_payload(ira, source_instr, wanted_type, value, result_loc_inst);
10684 result->value.data.rh_error_union = RuntimeHintErrorUnionNonError;11568 result->value.data.rh_error_union = RuntimeHintErrorUnionNonError;
10685 ir_add_alloca(ira, result, wanted_type);
10686 return result;11569 return result;
10687}11570}
1068811571
...@@ -10729,7 +11612,9 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou...@@ -10729,7 +11612,9 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou
10729 return result;11612 return result;
10730}11613}
1073111614
10732static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {11615static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
11616 ZigType *wanted_type, ResultLoc *result_loc)
11617{
10733 assert(wanted_type->id == ZigTypeIdErrorUnion);11618 assert(wanted_type->id == ZigTypeIdErrorUnion);
1073411619
10735 IrInstruction *casted_value = ir_implicit_cast(ira, value, wanted_type->data.error_union.err_set_type);11620 IrInstruction *casted_value = ir_implicit_cast(ira, value, wanted_type->data.error_union.err_set_type);
...@@ -10753,10 +11638,20 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so...@@ -10753,10 +11638,20 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
10753 return &const_instruction->base;11638 return &const_instruction->base;
10754 }11639 }
1075511640
10756 IrInstruction *result = ir_build_err_wrap_code(&ira->new_irb, source_instr->scope, source_instr->source_node, value);11641 IrInstruction *result_loc_inst;
10757 result->value.type = wanted_type;11642 if (handle_is_ptr(wanted_type)) {
11643 if (result_loc == nullptr) result_loc = no_result_loc();
11644 result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
11645 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
11646 return result_loc_inst;
11647 }
11648 } else {
11649 result_loc_inst = nullptr;
11650 }
11651
11652
11653 IrInstruction *result = ir_build_err_wrap_code(ira, source_instr, wanted_type, value, result_loc_inst);
10758 result->value.data.rh_error_union = RuntimeHintErrorUnionError;11654 result->value.data.rh_error_union = RuntimeHintErrorUnionError;
10759 ir_add_alloca(ira, result, wanted_type);
10760 return result;11655 return result;
10761}11656}
1076211657
...@@ -10816,20 +11711,21 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi...@@ -10816,20 +11711,21 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
1081611711
10817 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,11712 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
10818 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);11713 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
10819 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,11714
10820 source_instruction->source_node, value, is_const, is_volatile);11715 IrInstruction *result_loc;
10821 new_instruction->value.type = ptr_type;
10822 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
10823 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {11716 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
10824 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);11717 result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true, false);
10825 assert(fn_entry);11718 } else {
10826 fn_entry->alloca_list.append(new_instruction);11719 result_loc = nullptr;
10827 }11720 }
11721
11722 IrInstruction *new_instruction = ir_build_ref_gen(ira, source_instruction, ptr_type, value, result_loc);
11723 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
10828 return new_instruction;11724 return new_instruction;
10829}11725}
1083011726
10831static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,11727static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
10832 IrInstruction *array_arg, ZigType *wanted_type)11728 IrInstruction *array_arg, ZigType *wanted_type, ResultLoc *result_loc)
10833{11729{
10834 assert(is_slice(wanted_type));11730 assert(is_slice(wanted_type));
10835 // In this function we honor the const-ness of wanted_type, because11731 // In this function we honor the const-ness of wanted_type, because
...@@ -10838,7 +11734,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -10838,7 +11734,7 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
10838 IrInstruction *array_ptr = nullptr;11734 IrInstruction *array_ptr = nullptr;
10839 IrInstruction *array;11735 IrInstruction *array;
10840 if (array_arg->value.type->id == ZigTypeIdPointer) {11736 if (array_arg->value.type->id == ZigTypeIdPointer) {
10841 array = ir_get_deref(ira, source_instr, array_arg);11737 array = ir_get_deref(ira, source_instr, array_arg, nullptr);
10842 array_ptr = array_arg;11738 array_ptr = array_arg;
10843 } else {11739 } else {
10844 array = array_arg;11740 array = array_arg;
...@@ -10861,12 +11757,14 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -10861,12 +11757,14 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
1086111757
10862 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);11758 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
1086311759
10864 IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,11760 if (result_loc == nullptr) result_loc = no_result_loc();
10865 source_instr->source_node, array_ptr, start, end, false);11761 IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false);
10866 result->value.type = wanted_type;11762 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
11763 return result_loc_inst;
11764 }
11765 IrInstruction *result = ir_build_slice_gen(ira, source_instr, wanted_type, array_ptr, start, end, false, result_loc_inst);
10867 result->value.data.rh_slice.id = RuntimeHintSliceIdLen;11766 result->value.data.rh_slice.id = RuntimeHintSliceIdLen;
10868 result->value.data.rh_slice.len = array_type->data.array.len;11767 result->value.data.rh_slice.len = array_type->data.array.len;
10869 ir_add_alloca(ira, result, result->value.type);
1087011768
10871 return result;11769 return result;
10872}11770}
...@@ -11504,7 +12402,7 @@ static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *...@@ -11504,7 +12402,7 @@ static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *
11504}12402}
1150512403
11506static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr,12404static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr,
11507 IrInstruction *vector, ZigType *array_type)12405 IrInstruction *vector, ZigType *array_type, ResultLoc *result_loc)
11508{12406{
11509 if (instr_is_comptime(vector)) {12407 if (instr_is_comptime(vector)) {
11510 // arrays and vectors have the same ConstExprValue representation12408 // arrays and vectors have the same ConstExprValue representation
...@@ -11513,7 +12411,14 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *...@@ -11513,7 +12411,14 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
11513 result->value.type = array_type;12411 result->value.type = array_type;
11514 return result;12412 return result;
11515 }12413 }
11516 return ir_build_vector_to_array(ira, source_instr, vector, array_type);12414 if (result_loc == nullptr) {
12415 result_loc = no_result_loc();
12416 }
12417 IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, true, false);
12418 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
12419 return result_loc_inst;
12420 }
12421 return ir_build_vector_to_array(ira, source_instr, array_type, vector, result_loc_inst);
11517}12422}
1151812423
11519static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,12424static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,
...@@ -11563,7 +12468,7 @@ static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) {...@@ -11563,7 +12468,7 @@ static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) {
11563}12468}
1156412469
11565static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,12470static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
11566 ZigType *wanted_type, IrInstruction *value)12471 ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc)
11567{12472{
11568 Error err;12473 Error err;
11569 ZigType *actual_type = value->value.type;12474 ZigType *actual_type = value->value.type;
...@@ -11579,7 +12484,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11579,7 +12484,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11579 if (const_cast_result.id == ConstCastResultIdInvalid)12484 if (const_cast_result.id == ConstCastResultIdInvalid)
11580 return ira->codegen->invalid_instruction;12485 return ira->codegen->invalid_instruction;
11581 if (const_cast_result.id == ConstCastResultIdOk) {12486 if (const_cast_result.id == ConstCastResultIdOk) {
11582 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);12487 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop);
11583 }12488 }
1158412489
11585 // cast from T to ?T12490 // cast from T to ?T
...@@ -11589,12 +12494,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11589,12 +12494,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11589 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,12494 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
11590 false).id == ConstCastResultIdOk)12495 false).id == ConstCastResultIdOk)
11591 {12496 {
11592 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);12497 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, result_loc);
11593 } else if (actual_type->id == ZigTypeIdComptimeInt ||12498 } else if (actual_type->id == ZigTypeIdComptimeInt ||
11594 actual_type->id == ZigTypeIdComptimeFloat)12499 actual_type->id == ZigTypeIdComptimeFloat)
11595 {12500 {
11596 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {12501 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
11597 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);12502 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, result_loc);
11598 } else {12503 } else {
11599 return ira->codegen->invalid_instruction;12504 return ira->codegen->invalid_instruction;
11600 }12505 }
...@@ -11618,7 +12523,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11618,7 +12523,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11618 wanted_child_type);12523 wanted_child_type);
11619 if (type_is_invalid(cast1->value.type))12524 if (type_is_invalid(cast1->value.type))
11620 return ira->codegen->invalid_instruction;12525 return ira->codegen->invalid_instruction;
11621 return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type);12526 return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type, result_loc);
11622 }12527 }
11623 }12528 }
11624 }12529 }
...@@ -11628,12 +12533,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11628,12 +12533,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11628 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,12533 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
11629 source_node, false).id == ConstCastResultIdOk)12534 source_node, false).id == ConstCastResultIdOk)
11630 {12535 {
11631 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);12536 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, result_loc);
11632 } else if (actual_type->id == ZigTypeIdComptimeInt ||12537 } else if (actual_type->id == ZigTypeIdComptimeInt ||
11633 actual_type->id == ZigTypeIdComptimeFloat)12538 actual_type->id == ZigTypeIdComptimeFloat)
11634 {12539 {
11635 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {12540 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
11636 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);12541 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, result_loc);
11637 } else {12542 } else {
11638 return ira->codegen->invalid_instruction;12543 return ira->codegen->invalid_instruction;
11639 }12544 }
...@@ -11651,11 +12556,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11651,11 +12556,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11651 actual_type->id == ZigTypeIdComptimeInt ||12556 actual_type->id == ZigTypeIdComptimeInt ||
11652 actual_type->id == ZigTypeIdComptimeFloat)12557 actual_type->id == ZigTypeIdComptimeFloat)
11653 {12558 {
11654 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);12559 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value, nullptr);
11655 if (type_is_invalid(cast1->value.type))12560 if (type_is_invalid(cast1->value.type))
11656 return ira->codegen->invalid_instruction;12561 return ira->codegen->invalid_instruction;
1165712562
11658 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);12563 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
11659 if (type_is_invalid(cast2->value.type))12564 if (type_is_invalid(cast2->value.type))
11660 return ira->codegen->invalid_instruction;12565 return ira->codegen->invalid_instruction;
1166112566
...@@ -11737,7 +12642,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11737,7 +12642,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11737 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,12642 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
11738 source_node, false).id == ConstCastResultIdOk)12643 source_node, false).id == ConstCastResultIdOk)
11739 {12644 {
11740 return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type);12645 return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type, result_loc);
11741 }12646 }
11742 }12647 }
1174312648
...@@ -11754,11 +12659,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11754,11 +12659,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11754 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,12659 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
11755 source_node, false).id == ConstCastResultIdOk)12660 source_node, false).id == ConstCastResultIdOk)
11756 {12661 {
11757 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value);12662 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value, nullptr);
11758 if (type_is_invalid(cast1->value.type))12663 if (type_is_invalid(cast1->value.type))
11759 return ira->codegen->invalid_instruction;12664 return ira->codegen->invalid_instruction;
1176012665
11761 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);12666 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
11762 if (type_is_invalid(cast2->value.type))12667 if (type_is_invalid(cast2->value.type))
11763 return ira->codegen->invalid_instruction;12668 return ira->codegen->invalid_instruction;
1176412669
...@@ -11801,7 +12706,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11801,7 +12706,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11801 array_type->data.array.child_type, source_node,12706 array_type->data.array.child_type, source_node,
11802 !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk)12707 !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk)
11803 {12708 {
11804 return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type);12709 return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type, result_loc);
11805 }12710 }
11806 }12711 }
1180712712
...@@ -11832,11 +12737,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11832,11 +12737,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11832 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,12737 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
11833 source_node, false).id == ConstCastResultIdOk)12738 source_node, false).id == ConstCastResultIdOk)
11834 {12739 {
11835 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);12740 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value, nullptr);
11836 if (type_is_invalid(cast1->value.type))12741 if (type_is_invalid(cast1->value.type))
11837 return ira->codegen->invalid_instruction;12742 return ira->codegen->invalid_instruction;
1183812743
11839 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);12744 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
11840 if (type_is_invalid(cast2->value.type))12745 if (type_is_invalid(cast2->value.type))
11841 return ira->codegen->invalid_instruction;12746 return ira->codegen->invalid_instruction;
1184212747
...@@ -11848,7 +12753,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11848,7 +12753,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11848 if (wanted_type->id == ZigTypeIdErrorUnion &&12753 if (wanted_type->id == ZigTypeIdErrorUnion &&
11849 actual_type->id == ZigTypeIdErrorSet)12754 actual_type->id == ZigTypeIdErrorSet)
11850 {12755 {
11851 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);12756 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type, result_loc);
11852 }12757 }
1185312758
11854 // cast from typed number to integer or float literal.12759 // cast from typed number to integer or float literal.
...@@ -11972,7 +12877,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11972,7 +12877,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11972 types_match_const_cast_only(ira, wanted_type->data.array.child_type,12877 types_match_const_cast_only(ira, wanted_type->data.array.child_type,
11973 actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)12878 actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
11974 {12879 {
11975 return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type);12880 return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type, result_loc);
11976 }12881 }
1197712882
11978 // cast from [N]T to @Vector(N, T)12883 // cast from [N]T to @Vector(N, T)
...@@ -12014,7 +12919,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12014,7 +12919,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12014 return ira->codegen->invalid_instruction;12919 return ira->codegen->invalid_instruction;
12015}12920}
1201612921
12017static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) {12922static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type,
12923 ResultLoc *result_loc)
12924{
12018 assert(value);12925 assert(value);
12019 assert(value != ira->codegen->invalid_instruction);12926 assert(value != ira->codegen->invalid_instruction);
12020 assert(!expected_type || !type_is_invalid(expected_type));12927 assert(!expected_type || !type_is_invalid(expected_type));
...@@ -12027,63 +12934,76 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig...@@ -12027,63 +12934,76 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig
12027 if (value->value.type->id == ZigTypeIdUnreachable)12934 if (value->value.type->id == ZigTypeIdUnreachable)
12028 return value;12935 return value;
1202912936
12030 return ir_analyze_cast(ira, value, expected_type, value);12937 return ir_analyze_cast(ira, value, expected_type, value, result_loc);
12938}
12939
12940static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) {
12941 return ir_implicit_cast_with_result(ira, value, expected_type, nullptr);
12031}12942}
1203212943
12033static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) {12944static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
12945 ResultLoc *result_loc)
12946{
12034 Error err;12947 Error err;
12035 ZigType *type_entry = ptr->value.type;12948 ZigType *type_entry = ptr->value.type;
12036 if (type_is_invalid(type_entry)) {12949 if (type_is_invalid(type_entry))
12037 return ira->codegen->invalid_instruction;12950 return ira->codegen->invalid_instruction;
12038 } else if (type_entry->id == ZigTypeIdPointer) {12951
12039 ZigType *child_type = type_entry->data.pointer.child_type;12952 if (type_entry->id != ZigTypeIdPointer) {
12040 // if the child type has one possible value, the deref is comptime12953 ir_add_error_node(ira, source_instruction->source_node,
12041 switch (type_has_one_possible_value(ira->codegen, child_type)) {12954 buf_sprintf("attempt to dereference non-pointer type '%s'",
12042 case OnePossibleValueInvalid:12955 buf_ptr(&type_entry->name)));
12043 return ira->codegen->invalid_instruction;12956 return ira->codegen->invalid_instruction;
12044 case OnePossibleValueYes:12957 }
12045 return ir_const(ira, source_instruction, child_type);12958
12046 case OnePossibleValueNo:12959 ZigType *child_type = type_entry->data.pointer.child_type;
12047 break;12960 // if the child type has one possible value, the deref is comptime
12961 switch (type_has_one_possible_value(ira->codegen, child_type)) {
12962 case OnePossibleValueInvalid:
12963 return ira->codegen->invalid_instruction;
12964 case OnePossibleValueYes:
12965 return ir_const(ira, source_instruction, child_type);
12966 case OnePossibleValueNo:
12967 break;
12968 }
12969 if (instr_is_comptime(ptr)) {
12970 if (ptr->value.special == ConstValSpecialUndef) {
12971 ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));
12972 return ira->codegen->invalid_instruction;
12048 }12973 }
12049 if (instr_is_comptime(ptr)) {12974 if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
12050 if (ptr->value.special == ConstValSpecialUndef) {12975 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
12051 ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value"));12976 if (pointee->special != ConstValSpecialRuntime) {
12052 return ira->codegen->invalid_instruction;12977 IrInstruction *result = ir_const(ira, source_instruction, child_type);
12053 }
12054 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
12055 ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
12056 {
12057 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
12058 if (pointee->special != ConstValSpecialRuntime) {
12059 IrInstruction *result = ir_const(ira, source_instruction, child_type);
1206012978
12061 if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,12979 if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
12062 &ptr->value)))12980 &ptr->value)))
12063 {12981 {
12064 return ira->codegen->invalid_instruction;12982 return ira->codegen->invalid_instruction;
12065 }
12066 result->value.type = child_type;
12067 return result;
12068 }12983 }
12984 result->value.type = child_type;
12985 return result;
12069 }12986 }
12070 }12987 }
12071 // if the instruction is a const ref instruction we can skip it12988 }
12072 if (ptr->id == IrInstructionIdRef) {12989 // if the instruction is a const ref instruction we can skip it
12073 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);12990 if (ptr->id == IrInstructionIdRef) {
12074 return ref_inst->value;12991 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
12075 }12992 return ref_inst->value;
12076 IrInstruction *result = ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type);12993 }
12077 if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {12994
12078 ir_add_alloca(ira, result, child_type);12995 IrInstruction *result_loc_inst;
12996 if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
12997 if (result_loc == nullptr) result_loc = no_result_loc();
12998 result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true, false);
12999 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
13000 return result_loc_inst;
12079 }13001 }
12080 return result;
12081 } else {13002 } else {
12082 ir_add_error_node(ira, source_instruction->source_node,13003 result_loc_inst = nullptr;
12083 buf_sprintf("attempt to dereference non-pointer type '%s'",
12084 buf_ptr(&type_entry->name)));
12085 return ira->codegen->invalid_instruction;
12086 }13004 }
13005
13006 return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst);
12087}13007}
1208813008
12089static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {13009static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {
...@@ -12297,6 +13217,14 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio...@@ -12297,6 +13217,14 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
12297 if (type_is_invalid(value->value.type))13217 if (type_is_invalid(value->value.type))
12298 return ir_unreach_error(ira);13218 return ir_unreach_error(ira);
1229913219
13220 if (!instr_is_comptime(value) && handle_is_ptr(ira->explicit_return_type)) {
13221 // result location mechanism took care of it.
13222 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
13223 instruction->base.source_node, nullptr);
13224 result->value.type = ira->codegen->builtin_types.entry_unreachable;
13225 return ir_finish_anal(ira, result);
13226 }
13227
12300 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);13228 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);
12301 if (type_is_invalid(casted_value->value.type)) {13229 if (type_is_invalid(casted_value->value.type)) {
12302 AstNode *source_node = ira->explicit_return_type_source_node;13230 AstNode *source_node = ira->explicit_return_type_source_node;
...@@ -12459,7 +13387,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -12459,7 +13387,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
12459 } else {13387 } else {
12460 return is_non_null;13388 return is_non_null;
12461 }13389 }
12462 } else if (is_equality_cmp && 13390 } else if (is_equality_cmp &&
12463 ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdPointer &&13391 ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdPointer &&
12464 op2->value.type->data.pointer.ptr_len == PtrLenC) ||13392 op2->value.type->data.pointer.ptr_len == PtrLenC) ||
12465 (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdPointer &&13393 (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdPointer &&
...@@ -12901,7 +13829,7 @@ static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_in...@@ -12901,7 +13829,7 @@ static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_in
12901 }13829 }
12902 } else {13830 } else {
12903 float_div_trunc(out_val, op1_val, op2_val);13831 float_div_trunc(out_val, op1_val, op2_val);
12904 ConstExprValue remainder;13832 ConstExprValue remainder = {};
12905 float_rem(&remainder, op1_val, op2_val);13833 float_rem(&remainder, op1_val, op2_val);
12906 if (float_cmp_zero(&remainder) != CmpEQ) {13834 if (float_cmp_zero(&remainder) != CmpEQ) {
12907 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));13835 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
...@@ -13276,8 +14204,8 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -13276,8 +14204,8 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
13276 // have a remainder function ambiguity problem14204 // have a remainder function ambiguity problem
13277 ok = true;14205 ok = true;
13278 } else {14206 } else {
13279 ConstExprValue rem_result;14207 ConstExprValue rem_result = {};
13280 ConstExprValue mod_result;14208 ConstExprValue mod_result = {};
13281 float_rem(&rem_result, op1_val, op2_val);14209 float_rem(&rem_result, op1_val, op2_val);
13282 float_mod(&mod_result, op1_val, op2_val);14210 float_mod(&mod_result, op1_val, op2_val);
13283 ok = float_cmp(&rem_result, &mod_result) == CmpEQ;14211 ok = float_cmp(&rem_result, &mod_result) == CmpEQ;
...@@ -13500,10 +14428,12 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -13500,10 +14428,12 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1350014428
13501 size_t next_index = 0;14429 size_t next_index = 0;
13502 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {14430 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {
13503 out_array_val->data.x_array.data.s_none.elements[next_index] = op1_array_val->data.x_array.data.s_none.elements[i];14431 copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
14432 &op1_array_val->data.x_array.data.s_none.elements[i], true);
13504 }14433 }
13505 for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {14434 for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {
13506 out_array_val->data.x_array.data.s_none.elements[next_index] = op2_array_val->data.x_array.data.s_none.elements[i];14435 copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
14436 &op2_array_val->data.x_array.data.s_none.elements[i], true);
13507 }14437 }
13508 if (next_index < new_len) {14438 if (next_index < new_len) {
13509 ConstExprValue *null_byte = &out_array_val->data.x_array.data.s_none.elements[next_index];14439 ConstExprValue *null_byte = &out_array_val->data.x_array.data.s_none.elements[next_index];
...@@ -13564,7 +14494,8 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -13564,7 +14494,8 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
13564 uint64_t i = 0;14494 uint64_t i = 0;
13565 for (uint64_t x = 0; x < mult_amt; x += 1) {14495 for (uint64_t x = 0; x < mult_amt; x += 1) {
13566 for (uint64_t y = 0; y < old_array_len; y += 1) {14496 for (uint64_t y = 0; y < old_array_len; y += 1) {
13567 out_val->data.x_array.data.s_none.elements[i] = array_val->data.x_array.data.s_none.elements[y];14497 copy_const_val(&out_val->data.x_array.data.s_none.elements[i],
14498 &array_val->data.x_array.data.s_none.elements[y], true);
13568 i += 1;14499 i += 1;
13569 }14500 }
13570 }14501 }
...@@ -13661,12 +14592,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -13661,12 +14592,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
13661 Error err;14592 Error err;
13662 ZigVar *var = decl_var_instruction->var;14593 ZigVar *var = decl_var_instruction->var;
1366314594
13664 IrInstruction *init_value = decl_var_instruction->init_value->child;
13665 if (type_is_invalid(init_value->value.type)) {
13666 var->var_type = ira->codegen->builtin_types.entry_invalid;
13667 return ira->codegen->invalid_instruction;
13668 }
13669
13670 ZigType *explicit_type = nullptr;14595 ZigType *explicit_type = nullptr;
13671 IrInstruction *var_type = nullptr;14596 IrInstruction *var_type = nullptr;
13672 if (decl_var_instruction->var_type != nullptr) {14597 if (decl_var_instruction->var_type != nullptr) {
...@@ -13681,18 +14606,40 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -13681,18 +14606,40 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
1368114606
13682 AstNode *source_node = decl_var_instruction->base.source_node;14607 AstNode *source_node = decl_var_instruction->base.source_node;
1368314608
13684 IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, explicit_type);
13685 bool is_comptime_var = ir_get_var_is_comptime(var);14609 bool is_comptime_var = ir_get_var_is_comptime(var);
1368614610
13687 bool var_class_requires_const = false;14611 bool var_class_requires_const = false;
1368814612
13689 ZigType *result_type = casted_init_value->value.type;14613 IrInstruction *var_ptr = decl_var_instruction->ptr->child;
14614 // if this is null, a compiler error happened and did not initialize the variable.
14615 // if there are no compile errors there may be a missing ir_expr_wrap in pass1 IR generation.
14616 if (var_ptr == nullptr || type_is_invalid(var_ptr->value.type)) {
14617 ir_assert(var_ptr != nullptr || ira->codegen->errors.length != 0, &decl_var_instruction->base);
14618 var->var_type = ira->codegen->builtin_types.entry_invalid;
14619 return ira->codegen->invalid_instruction;
14620 }
14621
14622 // The ir_build_var_decl_src call is supposed to pass a pointer to the allocation, not an initialization value.
14623 ir_assert(var_ptr->value.type->id == ZigTypeIdPointer, &decl_var_instruction->base);
14624
14625 ZigType *result_type = var_ptr->value.type->data.pointer.child_type;
13690 if (type_is_invalid(result_type)) {14626 if (type_is_invalid(result_type)) {
13691 result_type = ira->codegen->builtin_types.entry_invalid;14627 result_type = ira->codegen->builtin_types.entry_invalid;
13692 } else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) {14628 } else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) {
13693 ir_add_error_node(ira, source_node,14629 zig_unreachable();
13694 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));14630 }
13695 result_type = ira->codegen->builtin_types.entry_invalid;14631
14632 ConstExprValue *init_val = nullptr;
14633 if (instr_is_comptime(var_ptr) && var_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
14634 init_val = const_ptr_pointee(ira, ira->codegen, &var_ptr->value, decl_var_instruction->base.source_node);
14635 if (is_comptime_var) {
14636 if (var->gen_is_const) {
14637 var->const_value = init_val;
14638 } else {
14639 var->const_value = create_const_vals(1);
14640 copy_const_val(var->const_value, init_val, false);
14641 }
14642 }
13696 }14643 }
1369714644
13698 switch (type_requires_comptime(ira->codegen, result_type)) {14645 switch (type_requires_comptime(ira->codegen, result_type)) {
...@@ -13709,18 +14656,20 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -13709,18 +14656,20 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
13709 }14656 }
13710 break;14657 break;
13711 case ReqCompTimeNo:14658 case ReqCompTimeNo:
13712 if (casted_init_value->value.special == ConstValSpecialStatic &&14659 if (init_val != nullptr) {
13713 casted_init_value->value.type->id == ZigTypeIdFn &&14660 if (init_val->special == ConstValSpecialStatic &&
13714 casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&14661 init_val->type->id == ZigTypeIdFn &&
13715 casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)14662 init_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
13716 {14663 init_val->data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
13717 var_class_requires_const = true;14664 {
13718 if (!var->src_is_const && !is_comptime_var) {14665 var_class_requires_const = true;
13719 ErrorMsg *msg = ir_add_error_node(ira, source_node,14666 if (!var->src_is_const && !is_comptime_var) {
13720 buf_sprintf("functions marked inline must be stored in const or comptime var"));14667 ErrorMsg *msg = ir_add_error_node(ira, source_node,
13721 AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node;14668 buf_sprintf("functions marked inline must be stored in const or comptime var"));
13722 add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here"));14669 AstNode *proto_node = init_val->data.x_ptr.data.fn.fn_entry->proto_node;
13723 result_type = ira->codegen->builtin_types.entry_invalid;14670 add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here"));
14671 result_type = ira->codegen->builtin_types.entry_invalid;
14672 }
13724 }14673 }
13725 }14674 }
13726 break;14675 break;
...@@ -13767,11 +14716,29 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -13767,11 +14716,29 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
13767 }14716 }
13768 }14717 }
1376914718
13770 if (casted_init_value->value.special != ConstValSpecialRuntime) {14719 if (init_val != nullptr && init_val->special != ConstValSpecialRuntime) {
13771 if (var->mem_slot_index != SIZE_MAX) {14720 // Resolve ConstPtrMutInfer
14721 if (var->gen_is_const) {
14722 var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
14723 } else if (is_comptime_var) {
14724 var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeVar;
14725 } else {
14726 // we need a runtime ptr but we have a comptime val.
14727 // since it's a comptime val there are no instructions for it.
14728 // we memcpy the init value here
14729 IrInstruction *deref = ir_get_deref(ira, var_ptr, var_ptr, nullptr);
14730 // If this assertion trips, something is wrong with the IR instructions, because
14731 // we expected the above deref to return a constant value, but it created a runtime
14732 // instruction.
14733 assert(deref->value.special != ConstValSpecialRuntime);
14734 var_ptr->value.special = ConstValSpecialRuntime;
14735 ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref);
14736 }
14737
14738 if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) {
13772 assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);14739 assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);
13773 ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);14740 ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);
13774 copy_const_val(mem_slot, &casted_init_value->value, !is_comptime_var || var->gen_is_const);14741 copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const);
1377514742
13776 if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) {14743 if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) {
13777 return ir_const_void(ira, &decl_var_instruction->base);14744 return ir_const_void(ira, &decl_var_instruction->base);
...@@ -13788,7 +14755,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -13788,7 +14755,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
13788 if (fn_entry)14755 if (fn_entry)
13789 fn_entry->variable_list.append(var);14756 fn_entry->variable_list.append(var);
1379014757
13791 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);14758 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, var_ptr);
13792}14759}
1379314760
13794static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {14761static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
...@@ -14082,7 +15049,7 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i...@@ -14082,7 +15049,7 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
14082 ZigVar *coro_allocator_var = ira->old_irb.exec->coro_allocator_var;15049 ZigVar *coro_allocator_var = ira->old_irb.exec->coro_allocator_var;
14083 assert(coro_allocator_var != nullptr);15050 assert(coro_allocator_var != nullptr);
14084 IrInstruction *var_ptr_inst = ir_get_var_ptr(ira, source_instr, coro_allocator_var);15051 IrInstruction *var_ptr_inst = ir_get_var_ptr(ira, source_instr, coro_allocator_var);
14085 IrInstruction *result = ir_get_deref(ira, source_instr, var_ptr_inst);15052 IrInstruction *result = ir_get_deref(ira, source_instr, var_ptr_inst, nullptr);
14086 assert(result->value.type != nullptr);15053 assert(result->value.type != nullptr);
14087 return result;15054 return result;
14088 }15055 }
...@@ -14090,109 +15057,543 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i...@@ -14090,109 +15057,543 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
14090 zig_unreachable();15057 zig_unreachable();
14091}15058}
1409215059
14093static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, ZigFn *fn_entry,15060static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type,
14094 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,15061 uint32_t align, const char *name_hint, bool force_comptime)
14095 IrInstruction *async_allocator_inst)
14096{15062{
14097 Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);15063 Error err;
14098 ir_assert(async_allocator_inst->value.type->id == ZigTypeIdPointer, &call_instruction->base);
14099 ZigType *container_type = async_allocator_inst->value.type->data.pointer.child_type;
14100 IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, realloc_field_name, &call_instruction->base,
14101 async_allocator_inst, container_type);
14102 if (type_is_invalid(field_ptr_inst->value.type)) {
14103 return ira->codegen->invalid_instruction;
14104 }
14105 ZigType *ptr_to_realloc_fn_type = field_ptr_inst->value.type;
14106 ir_assert(ptr_to_realloc_fn_type->id == ZigTypeIdPointer, &call_instruction->base);
1410715064
14108 ZigType *realloc_fn_type = ptr_to_realloc_fn_type->data.pointer.child_type;15065 ConstExprValue *pointee = create_const_vals(1);
14109 if (realloc_fn_type->id != ZigTypeIdFn) {15066 pointee->special = ConstValSpecialUndef;
14110 ir_add_error(ira, &call_instruction->base,
14111 buf_sprintf("expected reallocation function, found '%s'", buf_ptr(&realloc_fn_type->name)));
14112 return ira->codegen->invalid_instruction;
14113 }
1411415067
14115 ZigType *realloc_fn_return_type = realloc_fn_type->data.fn.fn_type_id.return_type;15068 IrInstructionAllocaGen *result = ir_create_alloca_gen(ira, source_inst, align, name_hint);
14116 if (realloc_fn_return_type->id != ZigTypeIdErrorUnion) {15069 result->base.value.special = ConstValSpecialStatic;
14117 ir_add_error(ira, fn_ref,15070 result->base.value.data.x_ptr.special = ConstPtrSpecialRef;
14118 buf_sprintf("expected allocation function to return error union, but it returns '%s'", buf_ptr(&realloc_fn_return_type->name)));15071 result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer;
15072 result->base.value.data.x_ptr.data.ref.pointee = pointee;
15073
15074 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))
14119 return ira->codegen->invalid_instruction;15075 return ira->codegen->invalid_instruction;
14120 }15076 assert(result->base.value.data.x_ptr.special != ConstPtrSpecialInvalid);
14121 ZigType *alloc_fn_error_set_type = realloc_fn_return_type->data.error_union.err_set_type;
14122 ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;
14123 ZigType *promise_type = get_promise_type(ira->codegen, return_type);
14124 ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
1412515077
14126 IrInstruction *result = ir_build_call(&ira->new_irb, call_instruction->base.scope, call_instruction->base.source_node,15078 pointee->type = var_type;
14127 fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst, nullptr);15079 result->base.value.type = get_pointer_to_type_extra(ira->codegen, var_type, false, false,
14128 result->value.type = async_return_type;15080 PtrLenSingle, align, 0, 0, false);
14129 return result;15081
15082 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
15083 if (fn_entry != nullptr) {
15084 fn_entry->alloca_gen_list.append(result);
15085 }
15086 result->base.is_gen = true;
15087 return &result->base;
14130}15088}
1413115089
14132static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,15090static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspend_source_instr,
14133 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)15091 ResultLoc *result_loc)
14134{15092{
14135 AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i);15093 switch (result_loc->id) {
14136 assert(param_decl_node->type == NodeTypeParamDecl);15094 case ResultLocIdInvalid:
1413715095 case ResultLocIdPeerParent:
14138 IrInstruction *casted_arg;15096 zig_unreachable();
14139 if (param_decl_node->data.param_decl.var_token == nullptr) {15097 case ResultLocIdNone:
14140 AstNode *param_type_node = param_decl_node->data.param_decl.type;15098 case ResultLocIdVar:
14141 ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node);15099 case ResultLocIdBitCast:
14142 if (type_is_invalid(param_type))15100 return nullptr;
14143 return false;15101 case ResultLocIdInstruction:
15102 return result_loc->source_instruction->child->value.type;
15103 case ResultLocIdReturn:
15104 return ira->explicit_return_type;
15105 case ResultLocIdPeer:
15106 return reinterpret_cast<ResultLocPeer*>(result_loc)->parent->resolved_type;
15107 }
15108 zig_unreachable();
15109}
1414415110
14145 casted_arg = ir_implicit_cast(ira, arg, param_type);15111static bool type_can_bit_cast(ZigType *t) {
14146 if (type_is_invalid(casted_arg->value.type))15112 switch (t->id) {
15113 case ZigTypeIdInvalid:
15114 zig_unreachable();
15115 case ZigTypeIdMetaType:
15116 case ZigTypeIdOpaque:
15117 case ZigTypeIdBoundFn:
15118 case ZigTypeIdArgTuple:
15119 case ZigTypeIdUnreachable:
15120 case ZigTypeIdComptimeFloat:
15121 case ZigTypeIdComptimeInt:
15122 case ZigTypeIdEnumLiteral:
15123 case ZigTypeIdUndefined:
15124 case ZigTypeIdNull:
15125 case ZigTypeIdPointer:
14147 return false;15126 return false;
14148 } else {15127 default:
14149 casted_arg = arg;15128 // TODO list these types out explicitly, there are probably some other invalid ones here
15129 return true;
14150 }15130 }
15131}
1415115132
14152 ConstExprValue *arg_val = ir_resolve_const(ira, casted_arg, UndefBad);15133static void set_up_result_loc_for_inferred_comptime(IrInstruction *ptr) {
14153 if (!arg_val)15134 ConstExprValue *undef_child = create_const_vals(1);
14154 return false;15135 undef_child->type = ptr->value.type->data.pointer.child_type;
1415515136 undef_child->special = ConstValSpecialUndef;
14156 Buf *param_name = param_decl_node->data.param_decl.name;15137 ptr->value.special = ConstValSpecialStatic;
14157 ZigVar *var = add_variable(ira->codegen, param_decl_node,15138 ptr->value.data.x_ptr.mut = ConstPtrMutInfer;
14158 *exec_scope, param_name, true, arg_val, nullptr, arg_val->type);15139 ptr->value.data.x_ptr.special = ConstPtrSpecialRef;
14159 *exec_scope = var->child_scope;15140 ptr->value.data.x_ptr.data.ref.pointee = undef_child;
14160 *next_proto_i += 1;
14161
14162 return true;
14163}15141}
1416415142
14165static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_node,15143// when calling this function, at the callsite must check for result type noreturn and propagate it up
14166 IrInstruction *arg, Scope **child_scope, size_t *next_proto_i,15144static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr,
14167 GenericFnTypeId *generic_id, FnTypeId *fn_type_id, IrInstruction **casted_args,15145 ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime)
14168 ZigFn *impl_fn)
14169{15146{
14170 AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i);15147 Error err;
14171 assert(param_decl_node->type == NodeTypeParamDecl);15148 if (result_loc->resolved_loc != nullptr) {
14172 bool is_var_args = param_decl_node->data.param_decl.is_var_args;15149 // allow to redo the result location if the value is known and comptime and the previous one isn't
14173 bool arg_part_of_generic_id = false;15150 if (value == nullptr || !instr_is_comptime(value) || instr_is_comptime(result_loc->resolved_loc)) {
14174 IrInstruction *casted_arg;15151 return result_loc->resolved_loc;
14175 if (is_var_args) {
14176 arg_part_of_generic_id = true;
14177 casted_arg = arg;
14178 } else {
14179 if (param_decl_node->data.param_decl.var_token == nullptr) {
14180 AstNode *param_type_node = param_decl_node->data.param_decl.type;
14181 ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node);
14182 if (type_is_invalid(param_type))
14183 return false;
14184
14185 casted_arg = ir_implicit_cast(ira, arg, param_type);
14186 if (type_is_invalid(casted_arg->value.type))
14187 return false;
14188 } else {
14189 arg_part_of_generic_id = true;
14190 casted_arg = arg;
14191 }15152 }
14192 }15153 }
15154 result_loc->gen_instruction = value;
15155 result_loc->implicit_elem_type = value_type;
15156 switch (result_loc->id) {
15157 case ResultLocIdInvalid:
15158 case ResultLocIdPeerParent:
15159 zig_unreachable();
15160 case ResultLocIdNone: {
15161 if (value != nullptr) {
15162 return nullptr;
15163 }
15164 // need to return a result location and don't have one. use a stack allocation
15165 IrInstructionAllocaGen *alloca_gen = ir_create_alloca_gen(ira, suspend_source_instr, 0, "");
15166 if ((err = type_resolve(ira->codegen, value_type, ResolveStatusZeroBitsKnown)))
15167 return ira->codegen->invalid_instruction;
15168 alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,
15169 PtrLenSingle, 0, 0, 0, false);
15170 set_up_result_loc_for_inferred_comptime(&alloca_gen->base);
15171 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
15172 if (fn_entry != nullptr) {
15173 fn_entry->alloca_gen_list.append(alloca_gen);
15174 }
15175 result_loc->written = true;
15176 result_loc->resolved_loc = &alloca_gen->base;
15177 return result_loc->resolved_loc;
15178 }
15179 case ResultLocIdVar: {
15180 ResultLocVar *result_loc_var = reinterpret_cast<ResultLocVar *>(result_loc);
15181 assert(result_loc->source_instruction->id == IrInstructionIdAllocaSrc);
15182
15183 if (value_type->id == ZigTypeIdUnreachable || value_type->id == ZigTypeIdOpaque) {
15184 ir_add_error(ira, result_loc->source_instruction,
15185 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&value_type->name)));
15186 return ira->codegen->invalid_instruction;
15187 }
1419315188
14194 bool comptime_arg = param_decl_node->data.param_decl.is_inline ||15189 IrInstructionAllocaSrc *alloca_src =
14195 casted_arg->value.type->id == ZigTypeIdComptimeInt || casted_arg->value.type->id == ZigTypeIdComptimeFloat;15190 reinterpret_cast<IrInstructionAllocaSrc *>(result_loc->source_instruction);
15191 bool force_comptime;
15192 if (!ir_resolve_comptime(ira, alloca_src->is_comptime->child, &force_comptime))
15193 return ira->codegen->invalid_instruction;
15194 bool is_comptime = force_comptime || (value != nullptr &&
15195 value->value.special != ConstValSpecialRuntime && result_loc_var->var->gen_is_const);
15196
15197 if (alloca_src->base.child == nullptr || is_comptime) {
15198 uint32_t align = 0;
15199 if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, &align)) {
15200 return ira->codegen->invalid_instruction;
15201 }
15202 IrInstruction *alloca_gen;
15203 if (is_comptime && value != nullptr) {
15204 if (align > value->value.global_refs->align) {
15205 value->value.global_refs->align = align;
15206 }
15207 alloca_gen = ir_get_ref(ira, result_loc->source_instruction, value, true, false);
15208 } else {
15209 alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, value_type, align,
15210 alloca_src->name_hint, force_comptime);
15211 }
15212 if (alloca_src->base.child != nullptr) {
15213 alloca_src->base.child->ref_count = 0;
15214 }
15215 alloca_src->base.child = alloca_gen;
15216 }
15217 result_loc->written = true;
15218 result_loc->resolved_loc = is_comptime ? nullptr : alloca_src->base.child;
15219 return result_loc->resolved_loc;
15220 }
15221 case ResultLocIdInstruction: {
15222 result_loc->written = true;
15223 result_loc->resolved_loc = result_loc->source_instruction->child;
15224 return result_loc->resolved_loc;
15225 }
15226 case ResultLocIdReturn: {
15227 if (!non_null_comptime) {
15228 bool is_comptime = value != nullptr && value->value.special != ConstValSpecialRuntime;
15229 if (is_comptime)
15230 return nullptr;
15231 }
15232 if ((err = type_resolve(ira->codegen, ira->explicit_return_type, ResolveStatusZeroBitsKnown))) {
15233 return ira->codegen->invalid_instruction;
15234 }
15235 if (!type_has_bits(ira->explicit_return_type) || !handle_is_ptr(ira->explicit_return_type))
15236 return nullptr;
15237
15238 ZigType *ptr_return_type = get_pointer_to_type(ira->codegen, ira->explicit_return_type, false);
15239 result_loc->written = true;
15240 result_loc->resolved_loc = ir_build_return_ptr(ira, result_loc->source_instruction, ptr_return_type);
15241 if (ir_should_inline(ira->old_irb.exec, result_loc->source_instruction->scope)) {
15242 set_up_result_loc_for_inferred_comptime(result_loc->resolved_loc);
15243 }
15244 return result_loc->resolved_loc;
15245 }
15246 case ResultLocIdPeer: {
15247 ResultLocPeer *result_peer = reinterpret_cast<ResultLocPeer *>(result_loc);
15248 ResultLocPeerParent *peer_parent = result_peer->parent;
15249
15250 if (peer_parent->peers.length == 1) {
15251 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
15252 value_type, value, force_runtime, non_null_comptime);
15253 result_peer->suspend_pos.basic_block_index = SIZE_MAX;
15254 result_peer->suspend_pos.instruction_index = SIZE_MAX;
15255 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
15256 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
15257 {
15258 return parent_result_loc;
15259 }
15260 result_loc->written = true;
15261 result_loc->resolved_loc = parent_result_loc;
15262 return result_loc->resolved_loc;
15263 }
15264
15265 bool is_comptime;
15266 if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime))
15267 return ira->codegen->invalid_instruction;
15268 peer_parent->skipped = is_comptime;
15269 if (peer_parent->skipped) {
15270 if (non_null_comptime) {
15271 return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
15272 value_type, value, force_runtime, non_null_comptime);
15273 }
15274 return nullptr;
15275 }
15276
15277 if (peer_parent->resolved_type == nullptr) {
15278 if (peer_parent->end_bb->suspend_instruction_ref == nullptr) {
15279 peer_parent->end_bb->suspend_instruction_ref = suspend_source_instr;
15280 }
15281 IrInstruction *unreach_inst = ira_suspend(ira, suspend_source_instr, result_peer->next_bb,
15282 &result_peer->suspend_pos);
15283 if (result_peer->next_bb == nullptr) {
15284 ir_start_next_bb(ira);
15285 }
15286 return unreach_inst;
15287 }
15288
15289 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
15290 peer_parent->resolved_type, nullptr, force_runtime, non_null_comptime);
15291 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
15292 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
15293 {
15294 return parent_result_loc;
15295 }
15296 // because is_comptime is false, we mark this a runtime pointer
15297 parent_result_loc->value.special = ConstValSpecialRuntime;
15298 result_loc->written = true;
15299 result_loc->resolved_loc = parent_result_loc;
15300 return result_loc->resolved_loc;
15301 }
15302 case ResultLocIdBitCast: {
15303 ResultLocBitCast *result_bit_cast = reinterpret_cast<ResultLocBitCast *>(result_loc);
15304 ZigType *dest_type = ir_resolve_type(ira, result_bit_cast->base.source_instruction->child);
15305 if (type_is_invalid(dest_type))
15306 return ira->codegen->invalid_instruction;
15307
15308 if (get_codegen_ptr_type(dest_type) != nullptr) {
15309 ir_add_error(ira, result_loc->source_instruction,
15310 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
15311 return ira->codegen->invalid_instruction;
15312 }
15313
15314 if (!type_can_bit_cast(dest_type)) {
15315 ir_add_error(ira, result_loc->source_instruction,
15316 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
15317 return ira->codegen->invalid_instruction;
15318 }
15319
15320 if (get_codegen_ptr_type(value_type) != nullptr) {
15321 ir_add_error(ira, suspend_source_instr,
15322 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&value_type->name)));
15323 return ira->codegen->invalid_instruction;
15324 }
15325
15326 if (!type_can_bit_cast(value_type)) {
15327 ir_add_error(ira, suspend_source_instr,
15328 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&value_type->name)));
15329 return ira->codegen->invalid_instruction;
15330 }
15331
15332 IrInstruction *bitcasted_value;
15333 if (value != nullptr) {
15334 bitcasted_value = ir_analyze_bit_cast(ira, result_loc->source_instruction, value, dest_type);
15335 } else {
15336 bitcasted_value = nullptr;
15337 }
15338
15339 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent,
15340 dest_type, bitcasted_value, force_runtime, non_null_comptime);
15341 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
15342 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
15343 {
15344 return parent_result_loc;
15345 }
15346 ZigType *parent_ptr_type = parent_result_loc->value.type;
15347 assert(parent_ptr_type->id == ZigTypeIdPointer);
15348 if ((err = type_resolve(ira->codegen, parent_ptr_type->data.pointer.child_type,
15349 ResolveStatusAlignmentKnown)))
15350 {
15351 return ira->codegen->invalid_instruction;
15352 }
15353 uint64_t parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type);
15354 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type,
15355 parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
15356 parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);
15357
15358 result_loc->written = true;
15359 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
15360 ptr_type, result_bit_cast->base.source_instruction, false);
15361 return result_loc->resolved_loc;
15362 }
15363 }
15364 zig_unreachable();
15365}
15366
15367static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
15368 ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime,
15369 bool non_null_comptime)
15370{
15371 IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type,
15372 value, force_runtime, non_null_comptime);
15373 if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value.type)))
15374 return result_loc;
15375
15376 if ((force_runtime || (value != nullptr && !instr_is_comptime(value))) &&
15377 result_loc_pass1->written && result_loc->value.data.x_ptr.mut == ConstPtrMutInfer)
15378 {
15379 result_loc->value.special = ConstValSpecialRuntime;
15380 }
15381
15382 ir_assert(result_loc->value.type->id == ZigTypeIdPointer, suspend_source_instr);
15383 ZigType *actual_elem_type = result_loc->value.type->data.pointer.child_type;
15384 if (actual_elem_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
15385 value_type->id != ZigTypeIdNull)
15386 {
15387 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
15388 } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {
15389 if (value_type->id == ZigTypeIdErrorSet) {
15390 return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
15391 } else {
15392 IrInstruction *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
15393 result_loc, false, true);
15394 ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
15395 if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional) {
15396 return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
15397 } else {
15398 return unwrapped_err_ptr;
15399 }
15400 }
15401 } else if (is_slice(actual_elem_type) && value_type->id == ZigTypeIdArray) {
15402 // need to allow EndExpr to do the implicit cast from array to slice
15403 result_loc_pass1->written = false;
15404 }
15405 return result_loc;
15406}
15407
15408static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrInstructionImplicitCast *instruction) {
15409 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
15410 if (type_is_invalid(dest_type))
15411 return ira->codegen->invalid_instruction;
15412
15413 IrInstruction *target = instruction->target->child;
15414 if (type_is_invalid(target->value.type))
15415 return ira->codegen->invalid_instruction;
15416
15417 return ir_implicit_cast_with_result(ira, target, dest_type, instruction->result_loc);
15418}
15419
15420static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) {
15421 ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
15422 if (type_is_invalid(implicit_elem_type))
15423 return ira->codegen->invalid_instruction;
15424 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
15425 implicit_elem_type, nullptr, false, true);
15426 if (result_loc != nullptr)
15427 return result_loc;
15428
15429 ZigFn *fn = exec_fn_entry(ira->new_irb.exec);
15430 if (fn != nullptr && fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync &&
15431 instruction->result_loc->id == ResultLocIdReturn)
15432 {
15433 result_loc = ir_resolve_result(ira, &instruction->base, no_result_loc(),
15434 implicit_elem_type, nullptr, false, true);
15435 if (result_loc != nullptr &&
15436 (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
15437 {
15438 return result_loc;
15439 }
15440 result_loc->value.special = ConstValSpecialRuntime;
15441 return result_loc;
15442 }
15443
15444 IrInstruction *result = ir_const(ira, &instruction->base, implicit_elem_type);
15445 result->value.special = ConstValSpecialUndef;
15446 IrInstruction *ptr = ir_get_ref(ira, &instruction->base, result, false, false);
15447 ptr->value.data.x_ptr.mut = ConstPtrMutComptimeVar;
15448 return ptr;
15449}
15450
15451static void ir_reset_result(ResultLoc *result_loc) {
15452 result_loc->written = false;
15453 result_loc->resolved_loc = nullptr;
15454 result_loc->gen_instruction = nullptr;
15455 result_loc->implicit_elem_type = nullptr;
15456 switch (result_loc->id) {
15457 case ResultLocIdInvalid:
15458 zig_unreachable();
15459 case ResultLocIdPeerParent: {
15460 ResultLocPeerParent *peer_parent = reinterpret_cast<ResultLocPeerParent *>(result_loc);
15461 peer_parent->skipped = false;
15462 peer_parent->done_resuming = false;
15463 peer_parent->resolved_type = nullptr;
15464 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
15465 ir_reset_result(&peer_parent->peers.at(i)->base);
15466 }
15467 break;
15468 }
15469 case ResultLocIdVar: {
15470 IrInstructionAllocaSrc *alloca_src =
15471 reinterpret_cast<IrInstructionAllocaSrc *>(result_loc->source_instruction);
15472 alloca_src->base.child = nullptr;
15473 break;
15474 }
15475 case ResultLocIdPeer:
15476 case ResultLocIdNone:
15477 case ResultLocIdReturn:
15478 case ResultLocIdInstruction:
15479 case ResultLocIdBitCast:
15480 break;
15481 }
15482}
15483
15484static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInstructionResetResult *instruction) {
15485 ir_reset_result(instruction->result_loc);
15486 return ir_const_void(ira, &instruction->base);
15487}
15488
15489static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
15490 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
15491 IrInstruction *async_allocator_inst)
15492{
15493 Buf *realloc_field_name = buf_create_from_str(ASYNC_REALLOC_FIELD_NAME);
15494 ir_assert(async_allocator_inst->value.type->id == ZigTypeIdPointer, &call_instruction->base);
15495 ZigType *container_type = async_allocator_inst->value.type->data.pointer.child_type;
15496 IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, realloc_field_name, &call_instruction->base,
15497 async_allocator_inst, container_type, false);
15498 if (type_is_invalid(field_ptr_inst->value.type)) {
15499 return ira->codegen->invalid_instruction;
15500 }
15501 ZigType *ptr_to_realloc_fn_type = field_ptr_inst->value.type;
15502 ir_assert(ptr_to_realloc_fn_type->id == ZigTypeIdPointer, &call_instruction->base);
15503
15504 ZigType *realloc_fn_type = ptr_to_realloc_fn_type->data.pointer.child_type;
15505 if (realloc_fn_type->id != ZigTypeIdFn) {
15506 ir_add_error(ira, &call_instruction->base,
15507 buf_sprintf("expected reallocation function, found '%s'", buf_ptr(&realloc_fn_type->name)));
15508 return ira->codegen->invalid_instruction;
15509 }
15510
15511 ZigType *realloc_fn_return_type = realloc_fn_type->data.fn.fn_type_id.return_type;
15512 if (realloc_fn_return_type->id != ZigTypeIdErrorUnion) {
15513 ir_add_error(ira, fn_ref,
15514 buf_sprintf("expected allocation function to return error union, but it returns '%s'", buf_ptr(&realloc_fn_return_type->name)));
15515 return ira->codegen->invalid_instruction;
15516 }
15517 ZigType *alloc_fn_error_set_type = realloc_fn_return_type->data.error_union.err_set_type;
15518 ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;
15519 ZigType *promise_type = get_promise_type(ira->codegen, return_type);
15520 ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
15521
15522 IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, no_result_loc(),
15523 async_return_type, nullptr, true, true);
15524 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
15525 return result_loc;
15526 }
15527
15528 return ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,
15529 casted_args, FnInlineAuto, true, async_allocator_inst, nullptr, result_loc,
15530 async_return_type);
15531}
15532
15533static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
15534 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)
15535{
15536 AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i);
15537 assert(param_decl_node->type == NodeTypeParamDecl);
15538
15539 IrInstruction *casted_arg;
15540 if (param_decl_node->data.param_decl.var_token == nullptr) {
15541 AstNode *param_type_node = param_decl_node->data.param_decl.type;
15542 ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node);
15543 if (type_is_invalid(param_type))
15544 return false;
15545
15546 casted_arg = ir_implicit_cast(ira, arg, param_type);
15547 if (type_is_invalid(casted_arg->value.type))
15548 return false;
15549 } else {
15550 casted_arg = arg;
15551 }
15552
15553 ConstExprValue *arg_val = ir_resolve_const(ira, casted_arg, UndefOk);
15554 if (!arg_val)
15555 return false;
15556
15557 Buf *param_name = param_decl_node->data.param_decl.name;
15558 ZigVar *var = add_variable(ira->codegen, param_decl_node,
15559 *exec_scope, param_name, true, arg_val, nullptr, arg_val->type);
15560 *exec_scope = var->child_scope;
15561 *next_proto_i += 1;
15562
15563 return true;
15564}
15565
15566static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_node,
15567 IrInstruction *arg, Scope **child_scope, size_t *next_proto_i,
15568 GenericFnTypeId *generic_id, FnTypeId *fn_type_id, IrInstruction **casted_args,
15569 ZigFn *impl_fn)
15570{
15571 AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i);
15572 assert(param_decl_node->type == NodeTypeParamDecl);
15573 bool is_var_args = param_decl_node->data.param_decl.is_var_args;
15574 bool arg_part_of_generic_id = false;
15575 IrInstruction *casted_arg;
15576 if (is_var_args) {
15577 arg_part_of_generic_id = true;
15578 casted_arg = arg;
15579 } else {
15580 if (param_decl_node->data.param_decl.var_token == nullptr) {
15581 AstNode *param_type_node = param_decl_node->data.param_decl.type;
15582 ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node);
15583 if (type_is_invalid(param_type))
15584 return false;
15585
15586 casted_arg = ir_implicit_cast(ira, arg, param_type);
15587 if (type_is_invalid(casted_arg->value.type))
15588 return false;
15589 } else {
15590 arg_part_of_generic_id = true;
15591 casted_arg = arg;
15592 }
15593 }
15594
15595 bool comptime_arg = param_decl_node->data.param_decl.is_inline ||
15596 casted_arg->value.type->id == ZigTypeIdComptimeInt || casted_arg->value.type->id == ZigTypeIdComptimeFloat;
1419615597
14197 ConstExprValue *arg_val;15598 ConstExprValue *arg_val;
1419815599
...@@ -14205,7 +15606,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -14205,7 +15606,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
14205 arg_val = create_const_runtime(casted_arg->value.type);15606 arg_val = create_const_runtime(casted_arg->value.type);
14206 }15607 }
14207 if (arg_part_of_generic_id) {15608 if (arg_part_of_generic_id) {
14208 generic_id->params[generic_id->param_count] = *arg_val;15609 copy_const_val(&generic_id->params[generic_id->param_count], arg_val, true);
14209 generic_id->param_count += 1;15610 generic_id->param_count += 1;
14210 }15611 }
1421115612
...@@ -14376,7 +15777,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -14376,7 +15777,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
14376 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));15777 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
14377 return ira->codegen->invalid_instruction;15778 return ira->codegen->invalid_instruction;
14378 }15779 }
14379 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {15780 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar ||
15781 ptr->value.data.x_ptr.mut == ConstPtrMutInfer)
15782 {
14380 if (instr_is_comptime(value)) {15783 if (instr_is_comptime(value)) {
14381 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);15784 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
14382 if (dest_val == nullptr)15785 if (dest_val == nullptr)
...@@ -14390,18 +15793,24 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -14390,18 +15793,24 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
14390 // ConstPtrMutComptimeVar, thus defeating the logic below.15793 // ConstPtrMutComptimeVar, thus defeating the logic below.
14391 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;15794 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
14392 copy_const_val(dest_val, &value->value, same_global_refs);15795 copy_const_val(dest_val, &value->value, same_global_refs);
14393 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {15796 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar &&
15797 !ira->new_irb.current_basic_block->must_be_comptime_source_instr)
15798 {
14394 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;15799 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
14395 }15800 }
14396 return ir_const_void(ira, source_instr);15801 return ir_const_void(ira, source_instr);
14397 }15802 }
14398 }15803 }
14399 ir_add_error(ira, source_instr,15804 if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
14400 buf_sprintf("cannot store runtime value in compile time variable"));15805 ptr->value.special = ConstValSpecialRuntime;
14401 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);15806 } else {
14402 dest_val->type = ira->codegen->builtin_types.entry_invalid;15807 ir_add_error(ira, source_instr,
15808 buf_sprintf("cannot store runtime value in compile time variable"));
15809 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
15810 dest_val->type = ira->codegen->builtin_types.entry_invalid;
1440315811
14404 return ira->codegen->invalid_instruction;15812 return ira->codegen->invalid_instruction;
15813 }
14405 }15814 }
14406 }15815 }
1440715816
...@@ -14430,7 +15839,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -14430,7 +15839,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
14430 return result;15839 return result;
14431}15840}
1443215841
14433static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,15842static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
14434 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,15843 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
14435 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)15844 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
14436{15845{
...@@ -14533,7 +15942,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14533,7 +15942,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14533 if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {15942 if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
14534 first_arg = first_arg_ptr;15943 first_arg = first_arg_ptr;
14535 } else {15944 } else {
14536 first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);15945 first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr);
14537 if (type_is_invalid(first_arg->value.type))15946 if (type_is_invalid(first_arg->value.type))
14538 return ira->codegen->invalid_instruction;15947 return ira->codegen->invalid_instruction;
14539 }15948 }
...@@ -14692,7 +16101,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14692,7 +16101,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14692 if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {16101 if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
14693 first_arg = first_arg_ptr;16102 first_arg = first_arg_ptr;
14694 } else {16103 } else {
14695 first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);16104 first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr);
14696 if (type_is_invalid(first_arg->value.type))16105 if (type_is_invalid(first_arg->value.type))
14697 return ira->codegen->invalid_instruction;16106 return ira->codegen->invalid_instruction;
14698 }16107 }
...@@ -14736,7 +16145,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14736,7 +16145,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14736 if (type_is_invalid(arg_var_ptr_inst->value.type))16145 if (type_is_invalid(arg_var_ptr_inst->value.type))
14737 return ira->codegen->invalid_instruction;16146 return ira->codegen->invalid_instruction;
1473816147
14739 IrInstruction *arg_tuple_arg = ir_get_deref(ira, arg, arg_var_ptr_inst);16148 IrInstruction *arg_tuple_arg = ir_get_deref(ira, arg, arg_var_ptr_inst, nullptr);
14740 if (type_is_invalid(arg_tuple_arg->value.type))16149 if (type_is_invalid(arg_tuple_arg->value.type))
14741 return ira->codegen->invalid_instruction;16150 return ira->codegen->invalid_instruction;
1474216151
...@@ -14785,7 +16194,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14785,7 +16194,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14785 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);16194 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);
14786 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,16195 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
14787 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);16196 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
14788 const_instruction->base.value = *align_result;16197 copy_const_val(&const_instruction->base.value, align_result, true);
1478916198
14790 uint32_t align_bytes = 0;16199 uint32_t align_bytes = 0;
14791 ir_resolve_align(ira, &const_instruction->base, &align_bytes);16200 ir_resolve_align(ira, &const_instruction->base, &align_bytes);
...@@ -14867,6 +16276,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14867,6 +16276,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14867 }16276 }
1486816277
14869 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;16278 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
16279 IrInstruction *result_loc;
16280 if (handle_is_ptr(impl_fn_type_id->return_type)) {
16281 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
16282 impl_fn_type_id->return_type, nullptr, true, true);
16283 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) ||
16284 instr_is_unreachable(result_loc)))
16285 {
16286 return result_loc;
16287 }
16288 } else {
16289 result_loc = nullptr;
16290 }
16291
14870 if (fn_type_can_fail(impl_fn_type_id)) {16292 if (fn_type_can_fail(impl_fn_type_id)) {
14871 parent_fn_entry->calls_or_awaits_errorable_fn = true;16293 parent_fn_entry->calls_or_awaits_errorable_fn = true;
14872 }16294 }
...@@ -14875,18 +16297,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14875,18 +16297,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14875 if (call_instruction->is_async) {16297 if (call_instruction->is_async) {
14876 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,16298 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
14877 fn_ref, casted_args, impl_param_count, async_allocator_inst);16299 fn_ref, casted_args, impl_param_count, async_allocator_inst);
14878 ir_add_alloca(ira, result, result->value.type);
14879 return ir_finish_anal(ira, result);16300 return ir_finish_anal(ira, result);
14880 }16301 }
1488116302
14882 assert(async_allocator_inst == nullptr);16303 assert(async_allocator_inst == nullptr);
14883 IrInstruction *new_call_instruction = ir_build_call(&ira->new_irb,16304 IrInstruction *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,
14884 call_instruction->base.scope, call_instruction->base.source_node,16305 impl_fn, nullptr, impl_param_count, casted_args, fn_inline,
14885 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,16306 call_instruction->is_async, nullptr, casted_new_stack, result_loc,
14886 call_instruction->is_async, nullptr, casted_new_stack);16307 impl_fn_type_id->return_type);
14887 new_call_instruction->value.type = impl_fn_type_id->return_type;
14888
14889 ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type);
1489016308
14891 return ir_finish_anal(ira, new_call_instruction);16309 return ir_finish_anal(ira, new_call_instruction);
14892 }16310 }
...@@ -14914,7 +16332,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14914,7 +16332,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14914 {16332 {
14915 first_arg = first_arg_ptr;16333 first_arg = first_arg_ptr;
14916 } else {16334 } else {
14917 first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);16335 first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr);
14918 if (type_is_invalid(first_arg->value.type))16336 if (type_is_invalid(first_arg->value.type))
14919 return ira->codegen->invalid_instruction;16337 return ira->codegen->invalid_instruction;
14920 }16338 }
...@@ -14971,7 +16389,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14971,7 +16389,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1497116389
14972 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,16390 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,
14973 casted_args, call_param_count, async_allocator_inst);16391 casted_args, call_param_count, async_allocator_inst);
14974 ir_add_alloca(ira, result, result->value.type);
14975 return ir_finish_anal(ira, result);16392 return ir_finish_anal(ira, result);
14976 }16393 }
1497716394
...@@ -14981,15 +16398,24 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14981,15 +16398,24 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14981 return ira->codegen->invalid_instruction;16398 return ira->codegen->invalid_instruction;
14982 }16399 }
1498316400
14984 IrInstruction *new_call_instruction = ir_build_call(&ira->new_irb,16401 IrInstruction *result_loc;
14985 call_instruction->base.scope, call_instruction->base.source_node,16402 if (handle_is_ptr(return_type)) {
14986 fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr, casted_new_stack);16403 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
14987 new_call_instruction->value.type = return_type;16404 return_type, nullptr, true, true);
14988 ir_add_alloca(ira, new_call_instruction, return_type);16405 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
16406 return result_loc;
16407 }
16408 } else {
16409 result_loc = nullptr;
16410 }
16411
16412 IrInstruction *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,
16413 call_param_count, casted_args, fn_inline, false, nullptr, casted_new_stack,
16414 result_loc, return_type);
14989 return ir_finish_anal(ira, new_call_instruction);16415 return ir_finish_anal(ira, new_call_instruction);
14990}16416}
1499116417
14992static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) {16418static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) {
14993 IrInstruction *fn_ref = call_instruction->fn_ref->child;16419 IrInstruction *fn_ref = call_instruction->fn_ref->child;
14994 if (type_is_invalid(fn_ref->value.type))16420 if (type_is_invalid(fn_ref->value.type))
14995 return ira->codegen->invalid_instruction;16421 return ira->codegen->invalid_instruction;
...@@ -15013,7 +16439,8 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC...@@ -15013,7 +16439,8 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
1501316439
15014 IrInstruction *arg = call_instruction->args[0]->child;16440 IrInstruction *arg = call_instruction->args[0]->child;
1501516441
15016 IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg);16442 IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg,
16443 call_instruction->result_loc);
15017 if (type_is_invalid(cast_instruction->value.type))16444 if (type_is_invalid(cast_instruction->value.type))
15018 return ira->codegen->invalid_instruction;16445 return ira->codegen->invalid_instruction;
15019 return ir_finish_anal(ira, cast_instruction);16446 return ir_finish_anal(ira, cast_instruction);
...@@ -15066,7 +16493,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -15066,7 +16493,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1506616493
15067 if (dst_size <= src_size) {16494 if (dst_size <= src_size) {
15068 if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {16495 if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
15069 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);16496 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);
15070 return ErrorNone;16497 return ErrorNone;
15071 }16498 }
15072 Buf buf = BUF_INIT;16499 Buf buf = BUF_INIT;
...@@ -15315,7 +16742,7 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction...@@ -15315,7 +16742,7 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction
15315 return ira->codegen->invalid_instruction;16742 return ira->codegen->invalid_instruction;
15316 }16743 }
1531716744
15318 IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr);16745 IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr, instruction->result_loc);
15319 if (result == ira->codegen->invalid_instruction)16746 if (result == ira->codegen->invalid_instruction)
15320 return ira->codegen->invalid_instruction;16747 return ira->codegen->invalid_instruction;
1532116748
...@@ -15334,6 +16761,19 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction...@@ -15334,6 +16761,19 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction
15334 zig_unreachable();16761 zig_unreachable();
15335}16762}
1533616763
16764static void ir_push_resume(IrAnalyze *ira, IrSuspendPosition pos) {
16765 IrBasicBlock *old_bb = ira->old_irb.exec->basic_block_list.at(pos.basic_block_index);
16766 if (old_bb->in_resume_stack) return;
16767 ira->resume_stack.append(pos);
16768 old_bb->in_resume_stack = true;
16769}
16770
16771static void ir_push_resume_block(IrAnalyze *ira, IrBasicBlock *old_bb) {
16772 if (ira->resume_stack.length != 0) {
16773 ir_push_resume(ira, {old_bb->index, 0});
16774 }
16775}
16776
15337static IrInstruction *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {16777static IrInstruction *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
15338 IrBasicBlock *old_dest_block = br_instruction->dest_block;16778 IrBasicBlock *old_dest_block = br_instruction->dest_block;
1533916779
...@@ -15341,13 +16781,15 @@ static IrInstruction *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr...@@ -15341,13 +16781,15 @@ static IrInstruction *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr
15341 if (!ir_resolve_comptime(ira, br_instruction->is_comptime->child, &is_comptime))16781 if (!ir_resolve_comptime(ira, br_instruction->is_comptime->child, &is_comptime))
15342 return ir_unreach_error(ira);16782 return ir_unreach_error(ira);
1534316783
15344 if (is_comptime || old_dest_block->ref_count == 1)16784 if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr))
15345 return ir_inline_bb(ira, &br_instruction->base, old_dest_block);16785 return ir_inline_bb(ira, &br_instruction->base, old_dest_block);
1534616786
15347 IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, old_dest_block, &br_instruction->base);16787 IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, old_dest_block, &br_instruction->base);
15348 if (new_bb == nullptr)16788 if (new_bb == nullptr)
15349 return ir_unreach_error(ira);16789 return ir_unreach_error(ira);
1535016790
16791 ir_push_resume_block(ira, old_dest_block);
16792
15351 IrInstruction *result = ir_build_br(&ira->new_irb,16793 IrInstruction *result = ir_build_br(&ira->new_irb,
15352 br_instruction->base.scope, br_instruction->base.source_node, new_bb, nullptr);16794 br_instruction->base.scope, br_instruction->base.source_node, new_bb, nullptr);
15353 result->value.type = ira->codegen->builtin_types.entry_unreachable;16795 result->value.type = ira->codegen->builtin_types.entry_unreachable;
...@@ -15376,13 +16818,15 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi...@@ -15376,13 +16818,15 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
15376 IrBasicBlock *old_dest_block = cond_is_true ?16818 IrBasicBlock *old_dest_block = cond_is_true ?
15377 cond_br_instruction->then_block : cond_br_instruction->else_block;16819 cond_br_instruction->then_block : cond_br_instruction->else_block;
1537816820
15379 if (is_comptime || old_dest_block->ref_count == 1)16821 if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr))
15380 return ir_inline_bb(ira, &cond_br_instruction->base, old_dest_block);16822 return ir_inline_bb(ira, &cond_br_instruction->base, old_dest_block);
1538116823
15382 IrBasicBlock *new_dest_block = ir_get_new_bb_runtime(ira, old_dest_block, &cond_br_instruction->base);16824 IrBasicBlock *new_dest_block = ir_get_new_bb_runtime(ira, old_dest_block, &cond_br_instruction->base);
15383 if (new_dest_block == nullptr)16825 if (new_dest_block == nullptr)
15384 return ir_unreach_error(ira);16826 return ir_unreach_error(ira);
1538516827
16828 ir_push_resume_block(ira, old_dest_block);
16829
15386 IrInstruction *result = ir_build_br(&ira->new_irb,16830 IrInstruction *result = ir_build_br(&ira->new_irb,
15387 cond_br_instruction->base.scope, cond_br_instruction->base.source_node, new_dest_block, nullptr);16831 cond_br_instruction->base.scope, cond_br_instruction->base.source_node, new_dest_block, nullptr);
15388 result->value.type = ira->codegen->builtin_types.entry_unreachable;16832 result->value.type = ira->codegen->builtin_types.entry_unreachable;
...@@ -15398,6 +16842,9 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi...@@ -15398,6 +16842,9 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
15398 if (new_else_block == nullptr)16842 if (new_else_block == nullptr)
15399 return ir_unreach_error(ira);16843 return ir_unreach_error(ira);
1540016844
16845 ir_push_resume_block(ira, cond_br_instruction->else_block);
16846 ir_push_resume_block(ira, cond_br_instruction->then_block);
16847
15401 IrInstruction *result = ir_build_cond_br(&ira->new_irb,16848 IrInstruction *result = ir_build_cond_br(&ira->new_irb,
15402 cond_br_instruction->base.scope, cond_br_instruction->base.source_node,16849 cond_br_instruction->base.scope, cond_br_instruction->base.source_node,
15403 casted_condition, new_then_block, new_else_block, nullptr);16850 casted_condition, new_then_block, new_else_block, nullptr);
...@@ -15436,6 +16883,80 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -15436,6 +16883,80 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
15436 zig_unreachable();16883 zig_unreachable();
15437 }16884 }
1543816885
16886 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
16887 if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming &&
16888 peer_parent->peers.length >= 2)
16889 {
16890 if (peer_parent->resolved_type == nullptr) {
16891 IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length);
16892 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
16893 ResultLocPeer *this_peer = peer_parent->peers.at(i);
16894
16895 IrInstruction *gen_instruction = this_peer->base.gen_instruction;
16896 if (gen_instruction == nullptr) {
16897 // unreachable instructions will cause implicit_elem_type to be null
16898 if (this_peer->base.implicit_elem_type == nullptr) {
16899 instructions[i] = ir_const_unreachable(ira, this_peer->base.source_instruction);
16900 } else {
16901 instructions[i] = ir_const(ira, this_peer->base.source_instruction,
16902 this_peer->base.implicit_elem_type);
16903 instructions[i]->value.special = ConstValSpecialRuntime;
16904 }
16905 } else {
16906 instructions[i] = gen_instruction;
16907 }
16908
16909 }
16910 ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base, peer_parent->parent);
16911 peer_parent->resolved_type = ir_resolve_peer_types(ira,
16912 peer_parent->base.source_instruction->source_node, expected_type, instructions,
16913 peer_parent->peers.length);
16914
16915 // the logic below assumes there are no instructions in the new current basic block yet
16916 ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base);
16917
16918 // In case resolving the parent activates a suspend, do it now
16919 IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent,
16920 peer_parent->resolved_type, nullptr, false, false);
16921 if (parent_result_loc != nullptr &&
16922 (type_is_invalid(parent_result_loc->value.type) || instr_is_unreachable(parent_result_loc)))
16923 {
16924 return parent_result_loc;
16925 }
16926 // If the above code generated any instructions in the current basic block, we need
16927 // to move them to the peer parent predecessor.
16928 ZigList<IrInstruction *> instrs_to_move = {};
16929 while (ira->new_irb.current_basic_block->instruction_list.length != 0) {
16930 instrs_to_move.append(ira->new_irb.current_basic_block->instruction_list.pop());
16931 }
16932 if (instrs_to_move.length != 0) {
16933 IrBasicBlock *predecessor = peer_parent->base.source_instruction->child->owner_bb;
16934 IrInstruction *branch_instruction = predecessor->instruction_list.pop();
16935 ir_assert(branch_instruction->value.type->id == ZigTypeIdUnreachable, &phi_instruction->base);
16936 while (instrs_to_move.length != 0) {
16937 predecessor->instruction_list.append(instrs_to_move.pop());
16938 }
16939 predecessor->instruction_list.append(branch_instruction);
16940 }
16941 }
16942
16943 IrSuspendPosition suspend_pos;
16944 ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos);
16945 ir_push_resume(ira, suspend_pos);
16946
16947 for (size_t i = 0; i < peer_parent->peers.length; i += 1) {
16948 ResultLocPeer *opposite_peer = peer_parent->peers.at(peer_parent->peers.length - i - 1);
16949 if (opposite_peer->base.implicit_elem_type != nullptr &&
16950 opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable)
16951 {
16952 ir_push_resume(ira, opposite_peer->suspend_pos);
16953 }
16954 }
16955
16956 peer_parent->done_resuming = true;
16957 return ira_resume(ira);
16958 }
16959
15439 ZigList<IrBasicBlock*> new_incoming_blocks = {0};16960 ZigList<IrBasicBlock*> new_incoming_blocks = {0};
15440 ZigList<IrInstruction*> new_incoming_values = {0};16961 ZigList<IrInstruction*> new_incoming_values = {0};
1544116962
...@@ -15508,7 +17029,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -15508,7 +17029,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
15508 IrInstruction *branch_instruction = predecessor->instruction_list.pop();17029 IrInstruction *branch_instruction = predecessor->instruction_list.pop();
15509 ir_set_cursor_at_end(&ira->new_irb, predecessor);17030 ir_set_cursor_at_end(&ira->new_irb, predecessor);
15510 IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type);17031 IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type);
15511 if (casted_value == ira->codegen->invalid_instruction) {17032 if (type_is_invalid(casted_value->value.type)) {
15512 return ira->codegen->invalid_instruction;17033 return ira->codegen->invalid_instruction;
15513 }17034 }
15514 new_incoming_values.items[i] = casted_value;17035 new_incoming_values.items[i] = casted_value;
...@@ -15524,7 +17045,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -15524,7 +17045,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1552417045
15525 IrInstruction *result = ir_build_phi(&ira->new_irb,17046 IrInstruction *result = ir_build_phi(&ira->new_irb,
15526 phi_instruction->base.scope, phi_instruction->base.source_node,17047 phi_instruction->base.scope, phi_instruction->base.source_node,
15527 new_incoming_blocks.length, new_incoming_blocks.items, new_incoming_values.items);17048 new_incoming_blocks.length, new_incoming_blocks.items, new_incoming_values.items, nullptr);
15528 result->value.type = resolved_type;17049 result->value.type = resolved_type;
1552917050
15530 if (all_stack_ptrs) {17051 if (all_stack_ptrs) {
...@@ -15742,6 +17263,52 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -15742,6 +17263,52 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
15742 if (array_ptr_val == nullptr)17263 if (array_ptr_val == nullptr)
15743 return ira->codegen->invalid_instruction;17264 return ira->codegen->invalid_instruction;
1574417265
17266 if (array_ptr_val->special == ConstValSpecialUndef && elem_ptr_instruction->init_array_type != nullptr) {
17267 if (array_type->id == ZigTypeIdArray) {
17268 array_ptr_val->data.x_array.special = ConstArraySpecialNone;
17269 array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len);
17270 array_ptr_val->special = ConstValSpecialStatic;
17271 for (size_t i = 0; i < array_type->data.array.len; i += 1) {
17272 ConstExprValue *elem_val = &array_ptr_val->data.x_array.data.s_none.elements[i];
17273 elem_val->special = ConstValSpecialUndef;
17274 elem_val->type = array_type->data.array.child_type;
17275 elem_val->parent.id = ConstParentIdArray;
17276 elem_val->parent.data.p_array.array_val = array_ptr_val;
17277 elem_val->parent.data.p_array.elem_index = i;
17278 }
17279 } else if (is_slice(array_type)) {
17280 ZigType *actual_array_type = ir_resolve_type(ira, elem_ptr_instruction->init_array_type->child);
17281 if (type_is_invalid(actual_array_type))
17282 return ira->codegen->invalid_instruction;
17283 if (actual_array_type->id != ZigTypeIdArray) {
17284 ir_add_error(ira, elem_ptr_instruction->init_array_type,
17285 buf_sprintf("expected array type or [_], found slice"));
17286 return ira->codegen->invalid_instruction;
17287 }
17288
17289 ConstExprValue *array_init_val = create_const_vals(1);
17290 array_init_val->special = ConstValSpecialStatic;
17291 array_init_val->type = actual_array_type;
17292 array_init_val->data.x_array.special = ConstArraySpecialNone;
17293 array_init_val->data.x_array.data.s_none.elements = create_const_vals(actual_array_type->data.array.len);
17294 array_init_val->special = ConstValSpecialStatic;
17295 for (size_t i = 0; i < actual_array_type->data.array.len; i += 1) {
17296 ConstExprValue *elem_val = &array_init_val->data.x_array.data.s_none.elements[i];
17297 elem_val->special = ConstValSpecialUndef;
17298 elem_val->type = actual_array_type->data.array.child_type;
17299 elem_val->parent.id = ConstParentIdArray;
17300 elem_val->parent.data.p_array.array_val = array_init_val;
17301 elem_val->parent.data.p_array.elem_index = i;
17302 }
17303
17304 init_const_slice(ira->codegen, array_ptr_val, array_init_val, 0, actual_array_type->data.array.len,
17305 false);
17306 array_ptr_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = ConstPtrMutInfer;
17307 } else {
17308 zig_unreachable();
17309 }
17310 }
17311
15745 if (array_ptr_val->special != ConstValSpecialRuntime &&17312 if (array_ptr_val->special != ConstValSpecialRuntime &&
15746 (array_type->id != ZigTypeIdPointer ||17313 (array_type->id != ZigTypeIdPointer ||
15747 array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))17314 array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
...@@ -15807,8 +17374,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -15807,8 +17374,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
15807 } else if (is_slice(array_type)) {17374 } else if (is_slice(array_type)) {
15808 ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];17375 ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];
15809 if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {17376 if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
15810 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,17377 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
15811 array_ptr, casted_elem_index, false, elem_ptr_instruction->ptr_len);17378 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, false,
17379 elem_ptr_instruction->ptr_len, nullptr);
15812 result->value.type = return_type;17380 result->value.type = return_type;
15813 return result;17381 return result;
15814 }17382 }
...@@ -15861,7 +17429,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -15861,7 +17429,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
15861 }17429 }
15862 return result;17430 return result;
15863 } else if (array_type->id == ZigTypeIdArray) {17431 } else if (array_type->id == ZigTypeIdArray) {
15864 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);17432 IrInstruction *result;
17433 if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
17434 result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
17435 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index,
17436 false, elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type);
17437 result->value.type = return_type;
17438 result->value.special = ConstValSpecialStatic;
17439 } else {
17440 result = ir_const(ira, &elem_ptr_instruction->base, return_type);
17441 }
15865 ConstExprValue *out_val = &result->value;17442 ConstExprValue *out_val = &result->value;
15866 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;17443 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
15867 out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;17444 out_val->data.x_ptr.mut = orig_array_ptr_val->data.x_ptr.mut;
...@@ -15873,7 +17450,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -15873,7 +17450,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
15873 }17450 }
15874 }17451 }
15875 }17452 }
15876
15877 } else {17453 } else {
15878 // runtime known element index17454 // runtime known element index
15879 switch (type_requires_comptime(ira->codegen, return_type)) {17455 switch (type_requires_comptime(ira->codegen, return_type)) {
...@@ -15899,8 +17475,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -15899,8 +17475,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
15899 }17475 }
15900 }17476 }
1590117477
15902 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node,17478 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
15903 array_ptr, casted_elem_index, safety_check_on, elem_ptr_instruction->ptr_len);17479 elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on,
17480 elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type);
15904 result->value.type = return_type;17481 result->value.type = return_type;
15905 return result;17482 return result;
15906}17483}
...@@ -15945,8 +17522,80 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,...@@ -15945,8 +17522,80 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
15945 return ira->codegen->invalid_instruction;17522 return ira->codegen->invalid_instruction;
15946}17523}
1594717524
17525static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,
17526 TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)
17527{
17528 switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
17529 case OnePossibleValueInvalid:
17530 return ira->codegen->invalid_instruction;
17531 case OnePossibleValueYes: {
17532 IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
17533 return ir_get_ref(ira, source_instr, elem, false, false);
17534 }
17535 case OnePossibleValueNo:
17536 break;
17537 }
17538 assert(struct_ptr->value.type->id == ZigTypeIdPointer);
17539 bool is_packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
17540 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
17541 uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;
17542 uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;
17543 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
17544 get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
17545 bool is_const = struct_ptr->value.type->data.pointer.is_const;
17546 bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;
17547 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
17548 is_const, is_volatile, PtrLenSingle, align_bytes,
17549 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
17550 (uint32_t)host_int_bytes_for_result_type, false);
17551 if (instr_is_comptime(struct_ptr)) {
17552 ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad);
17553 if (!ptr_val)
17554 return ira->codegen->invalid_instruction;
17555
17556 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
17557 ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
17558 if (struct_val == nullptr)
17559 return ira->codegen->invalid_instruction;
17560 if (type_is_invalid(struct_val->type))
17561 return ira->codegen->invalid_instruction;
17562 if (struct_val->special == ConstValSpecialUndef && initializing) {
17563 struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count);
17564 struct_val->special = ConstValSpecialStatic;
17565 for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
17566 ConstExprValue *field_val = &struct_val->data.x_struct.fields[i];
17567 field_val->special = ConstValSpecialUndef;
17568 field_val->type = struct_type->data.structure.fields[i].type_entry;
17569 field_val->parent.id = ConstParentIdStruct;
17570 field_val->parent.data.p_struct.struct_val = struct_val;
17571 field_val->parent.data.p_struct.field_index = i;
17572 }
17573 }
17574 IrInstruction *result;
17575 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
17576 result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope,
17577 source_instr->source_node, struct_ptr, field);
17578 result->value.type = ptr_type;
17579 result->value.special = ConstValSpecialStatic;
17580 } else {
17581 result = ir_const(ira, source_instr, ptr_type);
17582 }
17583 ConstExprValue *const_val = &result->value;
17584 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
17585 const_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
17586 const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
17587 const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
17588 return result;
17589 }
17590 }
17591 IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
17592 struct_ptr, field);
17593 result->value.type = ptr_type;
17594 return result;
17595}
17596
15948static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,17597static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
15949 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type)17598 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing)
15950{17599{
15951 Error err;17600 Error err;
1595217601
...@@ -15955,81 +17604,55 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -15955,81 +17604,55 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
15955 return ira->codegen->invalid_instruction;17604 return ira->codegen->invalid_instruction;
1595617605
15957 assert(container_ptr->value.type->id == ZigTypeIdPointer);17606 assert(container_ptr->value.type->id == ZigTypeIdPointer);
15958 bool is_const = container_ptr->value.type->data.pointer.is_const;
15959 bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
15960 if (bare_type->id == ZigTypeIdStruct) {17607 if (bare_type->id == ZigTypeIdStruct) {
15961 TypeStructField *field = find_struct_type_field(bare_type, field_name);17608 TypeStructField *field = find_struct_type_field(bare_type, field_name);
15962 if (field) {17609 if (field != nullptr) {
15963 switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {17610 return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing);
15964 case OnePossibleValueInvalid:
15965 return ira->codegen->invalid_instruction;
15966 case OnePossibleValueYes: {
15967 IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
15968 return ir_get_ref(ira, source_instr, elem, false, false);
15969 }
15970 case OnePossibleValueNo:
15971 break;
15972 }
15973 bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
15974 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
15975 uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;
15976 uint32_t ptr_host_int_bytes = container_ptr->value.type->data.pointer.host_int_bytes;
15977 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
15978 get_host_int_bytes(ira->codegen, bare_type, field) : ptr_host_int_bytes;
15979 if (instr_is_comptime(container_ptr)) {
15980 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
15981 if (!ptr_val)
15982 return ira->codegen->invalid_instruction;
15983
15984 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
15985 ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
15986 if (struct_val == nullptr)
15987 return ira->codegen->invalid_instruction;
15988 if (type_is_invalid(struct_val->type))
15989 return ira->codegen->invalid_instruction;
15990 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
15991 is_const, is_volatile, PtrLenSingle, align_bytes,
15992 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
15993 (uint32_t)host_int_bytes_for_result_type, false);
15994 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
15995 ConstExprValue *const_val = &result->value;
15996 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
15997 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
15998 const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
15999 const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
16000 return result;
16001 }
16002 }
16003 IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
16004 container_ptr, field);
16005 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
16006 PtrLenSingle,
16007 align_bytes,
16008 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
16009 host_int_bytes_for_result_type, false);
16010 return result;
16011 } else {17611 } else {
16012 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,17612 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
16013 source_instr, container_ptr, container_type);17613 source_instr, container_ptr, container_type);
16014 }17614 }
16015 } else if (bare_type->id == ZigTypeIdEnum) {17615 }
17616
17617 if (bare_type->id == ZigTypeIdEnum) {
16016 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,17618 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
16017 source_instr, container_ptr, container_type);17619 source_instr, container_ptr, container_type);
16018 } else if (bare_type->id == ZigTypeIdUnion) {17620 }
17621
17622 if (bare_type->id == ZigTypeIdUnion) {
17623 bool is_const = container_ptr->value.type->data.pointer.is_const;
17624 bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
17625
16019 TypeUnionField *field = find_union_type_field(bare_type, field_name);17626 TypeUnionField *field = find_union_type_field(bare_type, field_name);
16020 if (field) {17627 if (field == nullptr) {
16021 if (instr_is_comptime(container_ptr)) {17628 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
16022 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);17629 source_instr, container_ptr, container_type);
16023 if (!ptr_val)17630 }
17631 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
17632 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
17633 if (instr_is_comptime(container_ptr)) {
17634 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
17635 if (!ptr_val)
17636 return ira->codegen->invalid_instruction;
17637
17638 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
17639 ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
17640 if (union_val == nullptr)
17641 return ira->codegen->invalid_instruction;
17642 if (type_is_invalid(union_val->type))
16024 return ira->codegen->invalid_instruction;17643 return ira->codegen->invalid_instruction;
1602517644
16026 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {17645 if (initializing) {
16027 ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);17646 ConstExprValue *payload_val = create_const_vals(1);
16028 if (union_val == nullptr)17647 payload_val->special = ConstValSpecialUndef;
16029 return ira->codegen->invalid_instruction;17648 payload_val->type = field->type_entry;
16030 if (type_is_invalid(union_val->type))17649 payload_val->parent.id = ConstParentIdUnion;
16031 return ira->codegen->invalid_instruction;17650 payload_val->parent.data.p_union.union_val = union_val;
1603217651
17652 union_val->special = ConstValSpecialStatic;
17653 bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value);
17654 union_val->data.x_union.payload = payload_val;
17655 } else {
16033 TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag);17656 TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag);
16034 if (actual_field == nullptr)17657 if (actual_field == nullptr)
16035 zig_unreachable();17658 zig_unreachable();
...@@ -16040,33 +17663,35 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -16040,33 +17663,35 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
16040 buf_ptr(actual_field->name)));17663 buf_ptr(actual_field->name)));
16041 return ira->codegen->invalid_instruction;17664 return ira->codegen->invalid_instruction;
16042 }17665 }
17666 }
1604317667
16044 ConstExprValue *payload_val = union_val->data.x_union.payload;17668 ConstExprValue *payload_val = union_val->data.x_union.payload;
1604517669
16046 ZigType *field_type = field->type_entry;
16047 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
16048 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
1604917670
16050 IrInstruction *result = ir_const(ira, source_instr, ptr_type);17671 IrInstruction *result;
16051 ConstExprValue *const_val = &result->value;17672 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
16052 const_val->data.x_ptr.special = ConstPtrSpecialRef;17673 result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
16053 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;17674 source_instr->source_node, container_ptr, field, true, initializing);
16054 const_val->data.x_ptr.data.ref.pointee = payload_val;17675 result->value.type = ptr_type;
16055 return result;17676 result->value.special = ConstValSpecialStatic;
17677 } else {
17678 result = ir_const(ira, source_instr, ptr_type);
16056 }17679 }
17680 ConstExprValue *const_val = &result->value;
17681 const_val->data.x_ptr.special = ConstPtrSpecialRef;
17682 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
17683 const_val->data.x_ptr.data.ref.pointee = payload_val;
17684 return result;
16057 }17685 }
16058
16059 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
16060 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
16061 PtrLenSingle, 0, 0, 0, false);
16062 return result;
16063 } else {
16064 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
16065 source_instr, container_ptr, container_type);
16066 }17686 }
16067 } else {17687
16068 zig_unreachable();17688 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
17689 source_instr->source_node, container_ptr, field, true, initializing);
17690 result->value.type = ptr_type;
17691 return result;
16069 }17692 }
17693
17694 zig_unreachable();
16070}17695}
1607117696
16072static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {17697static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {
...@@ -16104,6 +17729,11 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,...@@ -16104,6 +17729,11 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,
16104 link_lib->symbols.append(symbol_name);17729 link_lib->symbols.append(symbol_name);
16105}17730}
1610617731
17732static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) {
17733 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));
17734 emit_error_notes_for_ref_stack(ira->codegen, msg);
17735 return ira->codegen->invalid_instruction;
17736}
1610717737
16108static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {17738static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
16109 resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node);17739 resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node);
...@@ -16118,6 +17748,9 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_...@@ -16118,6 +17748,9 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
16118 {17748 {
16119 TldVar *tld_var = (TldVar *)tld;17749 TldVar *tld_var = (TldVar *)tld;
16120 ZigVar *var = tld_var->var;17750 ZigVar *var = tld_var->var;
17751 if (var == nullptr) {
17752 return ir_error_dependency_loop(ira, source_instruction);
17753 }
16121 if (tld_var->extern_lib_name != nullptr) {17754 if (tld_var->extern_lib_name != nullptr) {
16122 add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, source_instruction->source_node);17755 add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, source_instruction->source_node);
16123 }17756 }
...@@ -16133,23 +17766,13 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_...@@ -16133,23 +17766,13 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
16133 if (type_is_invalid(fn_entry->type_entry))17766 if (type_is_invalid(fn_entry->type_entry))
16134 return ira->codegen->invalid_instruction;17767 return ira->codegen->invalid_instruction;
1613517768
16136 // TODO instead of allocating this every time, put it in the tld value and we can reference
16137 // the same one every time
16138 ConstExprValue *const_val = create_const_vals(1);
16139 const_val->special = ConstValSpecialStatic;
16140 const_val->type = fn_entry->type_entry;
16141 const_val->data.x_ptr.data.fn.fn_entry = fn_entry;
16142 const_val->data.x_ptr.special = ConstPtrSpecialFunction;
16143 const_val->data.x_ptr.mut = ConstPtrMutComptimeConst;
16144
16145 if (tld_fn->extern_lib_name != nullptr) {17769 if (tld_fn->extern_lib_name != nullptr) {
16146 add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, source_instruction->source_node);17770 add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, source_instruction->source_node);
16147 }17771 }
1614817772
16149 bool ptr_is_const = true;17773 IrInstruction *fn_inst = ir_create_const_fn(&ira->new_irb, source_instruction->scope,
16150 bool ptr_is_volatile = false;17774 source_instruction->source_node, fn_entry);
16151 return ir_get_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,17775 return ir_get_ref(ira, source_instruction, fn_inst, true, false);
16152 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
16153 }17776 }
16154 }17777 }
16155 zig_unreachable();17778 zig_unreachable();
...@@ -16191,14 +17814,14 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -16191,14 +17814,14 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
16191 assert(container_ptr->value.type->id == ZigTypeIdPointer);17814 assert(container_ptr->value.type->id == ZigTypeIdPointer);
16192 if (container_type->id == ZigTypeIdPointer) {17815 if (container_type->id == ZigTypeIdPointer) {
16193 ZigType *bare_type = container_ref_type(container_type);17816 ZigType *bare_type = container_ref_type(container_type);
16194 IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr);17817 IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr, nullptr);
16195 IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type);17818 IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type, field_ptr_instruction->initializing);
16196 return result;17819 return result;
16197 } else {17820 } else {
16198 IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type);17821 IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type, field_ptr_instruction->initializing);
16199 return result;17822 return result;
16200 }17823 }
16201 } else if (is_array_ref(container_type)) {17824 } else if (is_array_ref(container_type) && !field_ptr_instruction->initializing) {
16202 if (buf_eql_str(field_name, "len")) {17825 if (buf_eql_str(field_name, "len")) {
16203 ConstExprValue *len_val = create_const_vals(1);17826 ConstExprValue *len_val = create_const_vals(1);
16204 if (container_type->id == ZigTypeIdPointer) {17827 if (container_type->id == ZigTypeIdPointer) {
...@@ -16513,6 +18136,10 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -16513,6 +18136,10 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
16513 buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name)));18136 buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name)));
16514 return ira->codegen->invalid_instruction;18137 return ira->codegen->invalid_instruction;
16515 }18138 }
18139 } else if (field_ptr_instruction->initializing) {
18140 ir_add_error(ira, &field_ptr_instruction->base,
18141 buf_sprintf("type '%s' does not support struct initialization syntax", buf_ptr(&container_type->name)));
18142 return ira->codegen->invalid_instruction;
16516 } else {18143 } else {
16517 ir_add_error_node(ira, field_ptr_instruction->base.source_node,18144 ir_add_error_node(ira, field_ptr_instruction->base.source_node,
16518 buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name)));18145 buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name)));
...@@ -16536,7 +18163,7 @@ static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruct...@@ -16536,7 +18163,7 @@ static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruct
16536 IrInstruction *ptr = instruction->ptr->child;18163 IrInstruction *ptr = instruction->ptr->child;
16537 if (type_is_invalid(ptr->value.type))18164 if (type_is_invalid(ptr->value.type))
16538 return ira->codegen->invalid_instruction;18165 return ira->codegen->invalid_instruction;
16539 return ir_get_deref(ira, &instruction->base, ptr);18166 return ir_get_deref(ira, &instruction->base, ptr, nullptr);
16540}18167}
1654118168
16542static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {18169static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
...@@ -16547,64 +18174,6 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio...@@ -16547,64 +18174,6 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
16547 return ir_const_type(ira, &typeof_instruction->base, type_entry);18174 return ir_const_type(ira, &typeof_instruction->base, type_entry);
16548}18175}
1654918176
16550static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
16551 IrInstructionToPtrType *to_ptr_type_instruction)
16552{
16553 Error err;
16554 IrInstruction *ptr_ptr = to_ptr_type_instruction->ptr->child;
16555 if (type_is_invalid(ptr_ptr->value.type))
16556 return ira->codegen->invalid_instruction;
16557
16558 ZigType *ptr_ptr_type = ptr_ptr->value.type;
16559 assert(ptr_ptr_type->id == ZigTypeIdPointer);
16560 ZigType *type_entry = ptr_ptr_type->data.pointer.child_type;
16561
16562 ZigType *ptr_type;
16563 if (type_entry->id == ZigTypeIdArray) {
16564 ptr_type = get_pointer_to_type(ira->codegen, type_entry->data.array.child_type, ptr_ptr_type->data.pointer.is_const);
16565 } else if (is_array_ref(type_entry)) {
16566 ptr_type = get_pointer_to_type(ira->codegen,
16567 type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);
16568 } else if (is_slice(type_entry)) {
16569 ZigType *slice_ptr_type = type_entry->data.structure.fields[0].type_entry;
16570 ptr_type = adjust_ptr_len(ira->codegen, slice_ptr_type, PtrLenSingle);
16571 // If the pointer is over-aligned, we may have to reduce it based on the alignment of the element type.
16572 if (slice_ptr_type->data.pointer.explicit_alignment != 0) {
16573 ZigType *elem_type = slice_ptr_type->data.pointer.child_type;
16574 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown)))
16575 return ira->codegen->invalid_instruction;
16576 uint32_t elem_align = get_abi_alignment(ira->codegen, elem_type);
16577 uint32_t reduced_align = min(elem_align, slice_ptr_type->data.pointer.explicit_alignment);
16578 ptr_type = adjust_ptr_align(ira->codegen, ptr_type, reduced_align);
16579 }
16580 } else if (type_entry->id == ZigTypeIdArgTuple) {
16581 zig_panic("TODO for loop on var args");
16582 } else {
16583 ir_add_error_node(ira, to_ptr_type_instruction->base.source_node,
16584 buf_sprintf("expected array type, found '%s'", buf_ptr(&type_entry->name)));
16585 return ira->codegen->invalid_instruction;
16586 }
16587
16588 return ir_const_type(ira, &to_ptr_type_instruction->base, ptr_type);
16589}
16590
16591static IrInstruction *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
16592 IrInstructionPtrTypeChild *ptr_type_child_instruction)
16593{
16594 IrInstruction *type_value = ptr_type_child_instruction->value->child;
16595 ZigType *type_entry = ir_resolve_type(ira, type_value);
16596 if (type_is_invalid(type_entry))
16597 return ira->codegen->invalid_instruction;
16598
16599 if (type_entry->id != ZigTypeIdPointer) {
16600 ir_add_error_node(ira, ptr_type_child_instruction->base.source_node,
16601 buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name)));
16602 return ira->codegen->invalid_instruction;
16603 }
16604
16605 return ir_const_type(ira, &ptr_type_child_instruction->base, type_entry->data.pointer.child_type);
16606}
16607
16608static IrInstruction *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSetCold *instruction) {18177static IrInstruction *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSetCold *instruction) {
16609 if (ira->new_irb.exec->is_inline) {18178 if (ira->new_irb.exec->is_inline) {
16610 // ignore setCold when running functions at compile time18179 // ignore setCold when running functions at compile time
...@@ -17034,7 +18603,7 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns...@@ -17034,7 +18603,7 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
17034}18603}
1703518604
17036static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,18605static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
17037 IrInstruction *base_ptr, bool safety_check_on)18606 IrInstruction *base_ptr, bool safety_check_on, bool initializing)
17038{18607{
17039 ZigType *ptr_type = base_ptr->value.type;18608 ZigType *ptr_type = base_ptr->value.type;
17040 assert(ptr_type->id == ZigTypeIdPointer);18609 assert(ptr_type->id == ZigTypeIdPointer);
...@@ -17064,7 +18633,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr...@@ -17064,7 +18633,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
17064 }18633 }
17065 if (!safety_check_on)18634 if (!safety_check_on)
17066 return base_ptr;18635 return base_ptr;
17067 IrInstruction *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr);18636 IrInstruction *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr, nullptr);
17068 ir_build_assert_non_null(ira, source_instr, c_ptr_val);18637 ir_build_assert_non_null(ira, source_instr, c_ptr_val);
17069 return base_ptr;18638 return base_ptr;
17070 }18639 }
...@@ -17079,34 +18648,84 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr...@@ -17079,34 +18648,84 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
17079 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,18648 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
17080 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);18649 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);
1708118650
18651 bool same_comptime_repr = types_have_same_zig_comptime_repr(type_entry, child_type);
18652
17082 if (instr_is_comptime(base_ptr)) {18653 if (instr_is_comptime(base_ptr)) {
17083 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);18654 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
17084 if (!val)18655 if (!ptr_val)
17085 return ira->codegen->invalid_instruction;18656 return ira->codegen->invalid_instruction;
17086 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {18657 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
17087 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);18658 ConstExprValue *optional_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
17088 if (maybe_val == nullptr)18659 if (optional_val == nullptr)
17089 return ira->codegen->invalid_instruction;18660 return ira->codegen->invalid_instruction;
1709018661
17091 if (optional_value_is_null(maybe_val)) {18662 if (initializing && optional_val->special == ConstValSpecialUndef) {
18663 switch (type_has_one_possible_value(ira->codegen, child_type)) {
18664 case OnePossibleValueInvalid:
18665 return ira->codegen->invalid_instruction;
18666 case OnePossibleValueNo:
18667 if (!same_comptime_repr) {
18668 ConstExprValue *payload_val = create_const_vals(1);
18669 payload_val->type = child_type;
18670 payload_val->special = ConstValSpecialUndef;
18671 payload_val->parent.id = ConstParentIdOptionalPayload;
18672 payload_val->parent.data.p_optional_payload.optional_val = optional_val;
18673
18674 optional_val->data.x_optional = payload_val;
18675 optional_val->special = ConstValSpecialStatic;
18676 }
18677 break;
18678 case OnePossibleValueYes: {
18679 ConstExprValue *pointee = create_const_vals(1);
18680 pointee->special = ConstValSpecialStatic;
18681 pointee->type = child_type;
18682 pointee->parent.id = ConstParentIdOptionalPayload;
18683 pointee->parent.data.p_optional_payload.optional_val = optional_val;
18684
18685 optional_val->special = ConstValSpecialStatic;
18686 optional_val->data.x_optional = pointee;
18687 break;
18688 }
18689 }
18690 } else if (optional_value_is_null(optional_val)) {
17092 ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));18691 ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
17093 return ira->codegen->invalid_instruction;18692 return ira->codegen->invalid_instruction;
17094 }18693 }
17095 IrInstruction *result = ir_const(ira, source_instr, result_type);18694
17096 ConstExprValue *out_val = &result->value;18695 IrInstruction *result;
17097 out_val->data.x_ptr.special = ConstPtrSpecialRef;18696 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
17098 out_val->data.x_ptr.mut = val->data.x_ptr.mut;18697 result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
17099 if (types_have_same_zig_comptime_repr(type_entry, child_type)) {18698 source_instr->source_node, base_ptr, false, initializing);
17100 out_val->data.x_ptr.data.ref.pointee = maybe_val;18699 result->value.type = result_type;
18700 result->value.special = ConstValSpecialStatic;
17101 } else {18701 } else {
17102 out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;18702 result = ir_const(ira, source_instr, result_type);
18703 }
18704 ConstExprValue *result_val = &result->value;
18705 result_val->data.x_ptr.special = ConstPtrSpecialRef;
18706 result_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
18707 switch (type_has_one_possible_value(ira->codegen, child_type)) {
18708 case OnePossibleValueInvalid:
18709 return ira->codegen->invalid_instruction;
18710 case OnePossibleValueNo:
18711 if (same_comptime_repr) {
18712 result_val->data.x_ptr.data.ref.pointee = optional_val;
18713 } else {
18714 assert(optional_val->data.x_optional != nullptr);
18715 result_val->data.x_ptr.data.ref.pointee = optional_val->data.x_optional;
18716 }
18717 break;
18718 case OnePossibleValueYes:
18719 assert(optional_val->data.x_optional != nullptr);
18720 result_val->data.x_ptr.data.ref.pointee = optional_val->data.x_optional;
18721 break;
17103 }18722 }
17104 return result;18723 return result;
17105 }18724 }
17106 }18725 }
1710718726
17108 IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,18727 IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
17109 source_instr->source_node, base_ptr, safety_check_on);18728 source_instr->source_node, base_ptr, safety_check_on, initializing);
17110 result->value.type = result_type;18729 result->value.type = result_type;
17111 return result;18730 return result;
17112}18731}
...@@ -17118,7 +18737,8 @@ static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,...@@ -17118,7 +18737,8 @@ static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
17118 if (type_is_invalid(base_ptr->value.type))18737 if (type_is_invalid(base_ptr->value.type))
17119 return ira->codegen->invalid_instruction;18738 return ira->codegen->invalid_instruction;
1712018739
17121 return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on);18740 return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr,
18741 instruction->safety_check_on, false);
17122}18742}
1712318743
17124static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *instruction) {18744static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *instruction) {
...@@ -17419,7 +19039,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -17419,7 +19039,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
17419 return result;19039 return result;
17420 }19040 }
1742119041
17422 IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);19042 IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr);
17423 result->value.type = target_type;19043 result->value.type = target_type;
17424 return result;19044 return result;
17425 }19045 }
...@@ -17449,7 +19069,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -17449,7 +19069,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
17449 return result;19069 return result;
17450 }19070 }
1745119071
17452 IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);19072 IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr);
17453 union_value->value.type = target_type;19073 union_value->value.type = target_type;
1745419074
17455 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,19075 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
...@@ -17473,7 +19093,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -17473,7 +19093,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
17473 return result;19093 return result;
17474 }19094 }
1747519095
17476 IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);19096 IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr);
17477 enum_value->value.type = target_type;19097 enum_value->value.type = target_type;
17478 return enum_value;19098 return enum_value;
17479 }19099 }
...@@ -17546,7 +19166,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru...@@ -17546,7 +19166,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
17546 }19166 }
1754719167
17548 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb,19168 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb,
17549 instruction->base.scope, instruction->base.source_node, target_value_ptr, field);19169 instruction->base.scope, instruction->base.source_node, target_value_ptr, field, false, false);
17550 result->value.type = get_pointer_to_type(ira->codegen, field->type_entry,19170 result->value.type = get_pointer_to_type(ira->codegen, field->type_entry,
17551 target_value_ptr->value.type->data.pointer.is_const);19171 target_value_ptr->value.type->data.pointer.is_const);
17552 return result;19172 return result;
...@@ -17756,7 +19376,8 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe...@@ -17756,7 +19376,8 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe
17756}19376}
1775719377
17758static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,19378static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
17759 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)19379 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
19380 IrInstruction *result_loc)
17760{19381{
17761 Error err;19382 Error err;
17762 assert(container_type->id == ZigTypeIdUnion);19383 assert(container_type->id == ZigTypeIdUnion);
...@@ -17771,12 +19392,12 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -17771,12 +19392,12 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
17771 }19392 }
1777219393
17773 IrInstructionContainerInitFieldsField *field = &fields[0];19394 IrInstructionContainerInitFieldsField *field = &fields[0];
17774 IrInstruction *field_value = field->value->child;19395 IrInstruction *field_result_loc = field->result_loc->child;
17775 if (type_is_invalid(field_value->value.type))19396 if (type_is_invalid(field_result_loc->value.type))
17776 return ira->codegen->invalid_instruction;19397 return ira->codegen->invalid_instruction;
1777719398
17778 TypeUnionField *type_field = find_union_type_field(container_type, field->name);19399 TypeUnionField *type_field = find_union_type_field(container_type, field->name);
17779 if (!type_field) {19400 if (type_field == nullptr) {
17780 ir_add_error_node(ira, field->source_node,19401 ir_add_error_node(ira, field->source_node,
17781 buf_sprintf("no member named '%s' in union '%s'",19402 buf_sprintf("no member named '%s' in union '%s'",
17782 buf_ptr(field->name), buf_ptr(&container_type->name)));19403 buf_ptr(field->name), buf_ptr(&container_type->name)));
...@@ -17786,46 +19407,36 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -17786,46 +19407,36 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
17786 if (type_is_invalid(type_field->type_entry))19407 if (type_is_invalid(type_field->type_entry))
17787 return ira->codegen->invalid_instruction;19408 return ira->codegen->invalid_instruction;
1778819409
17789 IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry);19410 if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
17790 if (casted_field_value == ira->codegen->invalid_instruction)19411 if (instr_is_comptime(field_result_loc) &&
17791 return ira->codegen->invalid_instruction;19412 field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
1779219413 {
17793 if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))19414 // nothing
17794 return ira->codegen->invalid_instruction;19415 } else {
19416 result_loc->value.special = ConstValSpecialRuntime;
19417 }
19418 }
1779519419
17796 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)19420 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
17797 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;19421 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
17798 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
17799 !type_has_bits(casted_field_value->value.type))
17800 {
17801 ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
17802 if (!field_val)
17803 return ira->codegen->invalid_instruction;
17804
17805 IrInstruction *result = ir_const(ira, instruction, container_type);
17806 ConstExprValue *out_val = &result->value;
17807 out_val->data.x_union.payload = field_val;
17808 out_val->data.x_union.tag = type_field->enum_field->value;
17809 out_val->parent.id = ConstParentIdUnion;
17810 out_val->parent.data.p_union.union_val = out_val;
1781119422
17812 return result;19423 IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr);
19424 if (is_comptime && !instr_is_comptime(result)) {
19425 ir_add_error(ira, field->result_loc,
19426 buf_sprintf("unable to evaluate constant expression"));
19427 return ira->codegen->invalid_instruction;
17813 }19428 }
1781419429 return result;
17815 IrInstruction *new_instruction = ir_build_union_init(&ira->new_irb,
17816 instruction->scope, instruction->source_node,
17817 container_type, type_field, casted_field_value);
17818 new_instruction->value.type = container_type;
17819 ir_add_alloca(ira, new_instruction, container_type);
17820 return new_instruction;
17821}19430}
1782219431
17823static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,19432static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
17824 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)19433 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
19434 IrInstruction *result_loc)
17825{19435{
17826 Error err;19436 Error err;
17827 if (container_type->id == ZigTypeIdUnion) {19437 if (container_type->id == ZigTypeIdUnion) {
17828 return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count, fields);19438 return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count,
19439 fields, result_loc);
17829 }19440 }
17830 if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {19441 if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
17831 ir_add_error(ira, instruction,19442 ir_add_error(ira, instruction,
...@@ -17842,22 +19453,28 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -17842,22 +19453,28 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
17842 IrInstruction *first_non_const_instruction = nullptr;19453 IrInstruction *first_non_const_instruction = nullptr;
1784319454
17844 AstNode **field_assign_nodes = allocate<AstNode *>(actual_field_count);19455 AstNode **field_assign_nodes = allocate<AstNode *>(actual_field_count);
1784519456 ZigList<IrInstruction *> const_ptrs = {};
17846 IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);
1784719457
17848 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)19458 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
17849 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;19459 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
1785019460
17851 ConstExprValue const_val = {};19461
17852 const_val.special = ConstValSpecialStatic;19462 // Here we iterate over the fields that have been initialized, and emit
17853 const_val.type = container_type;19463 // compile errors for missing fields and duplicate fields.
17854 // const_val.global_refs = allocate<ConstGlobalRefs>(1);19464 // It is only now that we find out whether the struct initialization can be a comptime
17855 const_val.data.x_struct.fields = create_const_vals(actual_field_count);19465 // value, but we have already emitted runtime instructions for the fields that
19466 // were initialized with runtime values, and have omitted instructions that would have
19467 // initialized fields with comptime values.
19468 // So now we must clean up this situation. If it turns out the struct initialization can
19469 // be a comptime value, overwrite ConstPtrMutInfer with ConstPtrMutComptimeConst.
19470 // Otherwise, we must emit instructions to runtime-initialize the fields that have
19471 // comptime-known values.
19472
17856 for (size_t i = 0; i < instr_field_count; i += 1) {19473 for (size_t i = 0; i < instr_field_count; i += 1) {
17857 IrInstructionContainerInitFieldsField *field = &fields[i];19474 IrInstructionContainerInitFieldsField *field = &fields[i];
1785819475
17859 IrInstruction *field_value = field->value->child;19476 IrInstruction *field_result_loc = field->result_loc->child;
17860 if (type_is_invalid(field_value->value.type))19477 if (type_is_invalid(field_result_loc->value.type))
17861 return ira->codegen->invalid_instruction;19478 return ira->codegen->invalid_instruction;
1786219479
17863 TypeStructField *type_field = find_struct_type_field(container_type, field->name);19480 TypeStructField *type_field = find_struct_type_field(container_type, field->name);
...@@ -17871,10 +19488,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -17871,10 +19488,6 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
17871 if (type_is_invalid(type_field->type_entry))19488 if (type_is_invalid(type_field->type_entry))
17872 return ira->codegen->invalid_instruction;19489 return ira->codegen->invalid_instruction;
1787319490
17874 IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry);
17875 if (casted_field_value == ira->codegen->invalid_instruction)
17876 return ira->codegen->invalid_instruction;
17877
17878 size_t field_index = type_field->src_index;19491 size_t field_index = type_field->src_index;
17879 AstNode *existing_assign_node = field_assign_nodes[field_index];19492 AstNode *existing_assign_node = field_assign_nodes[field_index];
17880 if (existing_assign_node) {19493 if (existing_assign_node) {
...@@ -17884,26 +19497,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -17884,26 +19497,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
17884 }19497 }
17885 field_assign_nodes[field_index] = field->source_node;19498 field_assign_nodes[field_index] = field->source_node;
1788619499
17887 new_fields[field_index].value = casted_field_value;19500 if (instr_is_comptime(field_result_loc) &&
17888 new_fields[field_index].type_struct_field = type_field;19501 field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
1788919502 {
17890 if (const_val.special == ConstValSpecialStatic) {19503 const_ptrs.append(field_result_loc);
17891 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime) {19504 } else {
17892 ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);19505 first_non_const_instruction = field_result_loc;
17893 if (!field_val)
17894 return ira->codegen->invalid_instruction;
17895
17896 copy_const_val(&const_val.data.x_struct.fields[field_index], field_val, true);
17897 } else {
17898 first_non_const_instruction = casted_field_value;
17899 const_val.special = ConstValSpecialRuntime;
17900 }
17901 }19506 }
17902 }19507 }
1790319508
17904 bool any_missing = false;19509 bool any_missing = false;
17905 for (size_t i = 0; i < actual_field_count; i += 1) {19510 for (size_t i = 0; i < actual_field_count; i += 1) {
17906 if (field_assign_nodes[i]) continue;19511 if (field_assign_nodes[i] != nullptr) continue;
1790719512
17908 // look for a default field value19513 // look for a default field value
17909 TypeStructField *field = &container_type->data.structure.fields[i];19514 TypeStructField *field = &container_type->data.structure.fields[i];
...@@ -17929,182 +19534,177 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -17929,182 +19534,177 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
17929 IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);19534 IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);
17930 copy_const_val(&runtime_inst->value, field->init_val, true);19535 copy_const_val(&runtime_inst->value, field->init_val, true);
1793119536
17932 new_fields[i].value = runtime_inst;19537 IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc,
17933 new_fields[i].type_struct_field = field;19538 container_type, true);
1793419539 ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst);
17935 if (const_val.special == ConstValSpecialStatic) {19540 if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
17936 copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true);19541 const_ptrs.append(field_ptr);
19542 } else {
19543 first_non_const_instruction = result_loc;
17937 }19544 }
17938 }19545 }
17939 if (any_missing)19546 if (any_missing)
17940 return ira->codegen->invalid_instruction;19547 return ira->codegen->invalid_instruction;
1794119548
17942 if (const_val.special == ConstValSpecialStatic) {19549 if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
17943 IrInstruction *result = ir_const(ira, instruction, nullptr);19550 if (const_ptrs.length != actual_field_count) {
17944 ConstExprValue *out_val = &result->value;19551 result_loc->value.special = ConstValSpecialRuntime;
17945 copy_const_val(out_val, &const_val, false);19552 for (size_t i = 0; i < const_ptrs.length; i += 1) {
17946 out_val->type = container_type;19553 IrInstruction *field_result_loc = const_ptrs.at(i);
1794719554 IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr);
17948 for (size_t i = 0; i < instr_field_count; i += 1) {19555 field_result_loc->value.special = ConstValSpecialRuntime;
17949 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];19556 ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref);
17950 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
17951 if (parent != nullptr) {
17952 parent->id = ConstParentIdStruct;
17953 parent->data.p_struct.field_index = i;
17954 parent->data.p_struct.struct_val = out_val;
17955 }19557 }
17956 }19558 }
17957
17958 return result;
17959 }19559 }
1796019560
17961 if (is_comptime) {19561 IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr);
19562
19563 if (is_comptime && !instr_is_comptime(result)) {
17962 ir_add_error_node(ira, first_non_const_instruction->source_node,19564 ir_add_error_node(ira, first_non_const_instruction->source_node,
17963 buf_sprintf("unable to evaluate constant expression"));19565 buf_sprintf("unable to evaluate constant expression"));
17964 return ira->codegen->invalid_instruction;19566 return ira->codegen->invalid_instruction;
17965 }19567 }
1796619568
17967 IrInstruction *new_instruction = ir_build_struct_init(&ira->new_irb,19569 return result;
17968 instruction->scope, instruction->source_node,
17969 container_type, actual_field_count, new_fields);
17970 new_instruction->value.type = container_type;
17971 ir_add_alloca(ira, new_instruction, container_type);
17972 return new_instruction;
17973}19570}
1797419571
17975static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,19572static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
17976 IrInstructionContainerInitList *instruction)19573 IrInstructionContainerInitList *instruction)
17977{19574{
17978 Error err;19575 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
19576 if (type_is_invalid(container_type))
19577 return ira->codegen->invalid_instruction;
1797919578
17980 size_t elem_count = instruction->item_count;19579 size_t elem_count = instruction->item_count;
1798119580
17982 ZigType *container_type;
17983 if (instruction->container_type != nullptr) {
17984 container_type = ir_resolve_type(ira, instruction->container_type->child);
17985 if (type_is_invalid(container_type))
17986 return ira->codegen->invalid_instruction;
17987 } else {
17988 ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child);
17989 if (type_is_invalid(elem_type))
17990 return ira->codegen->invalid_instruction;
17991 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) {
17992 return ira->codegen->invalid_instruction;
17993 }
17994 container_type = get_array_type(ira->codegen, elem_type, elem_count);
17995 }
17996
17997 if (is_slice(container_type)) {19581 if (is_slice(container_type)) {
17998 ir_add_error(ira, &instruction->base,19582 ir_add_error(ira, instruction->container_type,
17999 buf_sprintf("expected array type or [_], found slice"));19583 buf_sprintf("expected array type or [_], found slice"));
18000 return ira->codegen->invalid_instruction;19584 return ira->codegen->invalid_instruction;
18001 } else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {19585 }
18002 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
18003 0, nullptr);
18004 } else if (container_type->id == ZigTypeIdArray) {
18005 // array is same as slice init but we make a compile error if the length is wrong
18006 ZigType *child_type;
18007 if (container_type->id == ZigTypeIdArray) {
18008 child_type = container_type->data.array.child_type;
18009 if (container_type->data.array.len != elem_count) {
18010 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
18011
18012 ir_add_error(ira, &instruction->base,
18013 buf_sprintf("expected %s literal, found %s literal",
18014 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
18015 return ira->codegen->invalid_instruction;
18016 }
18017 } else {
18018 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
18019 assert(pointer_type->id == ZigTypeIdPointer);
18020 child_type = pointer_type->data.pointer.child_type;
18021 }
1802219586
18023 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) {19587 if (container_type->id == ZigTypeIdVoid) {
19588 if (elem_count != 0) {
19589 ir_add_error_node(ira, instruction->base.source_node,
19590 buf_sprintf("void expression expects no arguments"));
18024 return ira->codegen->invalid_instruction;19591 return ira->codegen->invalid_instruction;
18025 }19592 }
19593 return ir_const_void(ira, &instruction->base);
19594 }
1802619595
18027 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);19596 if (container_type->id == ZigTypeIdStruct && elem_count == 0) {
19597 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19598 IrInstruction *result_loc = instruction->result_loc->child;
19599 if (type_is_invalid(result_loc->value.type))
19600 return result_loc;
19601 return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc);
19602 }
1802819603
18029 ConstExprValue const_val = {};19604 if (container_type->id != ZigTypeIdArray) {
18030 const_val.special = ConstValSpecialStatic;19605 ir_add_error_node(ira, instruction->base.source_node,
18031 const_val.type = fixed_size_array_type;19606 buf_sprintf("type '%s' does not support array initialization",
18032 // const_val.global_refs = allocate<ConstGlobalRefs>(1);19607 buf_ptr(&container_type->name)));
18033 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);19608 return ira->codegen->invalid_instruction;
19609 }
1803419610
18035 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);19611 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19612 IrInstruction *result_loc = instruction->result_loc->child;
19613 if (type_is_invalid(result_loc->value.type))
19614 return result_loc;
19615 ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
1803619616
18037 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);19617 ZigType *child_type = container_type->data.array.child_type;
19618 if (container_type->data.array.len != elem_count) {
19619 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
1803819620
18039 IrInstruction *first_non_const_instruction = nullptr;19621 ir_add_error(ira, &instruction->base,
19622 buf_sprintf("expected %s literal, found %s literal",
19623 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
19624 return ira->codegen->invalid_instruction;
19625 }
1804019626
18041 for (size_t i = 0; i < elem_count; i += 1) {19627 switch (type_has_one_possible_value(ira->codegen, container_type)) {
18042 IrInstruction *arg_value = instruction->items[i]->child;19628 case OnePossibleValueInvalid:
18043 if (type_is_invalid(arg_value->value.type))19629 return ira->codegen->invalid_instruction;
18044 return ira->codegen->invalid_instruction;19630 case OnePossibleValueYes:
19631 return ir_const(ira, &instruction->base, container_type);
19632 case OnePossibleValueNo:
19633 break;
19634 }
1804519635
18046 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);19636 bool is_comptime;
18047 if (casted_arg == ira->codegen->invalid_instruction)19637 switch (type_requires_comptime(ira->codegen, container_type)) {
18048 return ira->codegen->invalid_instruction;19638 case ReqCompTimeInvalid:
19639 return ira->codegen->invalid_instruction;
19640 case ReqCompTimeNo:
19641 is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
19642 break;
19643 case ReqCompTimeYes:
19644 is_comptime = true;
19645 break;
19646 }
1804919647
18050 new_items[i] = casted_arg;19648 IrInstruction *first_non_const_instruction = nullptr;
1805119649
18052 if (const_val.special == ConstValSpecialStatic) {19650 // The Result Location Mechanism has already emitted runtime instructions to
18053 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {19651 // initialize runtime elements and has omitted instructions for the comptime
18054 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);19652 // elements. However it is only now that we find out whether the array initialization
18055 if (!elem_val)19653 // can be a comptime value. So we must clean up the situation. If it turns out
18056 return ira->codegen->invalid_instruction;19654 // array initialization can be a comptime value, overwrite ConstPtrMutInfer with
19655 // ConstPtrMutComptimeConst. Otherwise, emit instructions to runtime-initialize the
19656 // elements that have comptime-known values.
19657 ZigList<IrInstruction *> const_ptrs = {};
19658
19659 for (size_t i = 0; i < elem_count; i += 1) {
19660 IrInstruction *elem_result_loc = instruction->elem_result_loc_list[i]->child;
19661 if (type_is_invalid(elem_result_loc->value.type))
19662 return ira->codegen->invalid_instruction;
1805719663
18058 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);19664 assert(elem_result_loc->value.type->id == ZigTypeIdPointer);
18059 } else {19665
18060 first_non_const_instruction = casted_arg;19666 if (instr_is_comptime(elem_result_loc) &&
18061 const_val.special = ConstValSpecialRuntime;19667 elem_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
18062 }19668 {
18063 }19669 const_ptrs.append(elem_result_loc);
19670 } else {
19671 first_non_const_instruction = elem_result_loc;
18064 }19672 }
19673 }
1806519674
18066 if (const_val.special == ConstValSpecialStatic) {19675 if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
18067 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);19676 if (const_ptrs.length != elem_count) {
18068 ConstExprValue *out_val = &result->value;19677 result_loc->value.special = ConstValSpecialRuntime;
18069 copy_const_val(out_val, &const_val, false);19678 for (size_t i = 0; i < const_ptrs.length; i += 1) {
18070 result->value.type = fixed_size_array_type;19679 IrInstruction *elem_result_loc = const_ptrs.at(i);
18071 for (size_t i = 0; i < elem_count; i += 1) {19680 assert(elem_result_loc->value.special == ConstValSpecialStatic);
18072 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];19681 IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
18073 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);19682 elem_result_loc->value.special = ConstValSpecialRuntime;
18074 if (parent != nullptr) {19683 ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref);
18075 parent->id = ConstParentIdArray;
18076 parent->data.p_array.array_val = out_val;
18077 parent->data.p_array.elem_index = i;
18078 }
18079 }19684 }
18080 return result;
18081 }19685 }
19686 }
1808219687
18083 if (is_comptime) {19688 IrInstruction *result = ir_get_deref(ira, &instruction->base, result_loc, nullptr);
18084 ir_add_error_node(ira, first_non_const_instruction->source_node,19689 if (instr_is_comptime(result))
18085 buf_sprintf("unable to evaluate constant expression"));19690 return result;
18086 return ira->codegen->invalid_instruction;
18087 }
1808819691
18089 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,19692 if (is_comptime) {
18090 instruction->base.scope, instruction->base.source_node,19693 ir_add_error_node(ira, first_non_const_instruction->source_node,
18091 nullptr, nullptr, elem_count, new_items);19694 buf_sprintf("unable to evaluate constant expression"));
18092 new_instruction->value.type = fixed_size_array_type;19695 return ira->codegen->invalid_instruction;
18093 ir_add_alloca(ira, new_instruction, fixed_size_array_type);19696 }
18094 return new_instruction;19697
18095 } else if (container_type->id == ZigTypeIdVoid) {19698 ZigType *result_elem_type = result_loc->value.type->data.pointer.child_type;
18096 if (elem_count != 0) {19699 if (is_slice(result_elem_type)) {
18097 ir_add_error_node(ira, instruction->base.source_node,19700 ErrorMsg *msg = ir_add_error(ira, &instruction->base,
18098 buf_sprintf("void expression expects no arguments"));19701 buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
18099 return ira->codegen->invalid_instruction;19702 buf_ptr(&result_elem_type->name)));
18100 }19703 add_error_note(ira->codegen, msg, first_non_const_instruction->source_node,
18101 return ir_const_void(ira, &instruction->base);19704 buf_sprintf("this value is not comptime-known"));
18102 } else {
18103 ir_add_error_node(ira, instruction->base.source_node,
18104 buf_sprintf("type '%s' does not support array initialization",
18105 buf_ptr(&container_type->name)));
18106 return ira->codegen->invalid_instruction;19705 return ira->codegen->invalid_instruction;
18107 }19706 }
19707 return result;
18108}19708}
1810919709
18110static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,19710static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
...@@ -18115,8 +19715,13 @@ static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ir...@@ -18115,8 +19715,13 @@ static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ir
18115 if (type_is_invalid(container_type))19715 if (type_is_invalid(container_type))
18116 return ira->codegen->invalid_instruction;19716 return ira->codegen->invalid_instruction;
1811719717
19718 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19719 IrInstruction *result_loc = instruction->result_loc->child;
19720 if (type_is_invalid(result_loc->value.type))
19721 return result_loc;
19722
18118 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,19723 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
18119 instruction->field_count, instruction->fields);19724 instruction->field_count, instruction->fields, result_loc);
18120}19725}
1812119726
18122static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,19727static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,
...@@ -18385,12 +19990,6 @@ static IrInstruction *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira,...@@ -18385,12 +19990,6 @@ static IrInstruction *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira,
18385 return ir_const_unsigned(ira, &instruction->base, bit_offset);19990 return ir_const_unsigned(ira, &instruction->base, bit_offset);
18386}19991}
1838719992
18388static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) {
18389 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));
18390 emit_error_notes_for_ref_stack(ira->codegen, msg);
18391 return ira->codegen->invalid_instruction;
18392}
18393
18394static void ensure_field_index(ZigType *type, const char *field_name, size_t index) {19993static void ensure_field_index(ZigType *type, const char *field_name, size_t index) {
18395 Buf *field_name_buf;19994 Buf *field_name_buf;
1839619995
...@@ -19509,7 +21108,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -19509,7 +21108,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
19509 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make dir: %s", err_str(err)));21108 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make dir: %s", err_str(err)));
19510 return ira->codegen->invalid_instruction;21109 return ira->codegen->invalid_instruction;
19511 }21110 }
19512 21111
19513 if ((err = os_write_file(&tmp_c_file_path, &cimport_scope->buf))) {21112 if ((err = os_write_file(&tmp_c_file_path, &cimport_scope->buf))) {
19514 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write .h file: %s", err_str(err)));21113 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write .h file: %s", err_str(err)));
19515 return ira->codegen->invalid_instruction;21114 return ira->codegen->invalid_instruction;
...@@ -19796,12 +21395,21 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi...@@ -19796,12 +21395,21 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
19796 zig_panic("TODO compile-time execution of cmpxchg");21395 zig_panic("TODO compile-time execution of cmpxchg");
19797 }21396 }
1979821397
19799 IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,21398 ZigType *result_type = get_optional_type(ira->codegen, operand_type);
21399 IrInstruction *result_loc;
21400 if (handle_is_ptr(result_type)) {
21401 result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
21402 result_type, nullptr, true, false);
21403 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
21404 return result_loc;
21405 }
21406 } else {
21407 result_loc = nullptr;
21408 }
21409
21410 return ir_build_cmpxchg_gen(ira, &instruction->base, result_type,
19800 casted_ptr, casted_cmp_value, casted_new_value,21411 casted_ptr, casted_cmp_value, casted_new_value,
19801 success_order, failure_order, instruction->is_weak);21412 success_order, failure_order, instruction->is_weak, result_loc);
19802 result->value.type = get_optional_type(ira->codegen, operand_type);
19803 ir_add_alloca(ira, result, result->value.type);
19804 return result;
19805}21413}
1980621414
19807static IrInstruction *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstructionFence *instruction) {21415static IrInstruction *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstructionFence *instruction) {
...@@ -19939,7 +21547,7 @@ static IrInstruction *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstru...@@ -19939,7 +21547,7 @@ static IrInstruction *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstru
19939 } else {21547 } else {
19940 op = CastOpNumLitToConcrete;21548 op = CastOpNumLitToConcrete;
19941 }21549 }
19942 return ir_resolve_cast(ira, &instruction->base, target, dest_type, op, false);21550 return ir_resolve_cast(ira, &instruction->base, target, dest_type, op);
19943 } else {21551 } else {
19944 return ira->codegen->invalid_instruction;21552 return ira->codegen->invalid_instruction;
19945 }21553 }
...@@ -20047,6 +21655,12 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru...@@ -20047,6 +21655,12 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
20047 }21655 }
20048 }21656 }
2004921657
21658 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
21659 dest_slice_type, nullptr, true, false);
21660 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
21661 return result_loc;
21662 }
21663
20050 if (casted_value->value.data.rh_slice.id == RuntimeHintSliceIdLen) {21664 if (casted_value->value.data.rh_slice.id == RuntimeHintSliceIdLen) {
20051 known_len = casted_value->value.data.rh_slice.len;21665 known_len = casted_value->value.data.rh_slice.len;
20052 have_known_len = true;21666 have_known_len = true;
...@@ -20066,9 +21680,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru...@@ -20066,9 +21680,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
20066 }21680 }
20067 }21681 }
2006821682
20069 IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type);21683 return ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type, result_loc);
20070 ir_add_alloca(ira, result, dest_slice_type);
20071 return result;
20072}21684}
2007321685
20074static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {21686static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
...@@ -20120,9 +21732,13 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct...@@ -20120,9 +21732,13 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
20120 return result;21732 return result;
20121 }21733 }
2012221734
20123 IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type);21735 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
20124 ir_add_alloca(ira, result, dest_slice_type);21736 dest_slice_type, nullptr, true, false);
20125 return result;21737 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
21738 return result_loc;
21739 }
21740
21741 return ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type, result_loc);
20126}21742}
2012721743
20128static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {21744static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
...@@ -20154,7 +21770,7 @@ static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInst...@@ -20154,7 +21770,7 @@ static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInst
20154 return ira->codegen->invalid_instruction;21770 return ira->codegen->invalid_instruction;
20155 }21771 }
2015621772
20157 return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat, false);21773 return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat);
20158}21774}
2015921775
20160static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstructionFloatToInt *instruction) {21776static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstructionFloatToInt *instruction) {
...@@ -20176,7 +21792,7 @@ static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInst...@@ -20176,7 +21792,7 @@ static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInst
20176 return ira->codegen->invalid_instruction;21792 return ira->codegen->invalid_instruction;
20177 }21793 }
2017821794
20179 return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt, false);21795 return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt);
20180}21796}
2018121797
20182static IrInstruction *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) {21798static IrInstruction *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) {
...@@ -20228,7 +21844,7 @@ static IrInstruction *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstr...@@ -20228,7 +21844,7 @@ static IrInstruction *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstr
20228 }21844 }
2022921845
20230 ZigType *u1_type = get_int_type(ira->codegen, false, 1);21846 ZigType *u1_type = get_int_type(ira->codegen, false, 1);
20231 return ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt, false);21847 return ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt);
20232}21848}
2023321849
20234static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) {21850static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) {
...@@ -20389,7 +22005,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio...@@ -20389,7 +22005,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
2038922005
20390 ConstExprValue *byte_val = &casted_byte->value;22006 ConstExprValue *byte_val = &casted_byte->value;
20391 for (size_t i = start; i < end; i += 1) {22007 for (size_t i = start; i < end; i += 1) {
20392 dest_elements[i] = *byte_val;22008 copy_const_val(&dest_elements[i], byte_val, true);
20393 }22009 }
2039422010
20395 return ir_const_void(ira, &instruction->base);22011 return ir_const_void(ira, &instruction->base);
...@@ -20459,7 +22075,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -20459,7 +22075,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
20459 return ira->codegen->invalid_instruction;22075 return ira->codegen->invalid_instruction;
2046022076
20461 // TODO test this at comptime with u8 and non-u8 types22077 // TODO test this at comptime with u8 and non-u8 types
20462 // TODO test with dest ptr being a global runtime variable 22078 // TODO test with dest ptr being a global runtime variable
20463 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&22079 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
20464 casted_src_ptr->value.special == ConstValSpecialStatic &&22080 casted_src_ptr->value.special == ConstValSpecialStatic &&
20465 casted_count->value.special == ConstValSpecialStatic &&22081 casted_count->value.special == ConstValSpecialStatic &&
...@@ -20557,7 +22173,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -20557,7 +22173,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
20557 // TODO check for noalias violations - this should be generalized to work for any function22173 // TODO check for noalias violations - this should be generalized to work for any function
2055822174
20559 for (size_t i = 0; i < count; i += 1) {22175 for (size_t i = 0; i < count; i += 1) {
20560 dest_elements[dest_start + i] = src_elements[src_start + i];22176 copy_const_val(&dest_elements[dest_start + i], &src_elements[src_start + i], true);
20561 }22177 }
2056222178
20563 return ir_const_void(ira, &instruction->base);22179 return ir_const_void(ira, &instruction->base);
...@@ -20569,7 +22185,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -20569,7 +22185,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
20569 return result;22185 return result;
20570}22186}
2057122187
20572static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice *instruction) {22188static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSliceSrc *instruction) {
20573 IrInstruction *ptr_ptr = instruction->ptr->child;22189 IrInstruction *ptr_ptr = instruction->ptr->child;
20574 if (type_is_invalid(ptr_ptr->value.type))22190 if (type_is_invalid(ptr_ptr->value.type))
20575 return ira->codegen->invalid_instruction;22191 return ira->codegen->invalid_instruction;
...@@ -20858,12 +22474,13 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -20858,12 +22474,13 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
20858 return result;22474 return result;
20859 }22475 }
2086022476
20861 IrInstruction *new_instruction = ir_build_slice(&ira->new_irb,22477 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
20862 instruction->base.scope, instruction->base.source_node,22478 return_type, nullptr, true, false);
20863 ptr_ptr, casted_start, end, instruction->safety_check_on);22479 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
20864 new_instruction->value.type = return_type;22480 return result_loc;
20865 ir_add_alloca(ira, new_instruction, return_type);22481 }
20866 return new_instruction;22482 return ir_build_slice_gen(ira, &instruction->base, return_type,
22483 ptr_ptr, casted_start, end, instruction->safety_check_on, result_loc);
20867}22484}
2086822485
20869static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) {22486static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) {
...@@ -21187,15 +22804,149 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr...@@ -21187,15 +22804,149 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
21187 return result;22804 return result;
21188}22805}
2118922806
21190static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErr *instruction) {22807static IrInstruction *ir_analyze_instruction_result_ptr(IrAnalyze *ira, IrInstructionResultPtr *instruction) {
21191 IrInstruction *value = instruction->value->child;22808 IrInstruction *result = instruction->result->child;
21192 if (type_is_invalid(value->value.type))22809 if (type_is_invalid(result->value.type))
22810 return result;
22811
22812 if (instruction->result_loc->written && instruction->result_loc->resolved_loc != nullptr &&
22813 !instr_is_comptime(result))
22814 {
22815 return instruction->result_loc->resolved_loc;
22816 }
22817 return ir_get_ref(ira, &instruction->base, result, true, false);
22818}
22819
22820static void ir_eval_mul_add(IrAnalyze *ira, IrInstructionMulAdd *source_instr, ZigType *float_type,
22821 ConstExprValue *op1, ConstExprValue *op2, ConstExprValue *op3, ConstExprValue *out_val) {
22822 if (float_type->id == ZigTypeIdComptimeFloat) {
22823 f128M_mulAdd(&out_val->data.x_bigfloat.value, &op1->data.x_bigfloat.value, &op2->data.x_bigfloat.value,
22824 &op3->data.x_bigfloat.value);
22825 } else if (float_type->id == ZigTypeIdFloat) {
22826 switch (float_type->data.floating.bit_count) {
22827 case 16:
22828 out_val->data.x_f16 = f16_mulAdd(op1->data.x_f16, op2->data.x_f16, op3->data.x_f16);
22829 break;
22830 case 32:
22831 out_val->data.x_f32 = fmaf(op1->data.x_f32, op2->data.x_f32, op3->data.x_f32);
22832 break;
22833 case 64:
22834 out_val->data.x_f64 = fma(op1->data.x_f64, op2->data.x_f64, op3->data.x_f64);
22835 break;
22836 case 128:
22837 f128M_mulAdd(&op1->data.x_f128, &op2->data.x_f128, &op3->data.x_f128, &out_val->data.x_f128);
22838 break;
22839 default:
22840 zig_unreachable();
22841 }
22842 } else {
22843 zig_unreachable();
22844 }
22845}
22846
22847static IrInstruction *ir_analyze_instruction_mul_add(IrAnalyze *ira, IrInstructionMulAdd *instruction) {
22848 IrInstruction *type_value = instruction->type_value->child;
22849 if (type_is_invalid(type_value->value.type))
22850 return ira->codegen->invalid_instruction;
22851
22852 ZigType *expr_type = ir_resolve_type(ira, type_value);
22853 if (type_is_invalid(expr_type))
22854 return ira->codegen->invalid_instruction;
22855
22856 // Only allow float types, and vectors of floats.
22857 ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
22858 if (float_type->id != ZigTypeIdFloat) {
22859 ir_add_error(ira, type_value,
22860 buf_sprintf("expected float or vector of float type, found '%s'", buf_ptr(&float_type->name)));
22861 return ira->codegen->invalid_instruction;
22862 }
22863
22864 IrInstruction *op1 = instruction->op1->child;
22865 if (type_is_invalid(op1->value.type))
22866 return ira->codegen->invalid_instruction;
22867
22868 IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, expr_type);
22869 if (type_is_invalid(casted_op1->value.type))
22870 return ira->codegen->invalid_instruction;
22871
22872 IrInstruction *op2 = instruction->op2->child;
22873 if (type_is_invalid(op2->value.type))
22874 return ira->codegen->invalid_instruction;
22875
22876 IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, expr_type);
22877 if (type_is_invalid(casted_op2->value.type))
22878 return ira->codegen->invalid_instruction;
22879
22880 IrInstruction *op3 = instruction->op3->child;
22881 if (type_is_invalid(op3->value.type))
22882 return ira->codegen->invalid_instruction;
22883
22884 IrInstruction *casted_op3 = ir_implicit_cast(ira, op3, expr_type);
22885 if (type_is_invalid(casted_op3->value.type))
22886 return ira->codegen->invalid_instruction;
22887
22888 if (instr_is_comptime(casted_op1) &&
22889 instr_is_comptime(casted_op2) &&
22890 instr_is_comptime(casted_op3)) {
22891 ConstExprValue *op1_const = ir_resolve_const(ira, casted_op1, UndefBad);
22892 if (!op1_const)
22893 return ira->codegen->invalid_instruction;
22894 ConstExprValue *op2_const = ir_resolve_const(ira, casted_op2, UndefBad);
22895 if (!op2_const)
22896 return ira->codegen->invalid_instruction;
22897 ConstExprValue *op3_const = ir_resolve_const(ira, casted_op3, UndefBad);
22898 if (!op3_const)
22899 return ira->codegen->invalid_instruction;
22900
22901 IrInstruction *result = ir_const(ira, &instruction->base, expr_type);
22902 ConstExprValue *out_val = &result->value;
22903
22904 if (expr_type->id == ZigTypeIdVector) {
22905 expand_undef_array(ira->codegen, op1_const);
22906 expand_undef_array(ira->codegen, op2_const);
22907 expand_undef_array(ira->codegen, op3_const);
22908 out_val->special = ConstValSpecialUndef;
22909 expand_undef_array(ira->codegen, out_val);
22910 size_t len = expr_type->data.vector.len;
22911 for (size_t i = 0; i < len; i += 1) {
22912 ConstExprValue *float_operand_op1 = &op1_const->data.x_array.data.s_none.elements[i];
22913 ConstExprValue *float_operand_op2 = &op2_const->data.x_array.data.s_none.elements[i];
22914 ConstExprValue *float_operand_op3 = &op3_const->data.x_array.data.s_none.elements[i];
22915 ConstExprValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i];
22916 assert(float_operand_op1->type == float_type);
22917 assert(float_operand_op2->type == float_type);
22918 assert(float_operand_op3->type == float_type);
22919 assert(float_out_val->type == float_type);
22920 ir_eval_mul_add(ira, instruction, float_type,
22921 op1_const, op2_const, op3_const, float_out_val);
22922 float_out_val->type = float_type;
22923 }
22924 out_val->type = expr_type;
22925 out_val->special = ConstValSpecialStatic;
22926 } else {
22927 ir_eval_mul_add(ira, instruction, float_type, op1_const, op2_const, op3_const, out_val);
22928 }
22929 return result;
22930 }
22931
22932 IrInstruction *result = ir_build_mul_add(&ira->new_irb,
22933 instruction->base.scope, instruction->base.source_node,
22934 type_value, casted_op1, casted_op2, casted_op3);
22935 result->value.type = expr_type;
22936 return result;
22937}
22938
22939static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErrSrc *instruction) {
22940 IrInstruction *base_ptr = instruction->base_ptr->child;
22941 if (type_is_invalid(base_ptr->value.type))
21193 return ira->codegen->invalid_instruction;22942 return ira->codegen->invalid_instruction;
2119422943
22944 IrInstruction *value = ir_get_deref(ira, &instruction->base, base_ptr, nullptr);
21195 ZigType *type_entry = value->value.type;22945 ZigType *type_entry = value->value.type;
21196 if (type_is_invalid(type_entry)) {22946 if (type_is_invalid(type_entry))
21197 return ira->codegen->invalid_instruction;22947 return ira->codegen->invalid_instruction;
21198 } else if (type_entry->id == ZigTypeIdErrorUnion) {22948
22949 if (type_entry->id == ZigTypeIdErrorUnion) {
21199 if (instr_is_comptime(value)) {22950 if (instr_is_comptime(value)) {
21200 ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);22951 ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
21201 if (!err_union_val)22952 if (!err_union_val)
...@@ -21207,21 +22958,20 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct...@@ -21207,21 +22958,20 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
21207 }22958 }
21208 }22959 }
2120922960
21210 ZigType *err_set_type = type_entry->data.error_union.err_set_type;22961 if (instruction->resolve_err_set) {
21211 if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.source_node)) {22962 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
21212 return ira->codegen->invalid_instruction;22963 if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.source_node)) {
21213 }22964 return ira->codegen->invalid_instruction;
21214 if (!type_is_global_error_set(err_set_type) &&22965 }
21215 err_set_type->data.error_set.err_count == 0)22966 if (!type_is_global_error_set(err_set_type) &&
21216 {22967 err_set_type->data.error_set.err_count == 0)
21217 assert(err_set_type->data.error_set.infer_fn == nullptr);22968 {
21218 return ir_const_bool(ira, &instruction->base, false);22969 assert(err_set_type->data.error_set.infer_fn == nullptr);
22970 return ir_const_bool(ira, &instruction->base, false);
22971 }
21219 }22972 }
2122022973
21221 IrInstruction *result = ir_build_test_err(&ira->new_irb,22974 return ir_build_test_err_gen(ira, &instruction->base, value);
21222 instruction->base.scope, instruction->base.source_node, value);
21223 result->value.type = ira->codegen->builtin_types.entry_bool;
21224 return result;
21225 } else if (type_entry->id == ZigTypeIdErrorSet) {22975 } else if (type_entry->id == ZigTypeIdErrorSet) {
21226 return ir_const_bool(ira, &instruction->base, true);22976 return ir_const_bool(ira, &instruction->base, true);
21227 } else {22977 } else {
...@@ -21229,10 +22979,9 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct...@@ -21229,10 +22979,9 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
21229 }22979 }
21230}22980}
2123122981
21232static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {22982static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
21233 IrInstruction *base_ptr = instruction->err_union->child;22983 IrInstruction *base_ptr, bool initializing)
21234 if (type_is_invalid(base_ptr->value.type))22984{
21235 return ira->codegen->invalid_instruction;
21236 ZigType *ptr_type = base_ptr->value.type;22985 ZigType *ptr_type = base_ptr->value.type;
2123722986
21238 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.22987 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
...@@ -21248,40 +22997,79 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrI...@@ -21248,40 +22997,79 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrI
21248 return ira->codegen->invalid_instruction;22997 return ira->codegen->invalid_instruction;
21249 }22998 }
2125022999
23000 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
23001 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, err_set_type,
23002 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle,
23003 ptr_type->data.pointer.explicit_alignment, 0, 0, false);
23004
21251 if (instr_is_comptime(base_ptr)) {23005 if (instr_is_comptime(base_ptr)) {
21252 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);23006 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
21253 if (!ptr_val)23007 if (!ptr_val)
21254 return ira->codegen->invalid_instruction;23008 return ira->codegen->invalid_instruction;
21255 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {23009 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
21256 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);23010 ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
23011 {
23012 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
21257 if (err_union_val == nullptr)23013 if (err_union_val == nullptr)
21258 return ira->codegen->invalid_instruction;23014 return ira->codegen->invalid_instruction;
21259 if (err_union_val->special != ConstValSpecialRuntime) {
21260 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
21261 assert(err);
2126223015
21263 IrInstruction *result = ir_const(ira, &instruction->base,23016 if (initializing && err_union_val->special == ConstValSpecialUndef) {
21264 type_entry->data.error_union.err_set_type);23017 ConstExprValue *vals = create_const_vals(2);
21265 result->value.data.x_err_set = err;23018 ConstExprValue *err_set_val = &vals[0];
21266 return result;23019 ConstExprValue *payload_val = &vals[1];
23020
23021 err_set_val->special = ConstValSpecialUndef;
23022 err_set_val->type = err_set_type;
23023 err_set_val->parent.id = ConstParentIdErrUnionCode;
23024 err_set_val->parent.data.p_err_union_code.err_union_val = err_union_val;
23025
23026 payload_val->special = ConstValSpecialUndef;
23027 payload_val->type = type_entry->data.error_union.payload_type;
23028 payload_val->parent.id = ConstParentIdErrUnionPayload;
23029 payload_val->parent.data.p_err_union_payload.err_union_val = err_union_val;
23030
23031 err_union_val->special = ConstValSpecialStatic;
23032 err_union_val->data.x_err_union.error_set = err_set_val;
23033 err_union_val->data.x_err_union.payload = payload_val;
23034 }
23035 ir_assert(err_union_val->special != ConstValSpecialRuntime, source_instr);
23036
23037 IrInstruction *result;
23038 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
23039 result = ir_build_unwrap_err_code(&ira->new_irb, source_instr->scope,
23040 source_instr->source_node, base_ptr);
23041 result->value.type = result_type;
23042 result->value.special = ConstValSpecialStatic;
23043 } else {
23044 result = ir_const(ira, source_instr, result_type);
21267 }23045 }
23046 ConstExprValue *const_val = &result->value;
23047 const_val->data.x_ptr.special = ConstPtrSpecialBaseErrorUnionCode;
23048 const_val->data.x_ptr.data.base_err_union_code.err_union_val = err_union_val;
23049 const_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut;
23050 return result;
21268 }23051 }
21269 }23052 }
2127023053
21271 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,23054 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
21272 instruction->base.scope, instruction->base.source_node, base_ptr);23055 source_instr->scope, source_instr->source_node, base_ptr);
21273 result->value.type = type_entry->data.error_union.err_set_type;23056 result->value.type = result_type;
21274 return result;23057 return result;
21275}23058}
2127623059
21277static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,23060static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
21278 IrInstructionUnwrapErrPayload *instruction)23061 IrInstructionUnwrapErrCode *instruction)
21279{23062{
21280 assert(instruction->value->child);23063 IrInstruction *base_ptr = instruction->err_union_ptr->child;
21281 IrInstruction *value = instruction->value->child;23064 if (type_is_invalid(base_ptr->value.type))
21282 if (type_is_invalid(value->value.type))
21283 return ira->codegen->invalid_instruction;23065 return ira->codegen->invalid_instruction;
21284 ZigType *ptr_type = value->value.type;23066 return ir_analyze_unwrap_err_code(ira, &instruction->base, base_ptr, false);
23067}
23068
23069static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr,
23070 IrInstruction *base_ptr, bool safety_check_on, bool initializing)
23071{
23072 ZigType *ptr_type = base_ptr->value.type;
2128523073
21286 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.23074 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
21287 assert(ptr_type->id == ZigTypeIdPointer);23075 assert(ptr_type->id == ZigTypeIdPointer);
...@@ -21291,7 +23079,7 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -21291,7 +23079,7 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
21291 return ira->codegen->invalid_instruction;23079 return ira->codegen->invalid_instruction;
2129223080
21293 if (type_entry->id != ZigTypeIdErrorUnion) {23081 if (type_entry->id != ZigTypeIdErrorUnion) {
21294 ir_add_error(ira, value,23082 ir_add_error(ira, base_ptr,
21295 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));23083 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
21296 return ira->codegen->invalid_instruction;23084 return ira->codegen->invalid_instruction;
21297 }23085 }
...@@ -21303,36 +23091,73 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -21303,36 +23091,73 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
21303 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,23091 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
21304 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,23092 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
21305 PtrLenSingle, 0, 0, 0, false);23093 PtrLenSingle, 0, 0, 0, false);
21306 if (instr_is_comptime(value)) {23094 if (instr_is_comptime(base_ptr)) {
21307 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);23095 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
21308 if (!ptr_val)23096 if (!ptr_val)
21309 return ira->codegen->invalid_instruction;23097 return ira->codegen->invalid_instruction;
21310 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {23098 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
21311 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);23099 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
21312 if (err_union_val == nullptr)23100 if (err_union_val == nullptr)
21313 return ira->codegen->invalid_instruction;23101 return ira->codegen->invalid_instruction;
23102 if (err_union_val->special == ConstValSpecialUndef && initializing) {
23103 ConstExprValue *vals = create_const_vals(2);
23104 ConstExprValue *err_set_val = &vals[0];
23105 ConstExprValue *payload_val = &vals[1];
23106
23107 err_set_val->special = ConstValSpecialStatic;
23108 err_set_val->type = type_entry->data.error_union.err_set_type;
23109 err_set_val->data.x_err_set = nullptr;
23110
23111 payload_val->special = ConstValSpecialUndef;
23112 payload_val->type = payload_type;
23113
23114 err_union_val->special = ConstValSpecialStatic;
23115 err_union_val->data.x_err_union.error_set = err_set_val;
23116 err_union_val->data.x_err_union.payload = payload_val;
23117 }
23118
21314 if (err_union_val->special != ConstValSpecialRuntime) {23119 if (err_union_val->special != ConstValSpecialRuntime) {
21315 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;23120 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
21316 if (err != nullptr) {23121 if (err != nullptr) {
21317 ir_add_error(ira, &instruction->base,23122 ir_add_error(ira, source_instr,
21318 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));23123 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
21319 return ira->codegen->invalid_instruction;23124 return ira->codegen->invalid_instruction;
21320 }23125 }
2132123126
21322 IrInstruction *result = ir_const(ira, &instruction->base, result_type);23127 IrInstruction *result;
23128 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
23129 result = ir_build_unwrap_err_payload(&ira->new_irb, source_instr->scope,
23130 source_instr->source_node, base_ptr, safety_check_on, initializing);
23131 result->value.type = result_type;
23132 result->value.special = ConstValSpecialStatic;
23133 } else {
23134 result = ir_const(ira, source_instr, result_type);
23135 }
21323 result->value.data.x_ptr.special = ConstPtrSpecialRef;23136 result->value.data.x_ptr.special = ConstPtrSpecialRef;
21324 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;23137 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
23138 result->value.data.x_ptr.mut = ptr_val->data.x_ptr.mut;
21325 return result;23139 return result;
21326 }23140 }
21327 }23141 }
21328 }23142 }
2132923143
21330 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,23144 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, source_instr->scope,
21331 instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);23145 source_instr->source_node, base_ptr, safety_check_on, initializing);
21332 result->value.type = result_type;23146 result->value.type = result_type;
21333 return result;23147 return result;
21334}23148}
2133523149
23150static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
23151 IrInstructionUnwrapErrPayload *instruction)
23152{
23153 assert(instruction->value->child);
23154 IrInstruction *value = instruction->value->child;
23155 if (type_is_invalid(value->value.type))
23156 return ira->codegen->invalid_instruction;
23157
23158 return ir_analyze_unwrap_error_payload(ira, &instruction->base, value, instruction->safety_check_on, false);
23159}
23160
21336static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {23161static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
21337 AstNode *proto_node = instruction->base.source_node;23162 AstNode *proto_node = instruction->base.source_node;
21338 assert(proto_node->type == NodeTypeFnProto);23163 assert(proto_node->type == NodeTypeFnProto);
...@@ -21824,14 +23649,19 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -21824,14 +23649,19 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
21824 }23649 }
21825 }23650 }
2182623651
21827 IrInstruction *result = ir_const(ira, source_instr, dest_type);23652 IrInstruction *result;
23653 if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
23654 result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
23655 } else {
23656 result = ir_const(ira, source_instr, dest_type);
23657 }
21828 copy_const_val(&result->value, val, true);23658 copy_const_val(&result->value, val, true);
21829 result->value.type = dest_type;23659 result->value.type = dest_type;
2183023660
21831 // Keep the bigger alignment, it can only help-23661 // Keep the bigger alignment, it can only help-
21832 // unless the target is zero bits.23662 // unless the target is zero bits.
21833 if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {23663 if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
21834 result = ir_align_cast(ira, result, src_align_bytes, false);23664 result = ir_align_cast(ira, result, src_align_bytes, false);
21835 }23665 }
2183623666
21837 return result;23667 return result;
...@@ -21915,6 +23745,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -21915,6 +23745,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
21915 case ZigTypeIdUndefined:23745 case ZigTypeIdUndefined:
21916 case ZigTypeIdNull:23746 case ZigTypeIdNull:
21917 case ZigTypeIdPromise:23747 case ZigTypeIdPromise:
23748 case ZigTypeIdErrorUnion:
23749 case ZigTypeIdErrorSet:
21918 zig_unreachable();23750 zig_unreachable();
21919 case ZigTypeIdVoid:23751 case ZigTypeIdVoid:
21920 return;23752 return;
...@@ -22018,10 +23850,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -22018,10 +23850,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
22018 }23850 }
22019 case ZigTypeIdOptional:23851 case ZigTypeIdOptional:
22020 zig_panic("TODO buf_write_value_bytes maybe type");23852 zig_panic("TODO buf_write_value_bytes maybe type");
22021 case ZigTypeIdErrorUnion:
22022 zig_panic("TODO buf_write_value_bytes error union");
22023 case ZigTypeIdErrorSet:
22024 zig_panic("TODO buf_write_value_bytes pure error type");
22025 case ZigTypeIdFn:23853 case ZigTypeIdFn:
22026 zig_panic("TODO buf_write_value_bytes fn type");23854 zig_panic("TODO buf_write_value_bytes fn type");
22027 case ZigTypeIdUnion:23855 case ZigTypeIdUnion:
...@@ -22210,28 +24038,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -22210,28 +24038,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
22210 zig_unreachable();24038 zig_unreachable();
22211}24039}
2221224040
22213static bool type_can_bit_cast(ZigType *t) {
22214 switch (t->id) {
22215 case ZigTypeIdInvalid:
22216 zig_unreachable();
22217 case ZigTypeIdMetaType:
22218 case ZigTypeIdOpaque:
22219 case ZigTypeIdBoundFn:
22220 case ZigTypeIdArgTuple:
22221 case ZigTypeIdUnreachable:
22222 case ZigTypeIdComptimeFloat:
22223 case ZigTypeIdComptimeInt:
22224 case ZigTypeIdEnumLiteral:
22225 case ZigTypeIdUndefined:
22226 case ZigTypeIdNull:
22227 case ZigTypeIdPointer:
22228 return false;
22229 default:
22230 // TODO list these types out explicitly, there are probably some other invalid ones here
22231 return true;
22232 }
22233}
22234
22235static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,24041static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
22236 ZigType *dest_type)24042 ZigType *dest_type)
22237{24043{
...@@ -22283,49 +24089,7 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -22283,49 +24089,7 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_
22283 return result;24089 return result;
22284 }24090 }
2228524091
22286 IrInstruction *result = ir_build_bit_cast_gen(ira, source_instr, value, dest_type);24092 return ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
22287 if (handle_is_ptr(dest_type) && !handle_is_ptr(src_type)) {
22288 ir_add_alloca(ira, result, dest_type);
22289 }
22290 return result;
22291}
22292
22293static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
22294 IrInstruction *dest_type_value = instruction->dest_type->child;
22295 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
22296 if (type_is_invalid(dest_type))
22297 return ira->codegen->invalid_instruction;
22298
22299 IrInstruction *value = instruction->value->child;
22300 ZigType *src_type = value->value.type;
22301 if (type_is_invalid(src_type))
22302 return ira->codegen->invalid_instruction;
22303
22304 if (get_codegen_ptr_type(src_type) != nullptr) {
22305 ir_add_error(ira, value,
22306 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
22307 return ira->codegen->invalid_instruction;
22308 }
22309
22310 if (!type_can_bit_cast(src_type)) {
22311 ir_add_error(ira, dest_type_value,
22312 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
22313 return ira->codegen->invalid_instruction;
22314 }
22315
22316 if (get_codegen_ptr_type(dest_type) != nullptr) {
22317 ir_add_error(ira, dest_type_value,
22318 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
22319 return ira->codegen->invalid_instruction;
22320 }
22321
22322 if (!type_can_bit_cast(dest_type)) {
22323 ir_add_error(ira, dest_type_value,
22324 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
22325 return ira->codegen->invalid_instruction;
22326 }
22327
22328 return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
22329}24093}
2233024094
22331static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,24095static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
...@@ -22395,58 +24159,15 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru...@@ -22395,58 +24159,15 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
22395static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,24159static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
22396 IrInstructionDeclRef *instruction)24160 IrInstructionDeclRef *instruction)
22397{24161{
22398 Tld *tld = instruction->tld;24162 IrInstruction *ref_instruction = ir_analyze_decl_ref(ira, &instruction->base, instruction->tld);
22399 LVal lval = instruction->lval;24163 if (type_is_invalid(ref_instruction->value.type))
22400
22401 resolve_top_level_decl(ira->codegen, tld, instruction->base.source_node);
22402 if (tld->resolution == TldResolutionInvalid)
22403 return ira->codegen->invalid_instruction;24164 return ira->codegen->invalid_instruction;
2240424165
22405 switch (tld->id) {24166 if (instruction->lval == LValPtr) {
22406 case TldIdContainer:24167 return ref_instruction;
22407 case TldIdCompTime:24168 } else {
22408 zig_unreachable();24169 return ir_get_deref(ira, &instruction->base, ref_instruction, nullptr);
22409 case TldIdVar: {
22410 TldVar *tld_var = (TldVar *)tld;
22411 ZigVar *var = tld_var->var;
22412
22413 if (var == nullptr) {
22414 return ir_error_dependency_loop(ira, &instruction->base);
22415 }
22416
22417 IrInstruction *var_ptr = ir_get_var_ptr(ira, &instruction->base, var);
22418 if (type_is_invalid(var_ptr->value.type))
22419 return ira->codegen->invalid_instruction;
22420
22421 if (tld_var->extern_lib_name != nullptr) {
22422 add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, instruction->base.source_node);
22423 }
22424
22425 if (lval == LValPtr) {
22426 return var_ptr;
22427 } else {
22428 return ir_get_deref(ira, &instruction->base, var_ptr);
22429 }
22430 }
22431 case TldIdFn: {
22432 TldFn *tld_fn = (TldFn *)tld;
22433 ZigFn *fn_entry = tld_fn->fn_entry;
22434 ir_assert(fn_entry->type_entry, &instruction->base);
22435
22436 if (tld_fn->extern_lib_name != nullptr) {
22437 add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, instruction->base.source_node);
22438 }
22439
22440 IrInstruction *ref_instruction = ir_create_const_fn(&ira->new_irb, instruction->base.scope,
22441 instruction->base.source_node, fn_entry);
22442 if (lval == LValPtr) {
22443 return ir_get_ref(ira, &instruction->base, ref_instruction, true, false);
22444 } else {
22445 return ref_instruction;
22446 }
22447 }
22448 }24170 }
22449 zig_unreachable();
22450}24171}
2245124172
22452static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionPtrToInt *instruction) {24173static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionPtrToInt *instruction) {
...@@ -22960,7 +24681,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr...@@ -22960,7 +24681,7 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr
22960 }24681 }
2296124682
22962 if (instr_is_comptime(casted_ptr)) {24683 if (instr_is_comptime(casted_ptr)) {
22963 IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr);24684 IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr, nullptr);
22964 ir_assert(result->value.type != nullptr, &instruction->base);24685 ir_assert(result->value.type != nullptr, &instruction->base);
22965 return result;24686 return result;
22966 }24687 }
...@@ -23048,70 +24769,254 @@ static IrInstruction *ir_analyze_instruction_mark_err_ret_trace_ptr(IrAnalyze *i...@@ -23048,70 +24769,254 @@ static IrInstruction *ir_analyze_instruction_mark_err_ret_trace_ptr(IrAnalyze *i
23048 return result;24769 return result;
23049}24770}
2305024771
23051static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionSqrt *instruction) {24772static void ir_eval_float_op(IrAnalyze *ira, IrInstructionFloatOp *source_instr, ZigType *float_type,
23052 ZigType *float_type = ir_resolve_type(ira, instruction->type->child);24773 ConstExprValue *op, ConstExprValue *out_val) {
23053 if (type_is_invalid(float_type))24774 assert(ira && source_instr && float_type && out_val && op);
23054 return ira->codegen->invalid_instruction;24775 assert(float_type->id == ZigTypeIdFloat ||
24776 float_type->id == ZigTypeIdComptimeFloat);
2305524777
23056 IrInstruction *op = instruction->op->child;24778 BuiltinFnId fop = source_instr->op;
23057 if (type_is_invalid(op->value.type))24779 unsigned bits;
24780
24781 switch (float_type->id) {
24782 case ZigTypeIdComptimeFloat:
24783 bits = 128;
24784 break;
24785 case ZigTypeIdFloat:
24786 bits = float_type->data.floating.bit_count;
24787 break;
24788 default:
24789 zig_unreachable();
24790 }
24791
24792 switch (bits) {
24793 case 16: {
24794 switch (fop) {
24795 case BuiltinFnIdSqrt:
24796 out_val->data.x_f16 = f16_sqrt(op->data.x_f16);
24797 break;
24798 case BuiltinFnIdSin:
24799 case BuiltinFnIdCos:
24800 case BuiltinFnIdExp:
24801 case BuiltinFnIdExp2:
24802 case BuiltinFnIdLn:
24803 case BuiltinFnIdLog10:
24804 case BuiltinFnIdLog2:
24805 case BuiltinFnIdFabs:
24806 case BuiltinFnIdFloor:
24807 case BuiltinFnIdCeil:
24808 case BuiltinFnIdTrunc:
24809 case BuiltinFnIdNearbyInt:
24810 case BuiltinFnIdRound:
24811 zig_panic("unimplemented f16 builtin");
24812 default:
24813 zig_unreachable();
24814 };
24815 break;
24816 };
24817 case 32: {
24818 switch (fop) {
24819 case BuiltinFnIdSqrt:
24820 out_val->data.x_f32 = sqrtf(op->data.x_f32);
24821 break;
24822 case BuiltinFnIdSin:
24823 out_val->data.x_f32 = sinf(op->data.x_f32);
24824 break;
24825 case BuiltinFnIdCos:
24826 out_val->data.x_f32 = cosf(op->data.x_f32);
24827 break;
24828 case BuiltinFnIdExp:
24829 out_val->data.x_f32 = expf(op->data.x_f32);
24830 break;
24831 case BuiltinFnIdExp2:
24832 out_val->data.x_f32 = exp2f(op->data.x_f32);
24833 break;
24834 case BuiltinFnIdLn:
24835 out_val->data.x_f32 = logf(op->data.x_f32);
24836 break;
24837 case BuiltinFnIdLog10:
24838 out_val->data.x_f32 = log10f(op->data.x_f32);
24839 break;
24840 case BuiltinFnIdLog2:
24841 out_val->data.x_f32 = log2f(op->data.x_f32);
24842 break;
24843 case BuiltinFnIdFabs:
24844 out_val->data.x_f32 = fabsf(op->data.x_f32);
24845 break;
24846 case BuiltinFnIdFloor:
24847 out_val->data.x_f32 = floorf(op->data.x_f32);
24848 break;
24849 case BuiltinFnIdCeil:
24850 out_val->data.x_f32 = ceilf(op->data.x_f32);
24851 break;
24852 case BuiltinFnIdTrunc:
24853 out_val->data.x_f32 = truncf(op->data.x_f32);
24854 break;
24855 case BuiltinFnIdNearbyInt:
24856 out_val->data.x_f32 = nearbyintf(op->data.x_f32);
24857 break;
24858 case BuiltinFnIdRound:
24859 out_val->data.x_f32 = roundf(op->data.x_f32);
24860 break;
24861 default:
24862 zig_unreachable();
24863 };
24864 break;
24865 };
24866 case 64: {
24867 switch (fop) {
24868 case BuiltinFnIdSqrt:
24869 out_val->data.x_f64 = sqrt(op->data.x_f64);
24870 break;
24871 case BuiltinFnIdSin:
24872 out_val->data.x_f64 = sin(op->data.x_f64);
24873 break;
24874 case BuiltinFnIdCos:
24875 out_val->data.x_f64 = cos(op->data.x_f64);
24876 break;
24877 case BuiltinFnIdExp:
24878 out_val->data.x_f64 = exp(op->data.x_f64);
24879 break;
24880 case BuiltinFnIdExp2:
24881 out_val->data.x_f64 = exp2(op->data.x_f64);
24882 break;
24883 case BuiltinFnIdLn:
24884 out_val->data.x_f64 = log(op->data.x_f64);
24885 break;
24886 case BuiltinFnIdLog10:
24887 out_val->data.x_f64 = log10(op->data.x_f64);
24888 break;
24889 case BuiltinFnIdLog2:
24890 out_val->data.x_f64 = log2(op->data.x_f64);
24891 break;
24892 case BuiltinFnIdFabs:
24893 out_val->data.x_f64 = fabs(op->data.x_f64);
24894 break;
24895 case BuiltinFnIdFloor:
24896 out_val->data.x_f64 = floor(op->data.x_f64);
24897 break;
24898 case BuiltinFnIdCeil:
24899 out_val->data.x_f64 = ceil(op->data.x_f64);
24900 break;
24901 case BuiltinFnIdTrunc:
24902 out_val->data.x_f64 = trunc(op->data.x_f64);
24903 break;
24904 case BuiltinFnIdNearbyInt:
24905 out_val->data.x_f64 = nearbyint(op->data.x_f64);
24906 break;
24907 case BuiltinFnIdRound:
24908 out_val->data.x_f64 = round(op->data.x_f64);
24909 break;
24910 default:
24911 zig_unreachable();
24912 }
24913 break;
24914 };
24915 case 128: {
24916 float128_t *out, *in;
24917 if (float_type->id == ZigTypeIdComptimeFloat) {
24918 out = &out_val->data.x_bigfloat.value;
24919 in = &op->data.x_bigfloat.value;
24920 } else {
24921 out = &out_val->data.x_f128;
24922 in = &op->data.x_f128;
24923 }
24924 switch (fop) {
24925 case BuiltinFnIdSqrt:
24926 f128M_sqrt(in, out);
24927 break;
24928 case BuiltinFnIdNearbyInt:
24929 case BuiltinFnIdSin:
24930 case BuiltinFnIdCos:
24931 case BuiltinFnIdExp:
24932 case BuiltinFnIdExp2:
24933 case BuiltinFnIdLn:
24934 case BuiltinFnIdLog10:
24935 case BuiltinFnIdLog2:
24936 case BuiltinFnIdFabs:
24937 case BuiltinFnIdFloor:
24938 case BuiltinFnIdCeil:
24939 case BuiltinFnIdTrunc:
24940 case BuiltinFnIdRound:
24941 zig_panic("unimplemented f128 builtin");
24942 default:
24943 zig_unreachable();
24944 }
24945 break;
24946 };
24947 default:
24948 zig_unreachable();
24949 }
24950}
24951
24952static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstructionFloatOp *instruction) {
24953 IrInstruction *type = instruction->type->child;
24954 if (type_is_invalid(type->value.type))
24955 return ira->codegen->invalid_instruction;
24956
24957 ZigType *expr_type = ir_resolve_type(ira, type);
24958 if (type_is_invalid(expr_type))
23058 return ira->codegen->invalid_instruction;24959 return ira->codegen->invalid_instruction;
2305924960
23060 bool ok_type = float_type->id == ZigTypeIdComptimeFloat || float_type->id == ZigTypeIdFloat;24961 // Only allow float types, and vectors of floats.
23061 if (!ok_type) {24962 ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
23062 ir_add_error(ira, instruction->type, buf_sprintf("@sqrt does not support type '%s'", buf_ptr(&float_type->name)));24963 if (float_type->id != ZigTypeIdFloat && float_type->id != ZigTypeIdComptimeFloat) {
24964 ir_add_error(ira, instruction->type, buf_sprintf("@%s does not support type '%s'", float_op_to_name(instruction->op, false), buf_ptr(&float_type->name)));
23063 return ira->codegen->invalid_instruction;24965 return ira->codegen->invalid_instruction;
23064 }24966 }
2306524967
23066 IrInstruction *casted_op = ir_implicit_cast(ira, op, float_type);24968 IrInstruction *op1 = instruction->op1->child;
23067 if (type_is_invalid(casted_op->value.type))24969 if (type_is_invalid(op1->value.type))
24970 return ira->codegen->invalid_instruction;
24971
24972 IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, float_type);
24973 if (type_is_invalid(casted_op1->value.type))
23068 return ira->codegen->invalid_instruction;24974 return ira->codegen->invalid_instruction;
2306924975
23070 if (instr_is_comptime(casted_op)) {24976 if (instr_is_comptime(casted_op1)) {
23071 ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);24977 // Our comptime 16-bit and 128-bit support is quite limited.
23072 if (!val)24978 if ((float_type->id == ZigTypeIdComptimeFloat ||
24979 float_type->data.floating.bit_count == 16 ||
24980 float_type->data.floating.bit_count == 128) &&
24981 instruction->op != BuiltinFnIdSqrt) {
24982 ir_add_error(ira, instruction->type, buf_sprintf("@%s does not support type '%s'", float_op_to_name(instruction->op, false), buf_ptr(&float_type->name)));
24983 return ira->codegen->invalid_instruction;
24984 }
24985
24986 ConstExprValue *op1_const = ir_resolve_const(ira, casted_op1, UndefBad);
24987 if (!op1_const)
23073 return ira->codegen->invalid_instruction;24988 return ira->codegen->invalid_instruction;
2307424989
23075 IrInstruction *result = ir_const(ira, &instruction->base, float_type);24990 IrInstruction *result = ir_const(ira, &instruction->base, expr_type);
23076 ConstExprValue *out_val = &result->value;24991 ConstExprValue *out_val = &result->value;
2307724992
23078 if (float_type->id == ZigTypeIdComptimeFloat) {24993 if (expr_type->id == ZigTypeIdVector) {
23079 bigfloat_sqrt(&out_val->data.x_bigfloat, &val->data.x_bigfloat);24994 expand_undef_array(ira->codegen, op1_const);
23080 } else if (float_type->id == ZigTypeIdFloat) {24995 out_val->special = ConstValSpecialUndef;
23081 switch (float_type->data.floating.bit_count) {24996 expand_undef_array(ira->codegen, out_val);
23082 case 16:24997 size_t len = expr_type->data.vector.len;
23083 out_val->data.x_f16 = f16_sqrt(val->data.x_f16);24998 for (size_t i = 0; i < len; i += 1) {
23084 break;24999 ConstExprValue *float_operand_op1 = &op1_const->data.x_array.data.s_none.elements[i];
23085 case 32:25000 ConstExprValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i];
23086 out_val->data.x_f32 = sqrtf(val->data.x_f32);25001 assert(float_operand_op1->type == float_type);
23087 break;25002 assert(float_out_val->type == float_type);
23088 case 64:25003 ir_eval_float_op(ira, instruction, float_type,
23089 out_val->data.x_f64 = sqrt(val->data.x_f64);25004 op1_const, float_out_val);
23090 break;25005 float_out_val->type = float_type;
23091 case 128:
23092 f128M_sqrt(&val->data.x_f128, &out_val->data.x_f128);
23093 break;
23094 default:
23095 zig_unreachable();
23096 }25006 }
25007 out_val->type = expr_type;
25008 out_val->special = ConstValSpecialStatic;
23097 } else {25009 } else {
23098 zig_unreachable();25010 ir_eval_float_op(ira, instruction, float_type, op1_const, out_val);
23099 }25011 }
23100
23101 return result;25012 return result;
23102 }25013 }
2310325014
23104 ir_assert(float_type->id == ZigTypeIdFloat, &instruction->base);25015 ir_assert(float_type->id == ZigTypeIdFloat, &instruction->base);
23105 if (float_type->data.floating.bit_count != 16 &&
23106 float_type->data.floating.bit_count != 32 &&
23107 float_type->data.floating.bit_count != 64) {
23108 ir_add_error(ira, instruction->type, buf_sprintf("compiler TODO: add implementation of sqrt for '%s'", buf_ptr(&float_type->name)));
23109 return ira->codegen->invalid_instruction;
23110 }
2311125016
23112 IrInstruction *result = ir_build_sqrt(&ira->new_irb, instruction->base.scope,25017 IrInstruction *result = ir_build_float_op(&ira->new_irb, instruction->base.scope,
23113 instruction->base.source_node, nullptr, casted_op);25018 instruction->base.source_node, nullptr, casted_op1, instruction->op);
23114 result->value.type = float_type;25019 result->value.type = expr_type;
23115 return result;25020 return result;
23116}25021}
2311725022
...@@ -23314,12 +25219,56 @@ static IrInstruction *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, Ir...@@ -23314,12 +25219,56 @@ static IrInstruction *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, Ir
23314 return ira->codegen->invalid_instruction;25219 return ira->codegen->invalid_instruction;
23315}25220}
2331625221
23317static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {25222static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstructionEndExpr *instruction) {
25223 IrInstruction *value = instruction->value->child;
25224 if (type_is_invalid(value->value.type))
25225 return ira->codegen->invalid_instruction;
25226
25227 bool was_written = instruction->result_loc->written;
25228 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
25229 value->value.type, value, false, false);
25230 if (result_loc != nullptr) {
25231 if (type_is_invalid(result_loc->value.type))
25232 return ira->codegen->invalid_instruction;
25233 if (result_loc->value.type->id == ZigTypeIdUnreachable)
25234 return result_loc;
25235
25236 if (!was_written) {
25237 IrInstruction *store_ptr = ir_analyze_store_ptr(ira, &instruction->base, result_loc, value);
25238 if (type_is_invalid(store_ptr->value.type)) {
25239 return ira->codegen->invalid_instruction;
25240 }
25241 }
25242
25243 if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
25244 if (instr_is_comptime(value)) {
25245 result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
25246 } else {
25247 result_loc->value.special = ConstValSpecialRuntime;
25248 }
25249 }
25250 }
25251
25252 return ir_const_void(ira, &instruction->base);
25253}
25254
25255static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) {
25256 IrInstruction *operand = instruction->operand->child;
25257 if (type_is_invalid(operand->value.type))
25258 return operand;
25259
25260 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base,
25261 &instruction->result_loc_bit_cast->base, operand->value.type, operand, false, false);
25262 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
25263 return result_loc;
25264
25265 return instruction->result_loc_bit_cast->parent->gen_instruction;
25266}
25267
25268static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
23318 switch (instruction->id) {25269 switch (instruction->id) {
23319 case IrInstructionIdInvalid:25270 case IrInstructionIdInvalid:
23320 case IrInstructionIdWidenOrShorten:25271 case IrInstructionIdWidenOrShorten:
23321 case IrInstructionIdStructInit:
23322 case IrInstructionIdUnionInit:
23323 case IrInstructionIdStructFieldPtr:25272 case IrInstructionIdStructFieldPtr:
23324 case IrInstructionIdUnionFieldPtr:25273 case IrInstructionIdUnionFieldPtr:
23325 case IrInstructionIdOptionalWrap:25274 case IrInstructionIdOptionalWrap:
...@@ -23331,11 +25280,18 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23331,11 +25280,18 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23331 case IrInstructionIdCmpxchgGen:25280 case IrInstructionIdCmpxchgGen:
23332 case IrInstructionIdArrayToVector:25281 case IrInstructionIdArrayToVector:
23333 case IrInstructionIdVectorToArray:25282 case IrInstructionIdVectorToArray:
25283 case IrInstructionIdPtrOfArrayToSlice:
23334 case IrInstructionIdAssertZero:25284 case IrInstructionIdAssertZero:
23335 case IrInstructionIdAssertNonNull:25285 case IrInstructionIdAssertNonNull:
23336 case IrInstructionIdResizeSlice:25286 case IrInstructionIdResizeSlice:
23337 case IrInstructionIdLoadPtrGen:25287 case IrInstructionIdLoadPtrGen:
23338 case IrInstructionIdBitCastGen:25288 case IrInstructionIdBitCastGen:
25289 case IrInstructionIdCallGen:
25290 case IrInstructionIdReturnPtr:
25291 case IrInstructionIdAllocaGen:
25292 case IrInstructionIdSliceGen:
25293 case IrInstructionIdRefGen:
25294 case IrInstructionIdTestErrGen:
23339 zig_unreachable();25295 zig_unreachable();
2334025296
23341 case IrInstructionIdReturn:25297 case IrInstructionIdReturn:
...@@ -23358,8 +25314,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23358,8 +25314,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23358 return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction);25314 return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction);
23359 case IrInstructionIdFieldPtr:25315 case IrInstructionIdFieldPtr:
23360 return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);25316 return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);
23361 case IrInstructionIdCall:25317 case IrInstructionIdCallSrc:
23362 return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);25318 return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction);
23363 case IrInstructionIdBr:25319 case IrInstructionIdBr:
23364 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);25320 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);
23365 case IrInstructionIdCondBr:25321 case IrInstructionIdCondBr:
...@@ -23370,10 +25326,6 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23370,10 +25326,6 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23370 return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction);25326 return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction);
23371 case IrInstructionIdTypeOf:25327 case IrInstructionIdTypeOf:
23372 return ir_analyze_instruction_typeof(ira, (IrInstructionTypeOf *)instruction);25328 return ir_analyze_instruction_typeof(ira, (IrInstructionTypeOf *)instruction);
23373 case IrInstructionIdToPtrType:
23374 return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction);
23375 case IrInstructionIdPtrTypeChild:
23376 return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
23377 case IrInstructionIdSetCold:25329 case IrInstructionIdSetCold:
23378 return ir_analyze_instruction_set_cold(ira, (IrInstructionSetCold *)instruction);25330 return ir_analyze_instruction_set_cold(ira, (IrInstructionSetCold *)instruction);
23379 case IrInstructionIdSetRuntimeSafety:25331 case IrInstructionIdSetRuntimeSafety:
...@@ -23474,8 +25426,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23474,8 +25426,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23474 return ir_analyze_instruction_memset(ira, (IrInstructionMemset *)instruction);25426 return ir_analyze_instruction_memset(ira, (IrInstructionMemset *)instruction);
23475 case IrInstructionIdMemcpy:25427 case IrInstructionIdMemcpy:
23476 return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction);25428 return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction);
23477 case IrInstructionIdSlice:25429 case IrInstructionIdSliceSrc:
23478 return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction);25430 return ir_analyze_instruction_slice(ira, (IrInstructionSliceSrc *)instruction);
23479 case IrInstructionIdMemberCount:25431 case IrInstructionIdMemberCount:
23480 return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction);25432 return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction);
23481 case IrInstructionIdMemberType:25433 case IrInstructionIdMemberType:
...@@ -23494,8 +25446,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23494,8 +25446,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23494 return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);25446 return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
23495 case IrInstructionIdOverflowOp:25447 case IrInstructionIdOverflowOp:
23496 return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction);25448 return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction);
23497 case IrInstructionIdTestErr:25449 case IrInstructionIdTestErrSrc:
23498 return ir_analyze_instruction_test_err(ira, (IrInstructionTestErr *)instruction);25450 return ir_analyze_instruction_test_err(ira, (IrInstructionTestErrSrc *)instruction);
23499 case IrInstructionIdUnwrapErrCode:25451 case IrInstructionIdUnwrapErrCode:
23500 return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction);25452 return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction);
23501 case IrInstructionIdUnwrapErrPayload:25453 case IrInstructionIdUnwrapErrPayload:
...@@ -23514,8 +25466,6 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23514,8 +25466,6 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23514 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);25466 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
23515 case IrInstructionIdPtrCastSrc:25467 case IrInstructionIdPtrCastSrc:
23516 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);25468 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);
23517 case IrInstructionIdBitCast:
23518 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
23519 case IrInstructionIdIntToPtr:25469 case IrInstructionIdIntToPtr:
23520 return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction);25470 return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction);
23521 case IrInstructionIdPtrToInt:25471 case IrInstructionIdPtrToInt:
...@@ -23538,6 +25488,14 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23538,6 +25488,14 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23538 return ir_analyze_instruction_ptr_type(ira, (IrInstructionPtrType *)instruction);25488 return ir_analyze_instruction_ptr_type(ira, (IrInstructionPtrType *)instruction);
23539 case IrInstructionIdAlignCast:25489 case IrInstructionIdAlignCast:
23540 return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);25490 return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
25491 case IrInstructionIdImplicitCast:
25492 return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction);
25493 case IrInstructionIdResolveResult:
25494 return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);
25495 case IrInstructionIdResetResult:
25496 return ir_analyze_instruction_reset_result(ira, (IrInstructionResetResult *)instruction);
25497 case IrInstructionIdResultPtr:
25498 return ir_analyze_instruction_result_ptr(ira, (IrInstructionResultPtr *)instruction);
23541 case IrInstructionIdOpaqueType:25499 case IrInstructionIdOpaqueType:
23542 return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);25500 return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
23543 case IrInstructionIdSetAlignStack:25501 case IrInstructionIdSetAlignStack:
...@@ -23596,8 +25554,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23596,8 +25554,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23596 return ir_analyze_instruction_merge_err_ret_traces(ira, (IrInstructionMergeErrRetTraces *)instruction);25554 return ir_analyze_instruction_merge_err_ret_traces(ira, (IrInstructionMergeErrRetTraces *)instruction);
23597 case IrInstructionIdMarkErrRetTracePtr:25555 case IrInstructionIdMarkErrRetTracePtr:
23598 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);25556 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
23599 case IrInstructionIdSqrt:25557 case IrInstructionIdFloatOp:
23600 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);25558 return ir_analyze_instruction_float_op(ira, (IrInstructionFloatOp *)instruction);
25559 case IrInstructionIdMulAdd:
25560 return ir_analyze_instruction_mul_add(ira, (IrInstructionMulAdd *)instruction);
23601 case IrInstructionIdIntToErr:25561 case IrInstructionIdIntToErr:
23602 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);25562 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
23603 case IrInstructionIdErrToInt:25563 case IrInstructionIdErrToInt:
...@@ -23612,17 +25572,16 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23612,17 +25572,16 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23612 return ir_analyze_instruction_has_decl(ira, (IrInstructionHasDecl *)instruction);25572 return ir_analyze_instruction_has_decl(ira, (IrInstructionHasDecl *)instruction);
23613 case IrInstructionIdUndeclaredIdent:25573 case IrInstructionIdUndeclaredIdent:
23614 return ir_analyze_instruction_undeclared_ident(ira, (IrInstructionUndeclaredIdent *)instruction);25574 return ir_analyze_instruction_undeclared_ident(ira, (IrInstructionUndeclaredIdent *)instruction);
25575 case IrInstructionIdAllocaSrc:
25576 return nullptr;
25577 case IrInstructionIdEndExpr:
25578 return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction);
25579 case IrInstructionIdBitCastSrc:
25580 return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction);
23615 }25581 }
23616 zig_unreachable();25582 zig_unreachable();
23617}25583}
2361825584
23619static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *old_instruction) {
23620 IrInstruction *new_instruction = ir_analyze_instruction_nocast(ira, old_instruction);
23621 ir_assert(new_instruction->value.type != nullptr, old_instruction);
23622 old_instruction->child = new_instruction;
23623 return new_instruction;
23624}
23625
23626// This function attempts to evaluate IR code while doing type checking and other analysis.25585// This function attempts to evaluate IR code while doing type checking and other analysis.
23627// It emits a new IrExecutable which is partially evaluated IR code.25586// It emits a new IrExecutable which is partially evaluated IR code.
23628ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,25587ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,
...@@ -23668,14 +25627,22 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_...@@ -23668,14 +25627,22 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
23668 continue;25627 continue;
23669 }25628 }
2367025629
23671 IrInstruction *new_instruction = ir_analyze_instruction(ira, old_instruction);25630 if (ira->codegen->verbose_ir) {
23672 if (type_is_invalid(new_instruction->value.type) && ir_should_inline(new_exec, old_instruction->scope)) {25631 fprintf(stderr, "analyze #%zu\n", old_instruction->debug_id);
23673 return ira->codegen->builtin_types.entry_invalid;
23674 }25632 }
25633 IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);
25634 if (new_instruction != nullptr) {
25635 ir_assert(new_instruction->value.type != nullptr || new_instruction->value.type != nullptr, old_instruction);
25636 old_instruction->child = new_instruction;
2367525637
23676 // unreachable instructions do their own control flow.25638 if (type_is_invalid(new_instruction->value.type)) {
23677 if (new_instruction->value.type->id == ZigTypeIdUnreachable)25639 return ira->codegen->builtin_types.entry_invalid;
23678 continue;25640 }
25641
25642 // unreachable instructions do their own control flow.
25643 if (new_instruction->value.type->id == ZigTypeIdUnreachable)
25644 continue;
25645 }
2367925646
23680 ira->instruction_index += 1;25647 ira->instruction_index += 1;
23681 }25648 }
...@@ -23700,7 +25667,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23700,7 +25667,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23700 case IrInstructionIdDeclVarSrc:25667 case IrInstructionIdDeclVarSrc:
23701 case IrInstructionIdDeclVarGen:25668 case IrInstructionIdDeclVarGen:
23702 case IrInstructionIdStorePtr:25669 case IrInstructionIdStorePtr:
23703 case IrInstructionIdCall:25670 case IrInstructionIdCallSrc:
25671 case IrInstructionIdCallGen:
23704 case IrInstructionIdReturn:25672 case IrInstructionIdReturn:
23705 case IrInstructionIdUnreachable:25673 case IrInstructionIdUnreachable:
23706 case IrInstructionIdSetCold:25674 case IrInstructionIdSetCold:
...@@ -23747,27 +25715,28 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23747,27 +25715,28 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23747 case IrInstructionIdResizeSlice:25715 case IrInstructionIdResizeSlice:
23748 case IrInstructionIdGlobalAsm:25716 case IrInstructionIdGlobalAsm:
23749 case IrInstructionIdUndeclaredIdent:25717 case IrInstructionIdUndeclaredIdent:
25718 case IrInstructionIdEndExpr:
25719 case IrInstructionIdPtrOfArrayToSlice:
25720 case IrInstructionIdSliceGen:
25721 case IrInstructionIdOptionalWrap:
25722 case IrInstructionIdVectorToArray:
25723 case IrInstructionIdResetResult:
23750 return true;25724 return true;
2375125725
23752 case IrInstructionIdPhi:25726 case IrInstructionIdPhi:
23753 case IrInstructionIdUnOp:25727 case IrInstructionIdUnOp:
23754 case IrInstructionIdBinOp:25728 case IrInstructionIdBinOp:
23755 case IrInstructionIdLoadPtr:25729 case IrInstructionIdLoadPtr:
23756 case IrInstructionIdLoadPtrGen:
23757 case IrInstructionIdConst:25730 case IrInstructionIdConst:
23758 case IrInstructionIdCast:25731 case IrInstructionIdCast:
23759 case IrInstructionIdContainerInitList:25732 case IrInstructionIdContainerInitList:
23760 case IrInstructionIdContainerInitFields:25733 case IrInstructionIdContainerInitFields:
23761 case IrInstructionIdStructInit:
23762 case IrInstructionIdUnionInit:
23763 case IrInstructionIdFieldPtr:25734 case IrInstructionIdFieldPtr:
23764 case IrInstructionIdElemPtr:25735 case IrInstructionIdElemPtr:
23765 case IrInstructionIdVarPtr:25736 case IrInstructionIdVarPtr:
25737 case IrInstructionIdReturnPtr:
23766 case IrInstructionIdTypeOf:25738 case IrInstructionIdTypeOf:
23767 case IrInstructionIdToPtrType:
23768 case IrInstructionIdPtrTypeChild:
23769 case IrInstructionIdStructFieldPtr:25739 case IrInstructionIdStructFieldPtr:
23770 case IrInstructionIdUnionFieldPtr:
23771 case IrInstructionIdArrayType:25740 case IrInstructionIdArrayType:
23772 case IrInstructionIdPromiseType:25741 case IrInstructionIdPromiseType:
23773 case IrInstructionIdSliceType:25742 case IrInstructionIdSliceType:
...@@ -23789,7 +25758,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23789,7 +25758,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23789 case IrInstructionIdIntType:25758 case IrInstructionIdIntType:
23790 case IrInstructionIdVectorType:25759 case IrInstructionIdVectorType:
23791 case IrInstructionIdBoolNot:25760 case IrInstructionIdBoolNot:
23792 case IrInstructionIdSlice:25761 case IrInstructionIdSliceSrc:
23793 case IrInstructionIdMemberCount:25762 case IrInstructionIdMemberCount:
23794 case IrInstructionIdMemberType:25763 case IrInstructionIdMemberType:
23795 case IrInstructionIdMemberName:25764 case IrInstructionIdMemberName:
...@@ -23797,16 +25766,13 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23797,16 +25766,13 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23797 case IrInstructionIdReturnAddress:25766 case IrInstructionIdReturnAddress:
23798 case IrInstructionIdFrameAddress:25767 case IrInstructionIdFrameAddress:
23799 case IrInstructionIdHandle:25768 case IrInstructionIdHandle:
23800 case IrInstructionIdTestErr:25769 case IrInstructionIdTestErrSrc:
23801 case IrInstructionIdUnwrapErrCode:25770 case IrInstructionIdTestErrGen:
23802 case IrInstructionIdOptionalWrap:
23803 case IrInstructionIdErrWrapCode:
23804 case IrInstructionIdErrWrapPayload:
23805 case IrInstructionIdFnProto:25771 case IrInstructionIdFnProto:
23806 case IrInstructionIdTestComptime:25772 case IrInstructionIdTestComptime:
23807 case IrInstructionIdPtrCastSrc:25773 case IrInstructionIdPtrCastSrc:
23808 case IrInstructionIdPtrCastGen:25774 case IrInstructionIdPtrCastGen:
23809 case IrInstructionIdBitCast:25775 case IrInstructionIdBitCastSrc:
23810 case IrInstructionIdBitCastGen:25776 case IrInstructionIdBitCastGen:
23811 case IrInstructionIdWidenOrShorten:25777 case IrInstructionIdWidenOrShorten:
23812 case IrInstructionIdPtrToInt:25778 case IrInstructionIdPtrToInt:
...@@ -23824,6 +25790,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23824,6 +25790,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23824 case IrInstructionIdTypeInfo:25790 case IrInstructionIdTypeInfo:
23825 case IrInstructionIdTypeId:25791 case IrInstructionIdTypeId:
23826 case IrInstructionIdAlignCast:25792 case IrInstructionIdAlignCast:
25793 case IrInstructionIdImplicitCast:
25794 case IrInstructionIdResolveResult:
23827 case IrInstructionIdOpaqueType:25795 case IrInstructionIdOpaqueType:
23828 case IrInstructionIdArgType:25796 case IrInstructionIdArgType:
23829 case IrInstructionIdTagType:25797 case IrInstructionIdTagType:
...@@ -23836,7 +25804,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23836,7 +25804,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23836 case IrInstructionIdCoroFree:25804 case IrInstructionIdCoroFree:
23837 case IrInstructionIdCoroPromise:25805 case IrInstructionIdCoroPromise:
23838 case IrInstructionIdPromiseResultType:25806 case IrInstructionIdPromiseResultType:
23839 case IrInstructionIdSqrt:25807 case IrInstructionIdFloatOp:
25808 case IrInstructionIdMulAdd:
23840 case IrInstructionIdAtomicLoad:25809 case IrInstructionIdAtomicLoad:
23841 case IrInstructionIdIntCast:25810 case IrInstructionIdIntCast:
23842 case IrInstructionIdFloatCast:25811 case IrInstructionIdFloatCast:
...@@ -23847,9 +25816,11 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23847,9 +25816,11 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23847 case IrInstructionIdFromBytes:25816 case IrInstructionIdFromBytes:
23848 case IrInstructionIdToBytes:25817 case IrInstructionIdToBytes:
23849 case IrInstructionIdEnumToInt:25818 case IrInstructionIdEnumToInt:
23850 case IrInstructionIdVectorToArray:
23851 case IrInstructionIdArrayToVector:25819 case IrInstructionIdArrayToVector:
23852 case IrInstructionIdHasDecl:25820 case IrInstructionIdHasDecl:
25821 case IrInstructionIdAllocaSrc:
25822 case IrInstructionIdAllocaGen:
25823 case IrInstructionIdResultPtr:
23853 return false;25824 return false;
2385425825
23855 case IrInstructionIdAsm:25826 case IrInstructionIdAsm:
...@@ -23861,8 +25832,21 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23861,8 +25832,21 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23861 {25832 {
23862 IrInstructionUnwrapErrPayload *unwrap_err_payload_instruction =25833 IrInstructionUnwrapErrPayload *unwrap_err_payload_instruction =
23863 (IrInstructionUnwrapErrPayload *)instruction;25834 (IrInstructionUnwrapErrPayload *)instruction;
23864 return unwrap_err_payload_instruction->safety_check_on;25835 return unwrap_err_payload_instruction->safety_check_on ||
25836 unwrap_err_payload_instruction->initializing;
23865 }25837 }
25838 case IrInstructionIdUnwrapErrCode:
25839 return reinterpret_cast<IrInstructionUnwrapErrCode *>(instruction)->initializing;
25840 case IrInstructionIdUnionFieldPtr:
25841 return reinterpret_cast<IrInstructionUnionFieldPtr *>(instruction)->initializing;
25842 case IrInstructionIdErrWrapPayload:
25843 return reinterpret_cast<IrInstructionErrWrapPayload *>(instruction)->result_loc != nullptr;
25844 case IrInstructionIdErrWrapCode:
25845 return reinterpret_cast<IrInstructionErrWrapCode *>(instruction)->result_loc != nullptr;
25846 case IrInstructionIdLoadPtrGen:
25847 return reinterpret_cast<IrInstructionLoadPtrGen *>(instruction)->result_loc != nullptr;
25848 case IrInstructionIdRefGen:
25849 return reinterpret_cast<IrInstructionRefGen *>(instruction)->result_loc != nullptr;
23866 }25850 }
23867 zig_unreachable();25851 zig_unreachable();
23868}25852}
src/ir.hpp+1
...@@ -26,5 +26,6 @@ bool ir_has_side_effects(IrInstruction *instruction);...@@ -26,5 +26,6 @@ bool ir_has_side_effects(IrInstruction *instruction);
26struct IrAnalyze;26struct IrAnalyze;
27ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprValue *const_val,27ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprValue *const_val,
28 AstNode *source_node);28 AstNode *source_node);
29const char *float_op_to_name(BuiltinFnId op, bool llvm_name);
2930
30#endif31#endif
src/ir_print.cpp+278-95
...@@ -57,13 +57,18 @@ static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction)...@@ -57,13 +57,18 @@ static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction)
57}57}
5858
59static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {59static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
60 fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id);60 if (bb == nullptr) {
61 fprintf(irp->f, "(null block)");
62 } else {
63 fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id);
64 }
61}65}
6266
63static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {67static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
64 assert(return_instruction->value);
65 fprintf(irp->f, "return ");68 fprintf(irp->f, "return ");
66 ir_print_other_instruction(irp, return_instruction->value);69 if (return_instruction->value != nullptr) {
70 ir_print_other_instruction(irp, return_instruction->value);
71 }
67}72}
6873
69static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {74static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
...@@ -188,7 +193,7 @@ static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_va...@@ -188,7 +193,7 @@ static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_va
188 fprintf(irp->f, " ");193 fprintf(irp->f, " ");
189 }194 }
190 fprintf(irp->f, "= ");195 fprintf(irp->f, "= ");
191 ir_print_other_instruction(irp, decl_var_instruction->init_value);196 ir_print_other_instruction(irp, decl_var_instruction->ptr);
192 if (decl_var_instruction->var->is_comptime != nullptr) {197 if (decl_var_instruction->var->is_comptime != nullptr) {
193 fprintf(irp->f, " // comptime = ");198 fprintf(irp->f, " // comptime = ");
194 ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);199 ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
...@@ -201,7 +206,56 @@ static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {...@@ -201,7 +206,56 @@ static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
201 fprintf(irp->f, " to %s", buf_ptr(&cast_instruction->dest_type->name));206 fprintf(irp->f, " to %s", buf_ptr(&cast_instruction->dest_type->name));
202}207}
203208
204static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {209static void ir_print_result_loc_var(IrPrint *irp, ResultLocVar *result_loc_var) {
210 fprintf(irp->f, "var(");
211 ir_print_other_instruction(irp, result_loc_var->base.source_instruction);
212 fprintf(irp->f, ")");
213}
214
215static void ir_print_result_loc_instruction(IrPrint *irp, ResultLocInstruction *result_loc_inst) {
216 fprintf(irp->f, "inst(");
217 ir_print_other_instruction(irp, result_loc_inst->base.source_instruction);
218 fprintf(irp->f, ")");
219}
220
221static void ir_print_result_loc_peer(IrPrint *irp, ResultLocPeer *result_loc_peer) {
222 fprintf(irp->f, "peer(next=");
223 ir_print_other_block(irp, result_loc_peer->next_bb);
224 fprintf(irp->f, ")");
225}
226
227static void ir_print_result_loc_bit_cast(IrPrint *irp, ResultLocBitCast *result_loc_bit_cast) {
228 fprintf(irp->f, "bitcast(ty=");
229 ir_print_other_instruction(irp, result_loc_bit_cast->base.source_instruction);
230 fprintf(irp->f, ")");
231}
232
233static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
234 switch (result_loc->id) {
235 case ResultLocIdInvalid:
236 zig_unreachable();
237 case ResultLocIdNone:
238 fprintf(irp->f, "none");
239 return;
240 case ResultLocIdReturn:
241 fprintf(irp->f, "return");
242 return;
243 case ResultLocIdVar:
244 return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc);
245 case ResultLocIdInstruction:
246 return ir_print_result_loc_instruction(irp, (ResultLocInstruction *)result_loc);
247 case ResultLocIdPeer:
248 return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc);
249 case ResultLocIdBitCast:
250 return ir_print_result_loc_bit_cast(irp, (ResultLocBitCast *)result_loc);
251 case ResultLocIdPeerParent:
252 fprintf(irp->f, "peer_parent");
253 return;
254 }
255 zig_unreachable();
256}
257
258static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {
205 if (call_instruction->is_async) {259 if (call_instruction->is_async) {
206 fprintf(irp->f, "async");260 fprintf(irp->f, "async");
207 if (call_instruction->async_allocator != nullptr) {261 if (call_instruction->async_allocator != nullptr) {
...@@ -224,7 +278,35 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {...@@ -224,7 +278,35 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
224 fprintf(irp->f, ", ");278 fprintf(irp->f, ", ");
225 ir_print_other_instruction(irp, arg);279 ir_print_other_instruction(irp, arg);
226 }280 }
227 fprintf(irp->f, ")");281 fprintf(irp->f, ")result=");
282 ir_print_result_loc(irp, call_instruction->result_loc);
283}
284
285static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instruction) {
286 if (call_instruction->is_async) {
287 fprintf(irp->f, "async");
288 if (call_instruction->async_allocator != nullptr) {
289 fprintf(irp->f, "<");
290 ir_print_other_instruction(irp, call_instruction->async_allocator);
291 fprintf(irp->f, ">");
292 }
293 fprintf(irp->f, " ");
294 }
295 if (call_instruction->fn_entry) {
296 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
297 } else {
298 assert(call_instruction->fn_ref);
299 ir_print_other_instruction(irp, call_instruction->fn_ref);
300 }
301 fprintf(irp->f, "(");
302 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
303 IrInstruction *arg = call_instruction->args[i];
304 if (i != 0)
305 fprintf(irp->f, ", ");
306 ir_print_other_instruction(irp, arg);
307 }
308 fprintf(irp->f, ")result=");
309 ir_print_other_instruction(irp, call_instruction->result_loc);
228}310}
229311
230static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {312static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
...@@ -270,10 +352,10 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni...@@ -270,10 +352,10 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni
270 fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);352 fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);
271 } else {353 } else {
272 for (size_t i = 0; i < instruction->item_count; i += 1) {354 for (size_t i = 0; i < instruction->item_count; i += 1) {
273 IrInstruction *item = instruction->items[i];355 IrInstruction *result_loc = instruction->elem_result_loc_list[i];
274 if (i != 0)356 if (i != 0)
275 fprintf(irp->f, ", ");357 fprintf(irp->f, ", ");
276 ir_print_other_instruction(irp, item);358 ir_print_other_instruction(irp, result_loc);
277 }359 }
278 }360 }
279 fprintf(irp->f, "}");361 fprintf(irp->f, "}");
...@@ -286,32 +368,11 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI...@@ -286,32 +368,11 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
286 IrInstructionContainerInitFieldsField *field = &instruction->fields[i];368 IrInstructionContainerInitFieldsField *field = &instruction->fields[i];
287 const char *comma = (i == 0) ? "" : ", ";369 const char *comma = (i == 0) ? "" : ", ";
288 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));370 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));
289 ir_print_other_instruction(irp, field->value);371 ir_print_other_instruction(irp, field->result_loc);
290 }372 }
291 fprintf(irp->f, "} // container init");373 fprintf(irp->f, "} // container init");
292}374}
293375
294static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruction) {
295 fprintf(irp->f, "%s {", buf_ptr(&instruction->struct_type->name));
296 for (size_t i = 0; i < instruction->field_count; i += 1) {
297 IrInstructionStructInitField *field = &instruction->fields[i];
298 Buf *field_name = field->type_struct_field->name;
299 const char *comma = (i == 0) ? "" : ", ";
300 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field_name));
301 ir_print_other_instruction(irp, field->value);
302 }
303 fprintf(irp->f, "} // struct init");
304}
305
306static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) {
307 Buf *field_name = instruction->field->enum_field->name;
308
309 fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name));
310 fprintf(irp->f, ".%s = ", buf_ptr(field_name));
311 ir_print_other_instruction(irp, instruction->init_value);
312 fprintf(irp->f, "} // union init");
313}
314
315static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {376static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {
316 fprintf(irp->f, "unreachable");377 fprintf(irp->f, "unreachable");
317}378}
...@@ -331,14 +392,20 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {...@@ -331,14 +392,20 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
331 fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name));392 fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name));
332}393}
333394
395static void ir_print_return_ptr(IrPrint *irp, IrInstructionReturnPtr *instruction) {
396 fprintf(irp->f, "@ReturnPtr");
397}
398
334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {399static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
335 ir_print_other_instruction(irp, instruction->ptr);400 ir_print_other_instruction(irp, instruction->ptr);
336 fprintf(irp->f, ".*");401 fprintf(irp->f, ".*");
337}402}
338403
339static void ir_print_load_ptr_gen(IrPrint *irp, IrInstructionLoadPtrGen *instruction) {404static void ir_print_load_ptr_gen(IrPrint *irp, IrInstructionLoadPtrGen *instruction) {
405 fprintf(irp->f, "loadptr(");
340 ir_print_other_instruction(irp, instruction->ptr);406 ir_print_other_instruction(irp, instruction->ptr);
341 fprintf(irp->f, ".*");407 fprintf(irp->f, ")result=");
408 ir_print_other_instruction(irp, instruction->result_loc);
342}409}
343410
344static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {411static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
...@@ -354,18 +421,6 @@ static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {...@@ -354,18 +421,6 @@ static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {
354 fprintf(irp->f, ")");421 fprintf(irp->f, ")");
355}422}
356423
357static void ir_print_to_ptr_type(IrPrint *irp, IrInstructionToPtrType *instruction) {
358 fprintf(irp->f, "@toPtrType(");
359 ir_print_other_instruction(irp, instruction->ptr);
360 fprintf(irp->f, ")");
361}
362
363static void ir_print_ptr_type_child(IrPrint *irp, IrInstructionPtrTypeChild *instruction) {
364 fprintf(irp->f, "@ptrTypeChild(");
365 ir_print_other_instruction(irp, instruction->value);
366 fprintf(irp->f, ")");
367}
368
369static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) {424static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) {
370 if (instruction->field_name_buffer) {425 if (instruction->field_name_buffer) {
371 fprintf(irp->f, "fieldptr ");426 fprintf(irp->f, "fieldptr ");
...@@ -618,6 +673,13 @@ static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {...@@ -618,6 +673,13 @@ static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
618 ir_print_other_instruction(irp, instruction->value);673 ir_print_other_instruction(irp, instruction->value);
619}674}
620675
676static void ir_print_ref_gen(IrPrint *irp, IrInstructionRefGen *instruction) {
677 fprintf(irp->f, "@ref(");
678 ir_print_other_instruction(irp, instruction->operand);
679 fprintf(irp->f, ")result=");
680 ir_print_other_instruction(irp, instruction->result_loc);
681}
682
621static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruction) {683static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruction) {
622 fprintf(irp->f, "@compileError(");684 fprintf(irp->f, "@compileError(");
623 ir_print_other_instruction(irp, instruction->msg);685 ir_print_other_instruction(irp, instruction->msg);
...@@ -682,7 +744,8 @@ static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruct...@@ -682,7 +744,8 @@ static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruct
682 ir_print_other_instruction(irp, instruction->success_order_value);744 ir_print_other_instruction(irp, instruction->success_order_value);
683 fprintf(irp->f, ", ");745 fprintf(irp->f, ", ");
684 ir_print_other_instruction(irp, instruction->failure_order_value);746 ir_print_other_instruction(irp, instruction->failure_order_value);
685 fprintf(irp->f, ")");747 fprintf(irp->f, ")result=");
748 ir_print_result_loc(irp, instruction->result_loc);
686}749}
687750
688static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {751static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
...@@ -692,7 +755,8 @@ static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruct...@@ -692,7 +755,8 @@ static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruct
692 ir_print_other_instruction(irp, instruction->cmp_value);755 ir_print_other_instruction(irp, instruction->cmp_value);
693 fprintf(irp->f, ", ");756 fprintf(irp->f, ", ");
694 ir_print_other_instruction(irp, instruction->new_value);757 ir_print_other_instruction(irp, instruction->new_value);
695 fprintf(irp->f, ", TODO print atomic orders)");758 fprintf(irp->f, ", TODO print atomic orders)result=");
759 ir_print_other_instruction(irp, instruction->result_loc);
696}760}
697761
698static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {762static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
...@@ -810,14 +874,26 @@ static void ir_print_memcpy(IrPrint *irp, IrInstructionMemcpy *instruction) {...@@ -810,14 +874,26 @@ static void ir_print_memcpy(IrPrint *irp, IrInstructionMemcpy *instruction) {
810 fprintf(irp->f, ")");874 fprintf(irp->f, ")");
811}875}
812876
813static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) {877static void ir_print_slice_src(IrPrint *irp, IrInstructionSliceSrc *instruction) {
814 ir_print_other_instruction(irp, instruction->ptr);878 ir_print_other_instruction(irp, instruction->ptr);
815 fprintf(irp->f, "[");879 fprintf(irp->f, "[");
816 ir_print_other_instruction(irp, instruction->start);880 ir_print_other_instruction(irp, instruction->start);
817 fprintf(irp->f, "..");881 fprintf(irp->f, "..");
818 if (instruction->end)882 if (instruction->end)
819 ir_print_other_instruction(irp, instruction->end);883 ir_print_other_instruction(irp, instruction->end);
820 fprintf(irp->f, "]");884 fprintf(irp->f, "]result=");
885 ir_print_result_loc(irp, instruction->result_loc);
886}
887
888static void ir_print_slice_gen(IrPrint *irp, IrInstructionSliceGen *instruction) {
889 ir_print_other_instruction(irp, instruction->ptr);
890 fprintf(irp->f, "[");
891 ir_print_other_instruction(irp, instruction->start);
892 fprintf(irp->f, "..");
893 if (instruction->end)
894 ir_print_other_instruction(irp, instruction->end);
895 fprintf(irp->f, "]result=");
896 ir_print_other_instruction(irp, instruction->result_loc);
821}897}
822898
823static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) {899static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) {
...@@ -889,43 +965,49 @@ static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruct...@@ -889,43 +965,49 @@ static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruct
889 fprintf(irp->f, ")");965 fprintf(irp->f, ")");
890}966}
891967
892static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {968static void ir_print_test_err_src(IrPrint *irp, IrInstructionTestErrSrc *instruction) {
893 fprintf(irp->f, "@testError(");969 fprintf(irp->f, "@testError(");
894 ir_print_other_instruction(irp, instruction->value);970 ir_print_other_instruction(irp, instruction->base_ptr);
971 fprintf(irp->f, ")");
972}
973
974static void ir_print_test_err_gen(IrPrint *irp, IrInstructionTestErrGen *instruction) {
975 fprintf(irp->f, "@testError(");
976 ir_print_other_instruction(irp, instruction->err_union);
895 fprintf(irp->f, ")");977 fprintf(irp->f, ")");
896}978}
897979
898static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {980static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
899 fprintf(irp->f, "UnwrapErrorCode(");981 fprintf(irp->f, "UnwrapErrorCode(");
900 ir_print_other_instruction(irp, instruction->err_union);982 ir_print_other_instruction(irp, instruction->err_union_ptr);
901 fprintf(irp->f, ")");983 fprintf(irp->f, ")");
902}984}
903985
904static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {986static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
905 fprintf(irp->f, "ErrorUnionFieldPayload(");987 fprintf(irp->f, "ErrorUnionFieldPayload(");
906 ir_print_other_instruction(irp, instruction->value);988 ir_print_other_instruction(irp, instruction->value);
907 fprintf(irp->f, ")");989 fprintf(irp->f, ")safety=%d,init=%d",instruction->safety_check_on, instruction->initializing);
908 if (!instruction->safety_check_on) {
909 fprintf(irp->f, " // no safety");
910 }
911}990}
912991
913static void ir_print_maybe_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) {992static void ir_print_optional_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) {
914 fprintf(irp->f, "@maybeWrap(");993 fprintf(irp->f, "@optionalWrap(");
915 ir_print_other_instruction(irp, instruction->value);994 ir_print_other_instruction(irp, instruction->operand);
916 fprintf(irp->f, ")");995 fprintf(irp->f, ")result=");
996 ir_print_other_instruction(irp, instruction->result_loc);
917}997}
918998
919static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instruction) {999static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instruction) {
920 fprintf(irp->f, "@errWrapCode(");1000 fprintf(irp->f, "@errWrapCode(");
921 ir_print_other_instruction(irp, instruction->value);1001 ir_print_other_instruction(irp, instruction->operand);
922 fprintf(irp->f, ")");1002 fprintf(irp->f, ")result=");
1003 ir_print_other_instruction(irp, instruction->result_loc);
923}1004}
9241005
925static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload *instruction) {1006static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload *instruction) {
926 fprintf(irp->f, "@errWrapPayload(");1007 fprintf(irp->f, "@errWrapPayload(");
927 ir_print_other_instruction(irp, instruction->value);1008 ir_print_other_instruction(irp, instruction->operand);
928 fprintf(irp->f, ")");1009 fprintf(irp->f, ")result=");
1010 ir_print_other_instruction(irp, instruction->result_loc);
929}1011}
9301012
931static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) {1013static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) {
...@@ -971,12 +1053,11 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc...@@ -971,12 +1053,11 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc
971 fprintf(irp->f, ")");1053 fprintf(irp->f, ")");
972}1054}
9731055
974static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {1056static void ir_print_bit_cast_src(IrPrint *irp, IrInstructionBitCastSrc *instruction) {
975 fprintf(irp->f, "@bitCast(");1057 fprintf(irp->f, "@bitCast(");
976 ir_print_other_instruction(irp, instruction->dest_type);1058 ir_print_other_instruction(irp, instruction->operand);
977 fprintf(irp->f, ",");1059 fprintf(irp->f, ")result=");
978 ir_print_other_instruction(irp, instruction->value);1060 ir_print_result_loc(irp, &instruction->result_loc_bit_cast->base);
979 fprintf(irp->f, ")");
980}1061}
9811062
982static void ir_print_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) {1063static void ir_print_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) {
...@@ -1043,7 +1124,15 @@ static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *i...@@ -1043,7 +1124,15 @@ static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *i
1043static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) {1124static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) {
1044 fprintf(irp->f, "VectorToArray(");1125 fprintf(irp->f, "VectorToArray(");
1045 ir_print_other_instruction(irp, instruction->vector);1126 ir_print_other_instruction(irp, instruction->vector);
1046 fprintf(irp->f, ")");1127 fprintf(irp->f, ")result=");
1128 ir_print_other_instruction(irp, instruction->result_loc);
1129}
1130
1131static void ir_print_ptr_of_array_to_slice(IrPrint *irp, IrInstructionPtrOfArrayToSlice *instruction) {
1132 fprintf(irp->f, "PtrOfArrayToSlice(");
1133 ir_print_other_instruction(irp, instruction->operand);
1134 fprintf(irp->f, ")result=");
1135 ir_print_other_instruction(irp, instruction->result_loc);
1047}1136}
10481137
1049static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruction) {1138static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruction) {
...@@ -1061,6 +1150,25 @@ static void ir_print_assert_non_null(IrPrint *irp, IrInstructionAssertNonNull *i...@@ -1061,6 +1150,25 @@ static void ir_print_assert_non_null(IrPrint *irp, IrInstructionAssertNonNull *i
1061static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) {1150static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) {
1062 fprintf(irp->f, "@resizeSlice(");1151 fprintf(irp->f, "@resizeSlice(");
1063 ir_print_other_instruction(irp, instruction->operand);1152 ir_print_other_instruction(irp, instruction->operand);
1153 fprintf(irp->f, ")result=");
1154 ir_print_other_instruction(irp, instruction->result_loc);
1155}
1156
1157static void ir_print_alloca_src(IrPrint *irp, IrInstructionAllocaSrc *instruction) {
1158 fprintf(irp->f, "Alloca(align=");
1159 ir_print_other_instruction(irp, instruction->align);
1160 fprintf(irp->f, ",name=%s)", instruction->name_hint);
1161}
1162
1163static void ir_print_alloca_gen(IrPrint *irp, IrInstructionAllocaGen *instruction) {
1164 fprintf(irp->f, "Alloca(align=%" PRIu32 ",name=%s)", instruction->align, instruction->name_hint);
1165}
1166
1167static void ir_print_end_expr(IrPrint *irp, IrInstructionEndExpr *instruction) {
1168 fprintf(irp->f, "EndExpr(result=");
1169 ir_print_result_loc(irp, instruction->result_loc);
1170 fprintf(irp->f, ",value=");
1171 ir_print_other_instruction(irp, instruction->value);
1064 fprintf(irp->f, ")");1172 fprintf(irp->f, ")");
1065}1173}
10661174
...@@ -1186,6 +1294,34 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio...@@ -1186,6 +1294,34 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio
1186 fprintf(irp->f, ")");1294 fprintf(irp->f, ")");
1187}1295}
11881296
1297static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *instruction) {
1298 fprintf(irp->f, "@implicitCast(");
1299 ir_print_other_instruction(irp, instruction->dest_type);
1300 fprintf(irp->f, ",");
1301 ir_print_other_instruction(irp, instruction->target);
1302 fprintf(irp->f, ")");
1303}
1304
1305static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *instruction) {
1306 fprintf(irp->f, "ResolveResult(");
1307 ir_print_result_loc(irp, instruction->result_loc);
1308 fprintf(irp->f, ")");
1309}
1310
1311static void ir_print_reset_result(IrPrint *irp, IrInstructionResetResult *instruction) {
1312 fprintf(irp->f, "ResetResult(");
1313 ir_print_result_loc(irp, instruction->result_loc);
1314 fprintf(irp->f, ")");
1315}
1316
1317static void ir_print_result_ptr(IrPrint *irp, IrInstructionResultPtr *instruction) {
1318 fprintf(irp->f, "ResultPtr(");
1319 ir_print_result_loc(irp, instruction->result_loc);
1320 fprintf(irp->f, ",");
1321 ir_print_other_instruction(irp, instruction->result);
1322 fprintf(irp->f, ")");
1323}
1324
1189static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {1325static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
1190 fprintf(irp->f, "@OpaqueType()");1326 fprintf(irp->f, "@OpaqueType()");
1191}1327}
...@@ -1427,15 +1563,32 @@ static void ir_print_mark_err_ret_trace_ptr(IrPrint *irp, IrInstructionMarkErrRe...@@ -1427,15 +1563,32 @@ static void ir_print_mark_err_ret_trace_ptr(IrPrint *irp, IrInstructionMarkErrRe
1427 fprintf(irp->f, ")");1563 fprintf(irp->f, ")");
1428}1564}
14291565
1430static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {1566static void ir_print_float_op(IrPrint *irp, IrInstructionFloatOp *instruction) {
1431 fprintf(irp->f, "@sqrt(");1567
1568 fprintf(irp->f, "@%s(", float_op_to_name(instruction->op, false));
1432 if (instruction->type != nullptr) {1569 if (instruction->type != nullptr) {
1433 ir_print_other_instruction(irp, instruction->type);1570 ir_print_other_instruction(irp, instruction->type);
1434 } else {1571 } else {
1435 fprintf(irp->f, "null");1572 fprintf(irp->f, "null");
1436 }1573 }
1437 fprintf(irp->f, ",");1574 fprintf(irp->f, ",");
1438 ir_print_other_instruction(irp, instruction->op);1575 ir_print_other_instruction(irp, instruction->op1);
1576 fprintf(irp->f, ")");
1577}
1578
1579static void ir_print_mul_add(IrPrint *irp, IrInstructionMulAdd *instruction) {
1580 fprintf(irp->f, "@mulAdd(");
1581 if (instruction->type_value != nullptr) {
1582 ir_print_other_instruction(irp, instruction->type_value);
1583 } else {
1584 fprintf(irp->f, "null");
1585 }
1586 fprintf(irp->f, ",");
1587 ir_print_other_instruction(irp, instruction->op1);
1588 fprintf(irp->f, ",");
1589 ir_print_other_instruction(irp, instruction->op2);
1590 fprintf(irp->f, ",");
1591 ir_print_other_instruction(irp, instruction->op3);
1439 fprintf(irp->f, ")");1592 fprintf(irp->f, ")");
1440}1593}
14411594
...@@ -1446,7 +1599,7 @@ static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_va...@@ -1446,7 +1599,7 @@ static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_va
1446 fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),1599 fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
1447 var->align_bytes);1600 var->align_bytes);
14481601
1449 ir_print_other_instruction(irp, decl_var_instruction->init_value);1602 ir_print_other_instruction(irp, decl_var_instruction->var_ptr);
1450 if (decl_var_instruction->var->is_comptime != nullptr) {1603 if (decl_var_instruction->var->is_comptime != nullptr) {
1451 fprintf(irp->f, " // comptime = ");1604 fprintf(irp->f, " // comptime = ");
1452 ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);1605 ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
...@@ -1485,8 +1638,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1485,8 +1638,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1485 case IrInstructionIdCast:1638 case IrInstructionIdCast:
1486 ir_print_cast(irp, (IrInstructionCast *)instruction);1639 ir_print_cast(irp, (IrInstructionCast *)instruction);
1487 break;1640 break;
1488 case IrInstructionIdCall:1641 case IrInstructionIdCallSrc:
1489 ir_print_call(irp, (IrInstructionCall *)instruction);1642 ir_print_call_src(irp, (IrInstructionCallSrc *)instruction);
1643 break;
1644 case IrInstructionIdCallGen:
1645 ir_print_call_gen(irp, (IrInstructionCallGen *)instruction);
1490 break;1646 break;
1491 case IrInstructionIdUnOp:1647 case IrInstructionIdUnOp:
1492 ir_print_un_op(irp, (IrInstructionUnOp *)instruction);1648 ir_print_un_op(irp, (IrInstructionUnOp *)instruction);
...@@ -1506,12 +1662,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1506,12 +1662,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1506 case IrInstructionIdContainerInitFields:1662 case IrInstructionIdContainerInitFields:
1507 ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction);1663 ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction);
1508 break;1664 break;
1509 case IrInstructionIdStructInit:
1510 ir_print_struct_init(irp, (IrInstructionStructInit *)instruction);
1511 break;
1512 case IrInstructionIdUnionInit:
1513 ir_print_union_init(irp, (IrInstructionUnionInit *)instruction);
1514 break;
1515 case IrInstructionIdUnreachable:1665 case IrInstructionIdUnreachable:
1516 ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);1666 ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);
1517 break;1667 break;
...@@ -1521,6 +1671,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1521,6 +1671,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1521 case IrInstructionIdVarPtr:1671 case IrInstructionIdVarPtr:
1522 ir_print_var_ptr(irp, (IrInstructionVarPtr *)instruction);1672 ir_print_var_ptr(irp, (IrInstructionVarPtr *)instruction);
1523 break;1673 break;
1674 case IrInstructionIdReturnPtr:
1675 ir_print_return_ptr(irp, (IrInstructionReturnPtr *)instruction);
1676 break;
1524 case IrInstructionIdLoadPtr:1677 case IrInstructionIdLoadPtr:
1525 ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);1678 ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
1526 break;1679 break;
...@@ -1533,12 +1686,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1533,12 +1686,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1533 case IrInstructionIdTypeOf:1686 case IrInstructionIdTypeOf:
1534 ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);1687 ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);
1535 break;1688 break;
1536 case IrInstructionIdToPtrType:
1537 ir_print_to_ptr_type(irp, (IrInstructionToPtrType *)instruction);
1538 break;
1539 case IrInstructionIdPtrTypeChild:
1540 ir_print_ptr_type_child(irp, (IrInstructionPtrTypeChild *)instruction);
1541 break;
1542 case IrInstructionIdFieldPtr:1689 case IrInstructionIdFieldPtr:
1543 ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction);1690 ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction);
1544 break;1691 break;
...@@ -1617,6 +1764,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1617,6 +1764,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1617 case IrInstructionIdRef:1764 case IrInstructionIdRef:
1618 ir_print_ref(irp, (IrInstructionRef *)instruction);1765 ir_print_ref(irp, (IrInstructionRef *)instruction);
1619 break;1766 break;
1767 case IrInstructionIdRefGen:
1768 ir_print_ref_gen(irp, (IrInstructionRefGen *)instruction);
1769 break;
1620 case IrInstructionIdCompileErr:1770 case IrInstructionIdCompileErr:
1621 ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction);1771 ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction);
1622 break;1772 break;
...@@ -1692,8 +1842,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1692,8 +1842,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1692 case IrInstructionIdMemcpy:1842 case IrInstructionIdMemcpy:
1693 ir_print_memcpy(irp, (IrInstructionMemcpy *)instruction);1843 ir_print_memcpy(irp, (IrInstructionMemcpy *)instruction);
1694 break;1844 break;
1695 case IrInstructionIdSlice:1845 case IrInstructionIdSliceSrc:
1696 ir_print_slice(irp, (IrInstructionSlice *)instruction);1846 ir_print_slice_src(irp, (IrInstructionSliceSrc *)instruction);
1847 break;
1848 case IrInstructionIdSliceGen:
1849 ir_print_slice_gen(irp, (IrInstructionSliceGen *)instruction);
1697 break;1850 break;
1698 case IrInstructionIdMemberCount:1851 case IrInstructionIdMemberCount:
1699 ir_print_member_count(irp, (IrInstructionMemberCount *)instruction);1852 ir_print_member_count(irp, (IrInstructionMemberCount *)instruction);
...@@ -1722,8 +1875,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1722,8 +1875,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1722 case IrInstructionIdOverflowOp:1875 case IrInstructionIdOverflowOp:
1723 ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction);1876 ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction);
1724 break;1877 break;
1725 case IrInstructionIdTestErr:1878 case IrInstructionIdTestErrSrc:
1726 ir_print_test_err(irp, (IrInstructionTestErr *)instruction);1879 ir_print_test_err_src(irp, (IrInstructionTestErrSrc *)instruction);
1880 break;
1881 case IrInstructionIdTestErrGen:
1882 ir_print_test_err_gen(irp, (IrInstructionTestErrGen *)instruction);
1727 break;1883 break;
1728 case IrInstructionIdUnwrapErrCode:1884 case IrInstructionIdUnwrapErrCode:
1729 ir_print_unwrap_err_code(irp, (IrInstructionUnwrapErrCode *)instruction);1885 ir_print_unwrap_err_code(irp, (IrInstructionUnwrapErrCode *)instruction);
...@@ -1732,7 +1888,7 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1732,7 +1888,7 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1732 ir_print_unwrap_err_payload(irp, (IrInstructionUnwrapErrPayload *)instruction);1888 ir_print_unwrap_err_payload(irp, (IrInstructionUnwrapErrPayload *)instruction);
1733 break;1889 break;
1734 case IrInstructionIdOptionalWrap:1890 case IrInstructionIdOptionalWrap:
1735 ir_print_maybe_wrap(irp, (IrInstructionOptionalWrap *)instruction);1891 ir_print_optional_wrap(irp, (IrInstructionOptionalWrap *)instruction);
1736 break;1892 break;
1737 case IrInstructionIdErrWrapCode:1893 case IrInstructionIdErrWrapCode:
1738 ir_print_err_wrap_code(irp, (IrInstructionErrWrapCode *)instruction);1894 ir_print_err_wrap_code(irp, (IrInstructionErrWrapCode *)instruction);
...@@ -1752,8 +1908,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1752,8 +1908,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1752 case IrInstructionIdPtrCastGen:1908 case IrInstructionIdPtrCastGen:
1753 ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);1909 ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
1754 break;1910 break;
1755 case IrInstructionIdBitCast:1911 case IrInstructionIdBitCastSrc:
1756 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);1912 ir_print_bit_cast_src(irp, (IrInstructionBitCastSrc *)instruction);
1757 break;1913 break;
1758 case IrInstructionIdBitCastGen:1914 case IrInstructionIdBitCastGen:
1759 ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction);1915 ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction);
...@@ -1818,6 +1974,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1818,6 +1974,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1818 case IrInstructionIdAlignCast:1974 case IrInstructionIdAlignCast:
1819 ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction);1975 ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction);
1820 break;1976 break;
1977 case IrInstructionIdImplicitCast:
1978 ir_print_implicit_cast(irp, (IrInstructionImplicitCast *)instruction);
1979 break;
1980 case IrInstructionIdResolveResult:
1981 ir_print_resolve_result(irp, (IrInstructionResolveResult *)instruction);
1982 break;
1983 case IrInstructionIdResetResult:
1984 ir_print_reset_result(irp, (IrInstructionResetResult *)instruction);
1985 break;
1986 case IrInstructionIdResultPtr:
1987 ir_print_result_ptr(irp, (IrInstructionResultPtr *)instruction);
1988 break;
1821 case IrInstructionIdOpaqueType:1989 case IrInstructionIdOpaqueType:
1822 ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);1990 ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
1823 break;1991 break;
...@@ -1902,8 +2070,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1902,8 +2070,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1902 case IrInstructionIdMarkErrRetTracePtr:2070 case IrInstructionIdMarkErrRetTracePtr:
1903 ir_print_mark_err_ret_trace_ptr(irp, (IrInstructionMarkErrRetTracePtr *)instruction);2071 ir_print_mark_err_ret_trace_ptr(irp, (IrInstructionMarkErrRetTracePtr *)instruction);
1904 break;2072 break;
1905 case IrInstructionIdSqrt:2073 case IrInstructionIdFloatOp:
1906 ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);2074 ir_print_float_op(irp, (IrInstructionFloatOp *)instruction);
2075 break;
2076 case IrInstructionIdMulAdd:
2077 ir_print_mul_add(irp, (IrInstructionMulAdd *)instruction);
1907 break;2078 break;
1908 case IrInstructionIdAtomicLoad:2079 case IrInstructionIdAtomicLoad:
1909 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);2080 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
...@@ -1923,6 +2094,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1923,6 +2094,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1923 case IrInstructionIdVectorToArray:2094 case IrInstructionIdVectorToArray:
1924 ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction);2095 ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction);
1925 break;2096 break;
2097 case IrInstructionIdPtrOfArrayToSlice:
2098 ir_print_ptr_of_array_to_slice(irp, (IrInstructionPtrOfArrayToSlice *)instruction);
2099 break;
1926 case IrInstructionIdAssertZero:2100 case IrInstructionIdAssertZero:
1927 ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);2101 ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
1928 break;2102 break;
...@@ -1938,6 +2112,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1938,6 +2112,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1938 case IrInstructionIdUndeclaredIdent:2112 case IrInstructionIdUndeclaredIdent:
1939 ir_print_undeclared_ident(irp, (IrInstructionUndeclaredIdent *)instruction);2113 ir_print_undeclared_ident(irp, (IrInstructionUndeclaredIdent *)instruction);
1940 break;2114 break;
2115 case IrInstructionIdAllocaSrc:
2116 ir_print_alloca_src(irp, (IrInstructionAllocaSrc *)instruction);
2117 break;
2118 case IrInstructionIdAllocaGen:
2119 ir_print_alloca_gen(irp, (IrInstructionAllocaGen *)instruction);
2120 break;
2121 case IrInstructionIdEndExpr:
2122 ir_print_end_expr(irp, (IrInstructionEndExpr *)instruction);
2123 break;
1941 }2124 }
1942 fprintf(irp->f, "\n");2125 fprintf(irp->f, "\n");
1943}2126}
src/main.cpp+14-2
...@@ -913,8 +913,20 @@ int main(int argc, char **argv) {...@@ -913,8 +913,20 @@ int main(int argc, char **argv) {
913 get_native_target(&target);913 get_native_target(&target);
914 } else {914 } else {
915 if ((err = target_parse_triple(&target, target_string))) {915 if ((err = target_parse_triple(&target, target_string))) {
916 fprintf(stderr, "invalid target: %s\n", err_str(err));916 if (err == ErrorUnknownArchitecture && target.arch != ZigLLVM_UnknownArch) {
917 return print_error_usage(arg0);917 fprintf(stderr, "'%s' requires a sub-architecture. Try one of these:\n",
918 target_arch_name(target.arch));
919 SubArchList sub_arch_list = target_subarch_list(target.arch);
920 size_t subarch_count = target_subarch_count(sub_arch_list);
921 for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) {
922 ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
923 fprintf(stderr, " %s%s\n", target_arch_name(target.arch), target_subarch_name(sub));
924 }
925 return print_error_usage(arg0);
926 } else {
927 fprintf(stderr, "invalid target: %s\n", err_str(err));
928 return print_error_usage(arg0);
929 }
918 }930 }
919 }931 }
920932
src/parser.cpp+3-3
...@@ -344,7 +344,7 @@ static AstNode *ast_parse_bin_op_expr(...@@ -344,7 +344,7 @@ static AstNode *ast_parse_bin_op_expr(
344 op->data.bin_op_expr.op1 = left;344 op->data.bin_op_expr.op1 = left;
345 op->data.bin_op_expr.op2 = right;345 op->data.bin_op_expr.op2 = right;
346 break;346 break;
347 case NodeTypeUnwrapErrorExpr:347 case NodeTypeCatchExpr:
348 op->data.unwrap_err_expr.op1 = left;348 op->data.unwrap_err_expr.op1 = left;
349 op->data.unwrap_err_expr.op2 = right;349 op->data.unwrap_err_expr.op2 = right;
350 break;350 break;
...@@ -2404,7 +2404,7 @@ static AstNode *ast_parse_bitwise_op(ParseContext *pc) {...@@ -2404,7 +2404,7 @@ static AstNode *ast_parse_bitwise_op(ParseContext *pc) {
2404 Token *catch_token = eat_token_if(pc, TokenIdKeywordCatch);2404 Token *catch_token = eat_token_if(pc, TokenIdKeywordCatch);
2405 if (catch_token != nullptr) {2405 if (catch_token != nullptr) {
2406 Token *payload = ast_parse_payload(pc);2406 Token *payload = ast_parse_payload(pc);
2407 AstNode *res = ast_create_node(pc, NodeTypeUnwrapErrorExpr, catch_token);2407 AstNode *res = ast_create_node(pc, NodeTypeCatchExpr, catch_token);
2408 if (payload != nullptr)2408 if (payload != nullptr)
2409 res->data.unwrap_err_expr.symbol = token_symbol(pc, payload);2409 res->data.unwrap_err_expr.symbol = token_symbol(pc, payload);
24102410
...@@ -2897,7 +2897,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2897,7 +2897,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2897 visit_field(&node->data.bin_op_expr.op1, visit, context);2897 visit_field(&node->data.bin_op_expr.op1, visit, context);
2898 visit_field(&node->data.bin_op_expr.op2, visit, context);2898 visit_field(&node->data.bin_op_expr.op2, visit, context);
2899 break;2899 break;
2900 case NodeTypeUnwrapErrorExpr:2900 case NodeTypeCatchExpr:
2901 visit_field(&node->data.unwrap_err_expr.op1, visit, context);2901 visit_field(&node->data.unwrap_err_expr.op1, visit, context);
2902 visit_field(&node->data.unwrap_err_expr.symbol, visit, context);2902 visit_field(&node->data.unwrap_err_expr.symbol, visit, context);
2903 visit_field(&node->data.unwrap_err_expr.op2, visit, context);2903 visit_field(&node->data.unwrap_err_expr.op2, visit, context);
src/target.cpp+5-5
...@@ -486,17 +486,17 @@ void get_native_target(ZigTarget *target) {...@@ -486,17 +486,17 @@ void get_native_target(ZigTarget *target) {
486Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub,486Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub,
487 const char *archsub_ptr, size_t archsub_len)487 const char *archsub_ptr, size_t archsub_len)
488{488{
489 *out_arch = ZigLLVM_UnknownArch;
490 *out_sub = ZigLLVM_NoSubArch;
489 for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) {491 for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) {
490 ZigLLVM_ArchType arch = arch_list[arch_i];492 ZigLLVM_ArchType arch = arch_list[arch_i];
491 SubArchList sub_arch_list = target_subarch_list(arch);493 SubArchList sub_arch_list = target_subarch_list(arch);
492 size_t subarch_count = target_subarch_count(sub_arch_list);494 size_t subarch_count = target_subarch_count(sub_arch_list);
493 if (subarch_count == 0) {495 if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) {
494 if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) {496 *out_arch = arch;
495 *out_arch = arch;497 if (subarch_count == 0) {
496 *out_sub = ZigLLVM_NoSubArch;
497 return ErrorNone;498 return ErrorNone;
498 }499 }
499 continue;
500 }500 }
501 for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) {501 for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) {
502 ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);502 ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
std/event/fs.zig+1-2
...@@ -1290,10 +1290,9 @@ pub fn Watch(comptime V: type) type {...@@ -1290,10 +1290,9 @@ pub fn Watch(comptime V: type) type {
1290 error.FileDescriptorAlreadyPresentInSet => unreachable,1290 error.FileDescriptorAlreadyPresentInSet => unreachable,
1291 error.OperationCausesCircularLoop => unreachable,1291 error.OperationCausesCircularLoop => unreachable,
1292 error.FileDescriptorNotRegistered => unreachable,1292 error.FileDescriptorNotRegistered => unreachable,
1293 error.SystemResources => error.SystemResources,
1294 error.UserResourceLimitReached => error.UserResourceLimitReached,
1295 error.FileDescriptorIncompatibleWithEpoll => unreachable,1293 error.FileDescriptorIncompatibleWithEpoll => unreachable,
1296 error.Unexpected => unreachable,1294 error.Unexpected => unreachable,
1295 else => |e| e,
1297 };1296 };
1298 await (async channel.put(transformed_err) catch unreachable);1297 await (async channel.put(transformed_err) catch unreachable);
1299 };1298 };
std/event/lock.zig+2-1
...@@ -123,7 +123,8 @@ pub const Lock = struct {...@@ -123,7 +123,8 @@ pub const Lock = struct {
123};123};
124124
125test "std.event.Lock" {125test "std.event.Lock" {
126 // https://github.com/ziglang/zig/issues/1908126 // TODO https://github.com/ziglang/zig/issues/2377
127 if (true) return error.SkipZigTest;
127 if (builtin.single_threaded) return error.SkipZigTest;128 if (builtin.single_threaded) return error.SkipZigTest;
128129
129 const allocator = std.heap.direct_allocator;130 const allocator = std.heap.direct_allocator;
std/event/net.zig+2-2
...@@ -263,8 +263,8 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File {...@@ -263,8 +263,8 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File {
263}263}
264264
265test "listen on a port, send bytes, receive bytes" {265test "listen on a port, send bytes, receive bytes" {
266 // https://github.com/ziglang/zig/issues/1908266 // https://github.com/ziglang/zig/issues/2377
267 if (builtin.single_threaded) return error.SkipZigTest;267 if (true) return error.SkipZigTest;
268268
269 if (builtin.os != builtin.Os.linux) {269 if (builtin.os != builtin.Os.linux) {
270 // TODO build abstractions for other operating systems270 // TODO build abstractions for other operating systems
std/event/rwlock.zig+2-2
...@@ -212,8 +212,8 @@ pub const RwLock = struct {...@@ -212,8 +212,8 @@ pub const RwLock = struct {
212};212};
213213
214test "std.event.RwLock" {214test "std.event.RwLock" {
215 // https://github.com/ziglang/zig/issues/1908215 // https://github.com/ziglang/zig/issues/2377
216 if (builtin.single_threaded or builtin.os != builtin.Os.linux) return error.SkipZigTest;216 if (true) return error.SkipZigTest;
217217
218 const allocator = std.heap.direct_allocator;218 const allocator = std.heap.direct_allocator;
219219
std/fmt.zig+387-363
...@@ -10,6 +10,42 @@ const lossyCast = std.math.lossyCast;...@@ -10,6 +10,42 @@ const lossyCast = std.math.lossyCast;
1010
11pub const default_max_depth = 3;11pub const default_max_depth = 3;
1212
13pub const Alignment = enum {
14 Left,
15 Center,
16 Right,
17};
18
19pub const FormatOptions = struct {
20 precision: ?usize = null,
21 width: ?usize = null,
22 alignment: ?Alignment = null,
23 fill: u8 = ' ',
24};
25
26fn nextArg(comptime used_pos_args: *u32, comptime maybe_pos_arg: ?comptime_int, comptime next_arg: *comptime_int) comptime_int {
27 if (maybe_pos_arg) |pos_arg| {
28 used_pos_args.* |= 1 << pos_arg;
29 return pos_arg;
30 } else {
31 const arg = next_arg.*;
32 next_arg.* += 1;
33 return arg;
34 }
35}
36
37fn peekIsAlign(comptime fmt: []const u8) bool {
38 // Should only be called during a state transition to the format segment.
39 std.debug.assert(fmt[0] == ':');
40
41 inline for (([_]u8{ 1, 2 })[0..]) |i| {
42 if (fmt.len > i and (fmt[i] == '<' or fmt[i] == '^' or fmt[i] == '>')) {
43 return true;
44 }
45 }
46 return false;
47}
48
13/// Renders fmt string with args, calling output with slices of bytes.49/// Renders fmt string with args, calling output with slices of bytes.
14/// If `output` returns an error, the error is returned from `format` and50/// If `output` returns an error, the error is returned from `format` and
15/// `output` is not called again.51/// `output` is not called again.
...@@ -20,17 +56,30 @@ pub fn format(...@@ -20,17 +56,30 @@ pub fn format(
20 comptime fmt: []const u8,56 comptime fmt: []const u8,
21 args: ...,57 args: ...,
22) Errors!void {58) Errors!void {
59 const ArgSetType = @IntType(false, 32);
60 if (args.len > ArgSetType.bit_count) {
61 @compileError("32 arguments max are supported per format call");
62 }
63
23 const State = enum {64 const State = enum {
24 Start,65 Start,
25 OpenBrace,66 Positional,
26 CloseBrace,67 CloseBrace,
27 FormatString,68 Specifier,
69 FormatFillAndAlign,
70 FormatWidth,
71 FormatPrecision,
28 Pointer,72 Pointer,
29 };73 };
3074
31 comptime var start_index = 0;75 comptime var start_index = 0;
32 comptime var state = State.Start;76 comptime var state = State.Start;
33 comptime var next_arg = 0;77 comptime var next_arg = 0;
78 comptime var maybe_pos_arg: ?comptime_int = null;
79 comptime var used_pos_args: ArgSetType = 0;
80 comptime var specifier_start = 0;
81 comptime var specifier_end = 0;
82 comptime var options = FormatOptions{};
3483
35 inline for (fmt) |c, i| {84 inline for (fmt) |c, i| {
36 switch (state) {85 switch (state) {
...@@ -39,58 +88,183 @@ pub fn format(...@@ -39,58 +88,183 @@ pub fn format(
39 if (start_index < i) {88 if (start_index < i) {
40 try output(context, fmt[start_index..i]);89 try output(context, fmt[start_index..i]);
41 }90 }
91
42 start_index = i;92 start_index = i;
43 state = State.OpenBrace;93 specifier_start = i + 1;
94 specifier_end = i + 1;
95 maybe_pos_arg = null;
96 state = .Positional;
97 options = FormatOptions{};
44 },98 },
45
46 '}' => {99 '}' => {
47 if (start_index < i) {100 if (start_index < i) {
48 try output(context, fmt[start_index..i]);101 try output(context, fmt[start_index..i]);
49 }102 }
50 state = State.CloseBrace;103 state = .CloseBrace;
51 },104 },
52 else => {},105 else => {},
53 },106 },
54 .OpenBrace => switch (c) {107 .Positional => switch (c) {
55 '{' => {108 '{' => {
56 state = State.Start;109 state = .Start;
57 start_index = i;110 start_index = i;
58 },111 },
112 '*' => {
113 state = .Pointer;
114 },
115 ':' => {
116 state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth;
117 specifier_end = i;
118 },
119 '0'...'9' => {
120 if (maybe_pos_arg == null) {
121 maybe_pos_arg = 0;
122 }
123
124 maybe_pos_arg.? *= 10;
125 maybe_pos_arg.? += c - '0';
126 specifier_start = i + 1;
127
128 if (maybe_pos_arg.? >= args.len) {
129 @compileError("Positional value refers to non-existent argument");
130 }
131 },
59 '}' => {132 '}' => {
60 try formatType(args[next_arg], fmt[0..0], context, Errors, output, default_max_depth);133 const arg_to_print = comptime nextArg(&used_pos_args, maybe_pos_arg, &next_arg);
61 next_arg += 1;134
62 state = State.Start;135 try formatType(
136 args[arg_to_print],
137 fmt[0..0],
138 options,
139 context,
140 Errors,
141 output,
142 default_max_depth,
143 );
144
145 state = .Start;
63 start_index = i + 1;146 start_index = i + 1;
64 },147 },
65 '*' => state = State.Pointer,
66 else => {148 else => {
67 state = State.FormatString;149 state = .Specifier;
150 specifier_start = i;
68 },151 },
69 },152 },
70 .CloseBrace => switch (c) {153 .CloseBrace => switch (c) {
71 '}' => {154 '}' => {
72 state = State.Start;155 state = .Start;
73 start_index = i;156 start_index = i;
74 },157 },
75 else => @compileError("Single '}' encountered in format string"),158 else => @compileError("Single '}' encountered in format string"),
76 },159 },
77 .FormatString => switch (c) {160 .Specifier => switch (c) {
161 ':' => {
162 specifier_end = i;
163 state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth;
164 },
78 '}' => {165 '}' => {
79 const s = start_index + 1;166 const arg_to_print = comptime nextArg(&used_pos_args, maybe_pos_arg, &next_arg);
80 try formatType(args[next_arg], fmt[s..i], context, Errors, output, default_max_depth);167
81 next_arg += 1;168 try formatType(
82 state = State.Start;169 args[arg_to_print],
170 fmt[specifier_start..i],
171 options,
172 context,
173 Errors,
174 output,
175 default_max_depth,
176 );
177 state = .Start;
83 start_index = i + 1;178 start_index = i + 1;
84 },179 },
85 else => {},180 else => {},
86 },181 },
182 // Only entered if the format string contains a fill/align segment.
183 .FormatFillAndAlign => switch (c) {
184 '<' => {
185 options.alignment = Alignment.Left;
186 state = .FormatWidth;
187 },
188 '^' => {
189 options.alignment = Alignment.Center;
190 state = .FormatWidth;
191 },
192 '>' => {
193 options.alignment = Alignment.Right;
194 state = .FormatWidth;
195 },
196 else => {
197 options.fill = c;
198 },
199 },
200 .FormatWidth => switch (c) {
201 '0'...'9' => {
202 if (options.width == null) {
203 options.width = 0;
204 }
205
206 options.width.? *= 10;
207 options.width.? += c - '0';
208 },
209 '.' => {
210 state = .FormatPrecision;
211 },
212 '}' => {
213 const arg_to_print = comptime nextArg(&used_pos_args, maybe_pos_arg, &next_arg);
214
215 try formatType(
216 args[arg_to_print],
217 fmt[specifier_start..specifier_end],
218 options,
219 context,
220 Errors,
221 output,
222 default_max_depth,
223 );
224 state = .Start;
225 start_index = i + 1;
226 },
227 else => {
228 @compileError("Unexpected character in width value: " ++ [_]u8{c});
229 },
230 },
231 .FormatPrecision => switch (c) {
232 '0'...'9' => {
233 if (options.precision == null) {
234 options.precision = 0;
235 }
236
237 options.precision.? *= 10;
238 options.precision.? += c - '0';
239 },
240 '}' => {
241 const arg_to_print = comptime nextArg(&used_pos_args, maybe_pos_arg, &next_arg);
242
243 try formatType(
244 args[arg_to_print],
245 fmt[specifier_start..specifier_end],
246 options,
247 context,
248 Errors,
249 output,
250 default_max_depth,
251 );
252 state = .Start;
253 start_index = i + 1;
254 },
255 else => {
256 @compileError("Unexpected character in precision value: " ++ [_]u8{c});
257 },
258 },
87 .Pointer => switch (c) {259 .Pointer => switch (c) {
88 '}' => {260 '}' => {
89 try output(context, @typeName(@typeOf(args[next_arg]).Child));261 const arg_to_print = comptime nextArg(&used_pos_args, maybe_pos_arg, &next_arg);
262
263 try output(context, @typeName(@typeOf(args[arg_to_print]).Child));
90 try output(context, "@");264 try output(context, "@");
91 try formatInt(@ptrToInt(args[next_arg]), 16, false, 0, context, Errors, output);265 try formatInt(@ptrToInt(args[arg_to_print]), 16, false, 0, context, Errors, output);
92 next_arg += 1;266
93 state = State.Start;267 state = .Start;
94 start_index = i + 1;268 start_index = i + 1;
95 },269 },
96 else => @compileError("Unexpected format character after '*'"),270 else => @compileError("Unexpected format character after '*'"),
...@@ -98,7 +272,13 @@ pub fn format(...@@ -98,7 +272,13 @@ pub fn format(
98 }272 }
99 }273 }
100 comptime {274 comptime {
101 if (args.len != next_arg) {275 // All arguments must have been printed but we allow mixing positional and fixed to achieve this.
276 var i: usize = 0;
277 inline while (i < next_arg) : (i += 1) {
278 used_pos_args |= 1 << i;
279 }
280
281 if (@popCount(ArgSetType, used_pos_args) != args.len) {
102 @compileError("Unused arguments");282 @compileError("Unused arguments");
103 }283 }
104 if (state != State.Start) {284 if (state != State.Start) {
...@@ -113,6 +293,7 @@ pub fn format(...@@ -113,6 +293,7 @@ pub fn format(
113pub fn formatType(293pub fn formatType(
114 value: var,294 value: var,
115 comptime fmt: []const u8,295 comptime fmt: []const u8,
296 comptime options: FormatOptions,
116 context: var,297 context: var,
117 comptime Errors: type,298 comptime Errors: type,
118 output: fn (@typeOf(context), []const u8) Errors!void,299 output: fn (@typeOf(context), []const u8) Errors!void,
...@@ -121,7 +302,7 @@ pub fn formatType(...@@ -121,7 +302,7 @@ pub fn formatType(
121 const T = @typeOf(value);302 const T = @typeOf(value);
122 switch (@typeInfo(T)) {303 switch (@typeInfo(T)) {
123 .ComptimeInt, .Int, .Float => {304 .ComptimeInt, .Int, .Float => {
124 return formatValue(value, fmt, context, Errors, output);305 return formatValue(value, fmt, options, context, Errors, output);
125 },306 },
126 .Void => {307 .Void => {
127 return output(context, "void");308 return output(context, "void");
...@@ -131,16 +312,16 @@ pub fn formatType(...@@ -131,16 +312,16 @@ pub fn formatType(
131 },312 },
132 .Optional => {313 .Optional => {
133 if (value) |payload| {314 if (value) |payload| {
134 return formatType(payload, fmt, context, Errors, output, max_depth);315 return formatType(payload, fmt, options, context, Errors, output, max_depth);
135 } else {316 } else {
136 return output(context, "null");317 return output(context, "null");
137 }318 }
138 },319 },
139 .ErrorUnion => {320 .ErrorUnion => {
140 if (value) |payload| {321 if (value) |payload| {
141 return formatType(payload, fmt, context, Errors, output, max_depth);322 return formatType(payload, fmt, options, context, Errors, output, max_depth);
142 } else |err| {323 } else |err| {
143 return formatType(err, fmt, context, Errors, output, max_depth);324 return formatType(err, fmt, options, context, Errors, output, max_depth);
144 }325 }
145 },326 },
146 .ErrorSet => {327 .ErrorSet => {
...@@ -152,16 +333,16 @@ pub fn formatType(...@@ -152,16 +333,16 @@ pub fn formatType(
152 },333 },
153 .Enum => {334 .Enum => {
154 if (comptime std.meta.trait.hasFn("format")(T)) {335 if (comptime std.meta.trait.hasFn("format")(T)) {
155 return value.format(fmt, context, Errors, output);336 return value.format(fmt, options, context, Errors, output);
156 }337 }
157338
158 try output(context, @typeName(T));339 try output(context, @typeName(T));
159 try output(context, ".");340 try output(context, ".");
160 return formatType(@tagName(value), "", context, Errors, output, max_depth);341 return formatType(@tagName(value), "", options, context, Errors, output, max_depth);
161 },342 },
162 .Union => {343 .Union => {
163 if (comptime std.meta.trait.hasFn("format")(T)) {344 if (comptime std.meta.trait.hasFn("format")(T)) {
164 return value.format(fmt, context, Errors, output);345 return value.format(fmt, options, context, Errors, output);
165 }346 }
166347
167 try output(context, @typeName(T));348 try output(context, @typeName(T));
...@@ -175,7 +356,7 @@ pub fn formatType(...@@ -175,7 +356,7 @@ pub fn formatType(
175 try output(context, " = ");356 try output(context, " = ");
176 inline for (info.fields) |u_field| {357 inline for (info.fields) |u_field| {
177 if (@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) {358 if (@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) {
178 try formatType(@field(value, u_field.name), "", context, Errors, output, max_depth - 1);359 try formatType(@field(value, u_field.name), "", options, context, Errors, output, max_depth - 1);
179 }360 }
180 }361 }
181 try output(context, " }");362 try output(context, " }");
...@@ -185,7 +366,7 @@ pub fn formatType(...@@ -185,7 +366,7 @@ pub fn formatType(
185 },366 },
186 .Struct => {367 .Struct => {
187 if (comptime std.meta.trait.hasFn("format")(T)) {368 if (comptime std.meta.trait.hasFn("format")(T)) {
188 return value.format(fmt, context, Errors, output);369 return value.format(fmt, options, context, Errors, output);
189 }370 }
190371
191 try output(context, @typeName(T));372 try output(context, @typeName(T));
...@@ -201,7 +382,7 @@ pub fn formatType(...@@ -201,7 +382,7 @@ pub fn formatType(
201 }382 }
202 try output(context, @memberName(T, field_i));383 try output(context, @memberName(T, field_i));
203 try output(context, " = ");384 try output(context, " = ");
204 try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output, max_depth - 1);385 try formatType(@field(value, @memberName(T, field_i)), "", options, context, Errors, output, max_depth - 1);
205 }386 }
206 try output(context, " }");387 try output(context, " }");
207 },388 },
...@@ -209,12 +390,12 @@ pub fn formatType(...@@ -209,12 +390,12 @@ pub fn formatType(
209 .One => switch (@typeInfo(ptr_info.child)) {390 .One => switch (@typeInfo(ptr_info.child)) {
210 builtin.TypeId.Array => |info| {391 builtin.TypeId.Array => |info| {
211 if (info.child == u8) {392 if (info.child == u8) {
212 return formatText(value, fmt, context, Errors, output);393 return formatText(value, fmt, options, context, Errors, output);
213 }394 }
214 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));395 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
215 },396 },
216 builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {397 builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
217 return formatType(value.*, fmt, context, Errors, output, max_depth);398 return formatType(value.*, fmt, options, context, Errors, output, max_depth);
218 },399 },
219 else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),400 else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),
220 },401 },
...@@ -222,17 +403,17 @@ pub fn formatType(...@@ -222,17 +403,17 @@ pub fn formatType(
222 if (ptr_info.child == u8) {403 if (ptr_info.child == u8) {
223 if (fmt.len > 0 and fmt[0] == 's') {404 if (fmt.len > 0 and fmt[0] == 's') {
224 const len = mem.len(u8, value);405 const len = mem.len(u8, value);
225 return formatText(value[0..len], fmt, context, Errors, output);406 return formatText(value[0..len], fmt, options, context, Errors, output);
226 }407 }
227 }408 }
228 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));409 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
229 },410 },
230 .Slice => {411 .Slice => {
231 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {412 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
232 return formatText(value, fmt, context, Errors, output);413 return formatText(value, fmt, options, context, Errors, output);
233 }414 }
234 if (ptr_info.child == u8) {415 if (ptr_info.child == u8) {
235 return formatText(value, fmt, context, Errors, output);416 return formatText(value, fmt, options, context, Errors, output);
236 }417 }
237 return format(context, Errors, output, "{}@{x}", @typeName(ptr_info.child), @ptrToInt(value.ptr));418 return format(context, Errors, output, "{}@{x}", @typeName(ptr_info.child), @ptrToInt(value.ptr));
238 },419 },
...@@ -242,7 +423,7 @@ pub fn formatType(...@@ -242,7 +423,7 @@ pub fn formatType(
242 },423 },
243 .Array => |info| {424 .Array => |info| {
244 if (info.child == u8) {425 if (info.child == u8) {
245 return formatText(value, fmt, context, Errors, output);426 return formatText(value, fmt, options, context, Errors, output);
246 }427 }
247 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));428 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
248 },429 },
...@@ -256,28 +437,21 @@ pub fn formatType(...@@ -256,28 +437,21 @@ pub fn formatType(
256fn formatValue(437fn formatValue(
257 value: var,438 value: var,
258 comptime fmt: []const u8,439 comptime fmt: []const u8,
440 comptime options: FormatOptions,
259 context: var,441 context: var,
260 comptime Errors: type,442 comptime Errors: type,
261 output: fn (@typeOf(context), []const u8) Errors!void,443 output: fn (@typeOf(context), []const u8) Errors!void,
262) Errors!void {444) Errors!void {
263 if (fmt.len > 0 and fmt[0] == 'B') {445 if (comptime std.mem.eql(u8, fmt, "B")) {
264 comptime var width: ?usize = null;446 return formatBytes(value, options.width, 1000, context, Errors, output);
265 if (fmt.len > 1) {447 } else if (comptime std.mem.eql(u8, fmt, "Bi")) {
266 if (fmt[1] == 'i') {448 return formatBytes(value, options.width, 1024, context, Errors, output);
267 if (fmt.len > 2) {
268 width = comptime (parseUnsigned(usize, fmt[2..], 10) catch unreachable);
269 }
270 return formatBytes(value, width, 1024, context, Errors, output);
271 }
272 width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
273 }
274 return formatBytes(value, width, 1000, context, Errors, output);
275 }449 }
276450
277 const T = @typeOf(value);451 const T = @typeOf(value);
278 switch (@typeId(T)) {452 switch (@typeId(T)) {
279 .Float => return formatFloatValue(value, fmt, context, Errors, output),453 .Float => return formatFloatValue(value, fmt, options, context, Errors, output),
280 .Int, .ComptimeInt => return formatIntValue(value, fmt, context, Errors, output),454 .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),
281 else => comptime unreachable,455 else => comptime unreachable,
282 }456 }
283}457}
...@@ -285,13 +459,13 @@ fn formatValue(...@@ -285,13 +459,13 @@ fn formatValue(
285pub fn formatIntValue(459pub fn formatIntValue(
286 value: var,460 value: var,
287 comptime fmt: []const u8,461 comptime fmt: []const u8,
462 comptime options: FormatOptions,
288 context: var,463 context: var,
289 comptime Errors: type,464 comptime Errors: type,
290 output: fn (@typeOf(context), []const u8) Errors!void,465 output: fn (@typeOf(context), []const u8) Errors!void,
291) Errors!void {466) Errors!void {
292 comptime var radix = 10;467 comptime var radix = 10;
293 comptime var uppercase = false;468 comptime var uppercase = false;
294 comptime var width = 0;
295469
296 const int_value = if (@typeOf(value) == comptime_int) blk: {470 const int_value = if (@typeOf(value) == comptime_int) blk: {
297 const Int = math.IntFittingRange(value, value);471 const Int = math.IntFittingRange(value, value);
...@@ -299,83 +473,69 @@ pub fn formatIntValue(...@@ -299,83 +473,69 @@ pub fn formatIntValue(
299 } else473 } else
300 value;474 value;
301475
302 if (fmt.len > 0) {476 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "d")) {
303 switch (fmt[0]) {477 radix = 10;
304 'c' => {478 uppercase = false;
305 if (@typeOf(int_value).bit_count <= 8) {479 } else if (comptime std.mem.eql(u8, fmt, "c")) {
306 if (fmt.len > 1)480 if (@typeOf(int_value).bit_count <= 8) {
307 @compileError("Unknown format character: " ++ [_]u8{fmt[1]});481 return formatAsciiChar(u8(int_value), context, Errors, output);
308 return formatAsciiChar(u8(int_value), context, Errors, output);482 } else {
309 }483 @compileError("Cannot print integer that is larger than 8 bits as a ascii");
310 },
311 'b' => {
312 radix = 2;
313 uppercase = false;
314 width = 0;
315 },
316 'd' => {
317 radix = 10;
318 uppercase = false;
319 width = 0;
320 },
321 'x' => {
322 radix = 16;
323 uppercase = false;
324 width = 0;
325 },
326 'X' => {
327 radix = 16;
328 uppercase = true;
329 width = 0;
330 },
331 else => @compileError("Unknown format character: " ++ [_]u8{fmt[0]}),
332 }484 }
333 if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);485 } else if (comptime std.mem.eql(u8, fmt, "b")) {
486 radix = 2;
487 uppercase = false;
488 } else if (comptime std.mem.eql(u8, fmt, "x")) {
489 radix = 16;
490 uppercase = false;
491 } else if (comptime std.mem.eql(u8, fmt, "X")) {
492 radix = 16;
493 uppercase = true;
494 } else {
495 @compileError("Unknown format string: '" ++ fmt ++ "'");
334 }496 }
335 return formatInt(int_value, radix, uppercase, width, context, Errors, output);497
498 return formatInt(int_value, radix, uppercase, options.width orelse 0, context, Errors, output);
336}499}
337500
338fn formatFloatValue(501fn formatFloatValue(
339 value: var,502 value: var,
340 comptime fmt: []const u8,503 comptime fmt: []const u8,
504 comptime options: FormatOptions,
341 context: var,505 context: var,
342 comptime Errors: type,506 comptime Errors: type,
343 output: fn (@typeOf(context), []const u8) Errors!void,507 output: fn (@typeOf(context), []const u8) Errors!void,
344) Errors!void {508) Errors!void {
345 comptime var width: ?usize = null;509 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
346 comptime var float_fmt = 'e';510 return formatFloatScientific(value, options.precision, context, Errors, output);
347 if (fmt.len > 0) {511 } else if (comptime std.mem.eql(u8, fmt, "d")) {
348 float_fmt = fmt[0];512 return formatFloatDecimal(value, options.precision, context, Errors, output);
349 if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);513 } else {
350 }514 @compileError("Unknown format string: '" ++ fmt ++ "'");
351
352 switch (float_fmt) {
353 'e' => try formatFloatScientific(value, width, context, Errors, output),
354 '.' => try formatFloatDecimal(value, width, context, Errors, output),
355 else => @compileError("Unknown format character: " ++ [_]u8{float_fmt}),
356 }515 }
357}516}
358517
359pub fn formatText(518pub fn formatText(
360 bytes: []const u8,519 bytes: []const u8,
361 comptime fmt: []const u8,520 comptime fmt: []const u8,
521 comptime options: FormatOptions,
362 context: var,522 context: var,
363 comptime Errors: type,523 comptime Errors: type,
364 output: fn (@typeOf(context), []const u8) Errors!void,524 output: fn (@typeOf(context), []const u8) Errors!void,
365) Errors!void {525) Errors!void {
366 if (fmt.len > 0) {526 if (fmt.len == 0) {
367 if (fmt[0] == 's') {527 return output(context, bytes);
368 comptime var width = 0;528 } else if (comptime std.mem.eql(u8, fmt, "s")) {
369 if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);529 if (options.width) |w| return formatBuf(bytes, w, context, Errors, output);
370 return formatBuf(bytes, width, context, Errors, output);530 return formatBuf(bytes, 0, context, Errors, output);
371 } else if ((fmt[0] == 'x') or (fmt[0] == 'X')) {531 } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
372 for (bytes) |c| {532 for (bytes) |c| {
373 try formatInt(c, 16, fmt[0] == 'X', 2, context, Errors, output);533 try formatInt(c, 16, fmt[0] == 'X', 2, context, Errors, output);
374 }534 }
375 return;535 return;
376 } else @compileError("Unknown format character: " ++ [_]u8{fmt[0]});536 } else {
537 @compileError("Unknown format string: '" ++ fmt ++ "'");
377 }538 }
378 return output(context, bytes);
379}539}
380540
381pub fn formatAsciiChar(541pub fn formatAsciiChar(
...@@ -868,7 +1028,7 @@ test "parseUnsigned" {...@@ -868,7 +1028,7 @@ test "parseUnsigned" {
8681028
869pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;1029pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
8701030
871test "fmt.parseFloat" {1031test "parseFloat" {
872 _ = @import("fmt/parse_float.zig");1032 _ = @import("fmt/parse_float.zig");
873}1033}
8741034
...@@ -960,7 +1120,7 @@ test "parse unsigned comptime" {...@@ -960,7 +1120,7 @@ test "parse unsigned comptime" {
960 }1120 }
961}1121}
9621122
963test "fmt.optional" {1123test "optional" {
964 {1124 {
965 const value: ?i32 = 1234;1125 const value: ?i32 = 1234;
966 try testFmt("optional: 1234\n", "optional: {}\n", value);1126 try testFmt("optional: 1234\n", "optional: {}\n", value);
...@@ -971,7 +1131,7 @@ test "fmt.optional" {...@@ -971,7 +1131,7 @@ test "fmt.optional" {
971 }1131 }
972}1132}
9731133
974test "fmt.error" {1134test "error" {
975 {1135 {
976 const value: anyerror!i32 = 1234;1136 const value: anyerror!i32 = 1234;
977 try testFmt("error union: 1234\n", "error union: {}\n", value);1137 try testFmt("error union: 1234\n", "error union: {}\n", value);
...@@ -982,14 +1142,14 @@ test "fmt.error" {...@@ -982,14 +1142,14 @@ test "fmt.error" {
982 }1142 }
983}1143}
9841144
985test "fmt.int.small" {1145test "int.small" {
986 {1146 {
987 const value: u3 = 0b101;1147 const value: u3 = 0b101;
988 try testFmt("u3: 5\n", "u3: {}\n", value);1148 try testFmt("u3: 5\n", "u3: {}\n", value);
989 }1149 }
990}1150}
9911151
992test "fmt.int.specifier" {1152test "int.specifier" {
993 {1153 {
994 const value: u8 = 'a';1154 const value: u8 = 'a';
995 try testFmt("u8: a\n", "u8: {c}\n", value);1155 try testFmt("u8: a\n", "u8: {c}\n", value);
...@@ -1000,27 +1160,31 @@ test "fmt.int.specifier" {...@@ -1000,27 +1160,31 @@ test "fmt.int.specifier" {
1000 }1160 }
1001}1161}
10021162
1003test "fmt.buffer" {1163test "int.padded" {
1164 try testFmt("u8: '0001'", "u8: '{:4}'", u8(1));
1165}
1166
1167test "buffer" {
1004 {1168 {
1005 var buf1: [32]u8 = undefined;1169 var buf1: [32]u8 = undefined;
1006 var context = BufPrintContext{ .remaining = buf1[0..] };1170 var context = BufPrintContext{ .remaining = buf1[0..] };
1007 try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1171 try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1008 var res = buf1[0 .. buf1.len - context.remaining.len];1172 var res = buf1[0 .. buf1.len - context.remaining.len];
1009 testing.expect(mem.eql(u8, res, "1234"));1173 testing.expect(mem.eql(u8, res, "1234"));
10101174
1011 context = BufPrintContext{ .remaining = buf1[0..] };1175 context = BufPrintContext{ .remaining = buf1[0..] };
1012 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1176 try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1013 res = buf1[0 .. buf1.len - context.remaining.len];1177 res = buf1[0 .. buf1.len - context.remaining.len];
1014 testing.expect(mem.eql(u8, res, "a"));1178 testing.expect(mem.eql(u8, res, "a"));
10151179
1016 context = BufPrintContext{ .remaining = buf1[0..] };1180 context = BufPrintContext{ .remaining = buf1[0..] };
1017 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1181 try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1018 res = buf1[0 .. buf1.len - context.remaining.len];1182 res = buf1[0 .. buf1.len - context.remaining.len];
1019 testing.expect(mem.eql(u8, res, "1100"));1183 testing.expect(mem.eql(u8, res, "1100"));
1020 }1184 }
1021}1185}
10221186
1023test "fmt.array" {1187test "array" {
1024 {1188 {
1025 const value: [3]u8 = "abc";1189 const value: [3]u8 = "abc";
1026 try testFmt("array: abc\n", "array: {}\n", value);1190 try testFmt("array: abc\n", "array: {}\n", value);
...@@ -1035,7 +1199,7 @@ test "fmt.array" {...@@ -1035,7 +1199,7 @@ test "fmt.array" {
1035 }1199 }
1036}1200}
10371201
1038test "fmt.slice" {1202test "slice" {
1039 {1203 {
1040 const value: []const u8 = "abc";1204 const value: []const u8 = "abc";
1041 try testFmt("slice: abc\n", "slice: {}\n", value);1205 try testFmt("slice: abc\n", "slice: {}\n", value);
...@@ -1045,11 +1209,11 @@ test "fmt.slice" {...@@ -1045,11 +1209,11 @@ test "fmt.slice" {
1045 try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", value);1209 try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", value);
1046 }1210 }
10471211
1048 try testFmt("buf: Test \n", "buf: {s5}\n", "Test");1212 try testFmt("buf: Test \n", "buf: {s:5}\n", "Test");
1049 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");1213 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
1050}1214}
10511215
1052test "fmt.pointer" {1216test "pointer" {
1053 {1217 {
1054 const value = @intToPtr(*i32, 0xdeadbeef);1218 const value = @intToPtr(*i32, 0xdeadbeef);
1055 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);1219 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
...@@ -1065,17 +1229,17 @@ test "fmt.pointer" {...@@ -1065,17 +1229,17 @@ test "fmt.pointer" {
1065 }1229 }
1066}1230}
10671231
1068test "fmt.cstr" {1232test "cstr" {
1069 try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");1233 try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
1070 try testFmt("cstr: Test C \n", "cstr: {s10}\n", c"Test C");1234 try testFmt("cstr: Test C \n", "cstr: {s:10}\n", c"Test C");
1071}1235}
10721236
1073test "fmt.filesize" {1237test "filesize" {
1074 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));1238 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));
1075 try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024));1239 try testFmt("file size: 66.06MB\n", "file size: {B:2}\n", usize(63 * 1024 * 1024));
1076}1240}
10771241
1078test "fmt.struct" {1242test "struct" {
1079 {1243 {
1080 const Struct = struct {1244 const Struct = struct {
1081 field: u8,1245 field: u8,
...@@ -1094,7 +1258,7 @@ test "fmt.struct" {...@@ -1094,7 +1258,7 @@ test "fmt.struct" {
1094 }1258 }
1095}1259}
10961260
1097test "fmt.enum" {1261test "enum" {
1098 const Enum = enum {1262 const Enum = enum {
1099 One,1263 One,
1100 Two,1264 Two,
...@@ -1104,229 +1268,71 @@ test "fmt.enum" {...@@ -1104,229 +1268,71 @@ test "fmt.enum" {
1104 try testFmt("enum: Enum.Two\n", "enum: {}\n", &value);1268 try testFmt("enum: Enum.Two\n", "enum: {}\n", &value);
1105}1269}
11061270
1107test "fmt.float.scientific" {1271test "float.scientific" {
1108 {1272 try testFmt("f32: 1.34000003e+00", "f32: {e}", f32(1.34));
1109 var buf1: [32]u8 = undefined;1273 try testFmt("f32: 1.23400001e+01", "f32: {e}", f32(12.34));
1110 const value: f32 = 1.34;1274 try testFmt("f64: -1.234e+11", "f64: {e}", f64(-12.34e10));
1111 const result = try bufPrint(buf1[0..], "f32: {e}\n", value);1275 try testFmt("f64: 9.99996e-40", "f64: {e}", f64(9.999960e-40));
1112 testing.expect(mem.eql(u8, result, "f32: 1.34000003e+00\n"));
1113 }
1114 {
1115 var buf1: [32]u8 = undefined;
1116 const value: f32 = 12.34;
1117 const result = try bufPrint(buf1[0..], "f32: {e}\n", value);
1118 testing.expect(mem.eql(u8, result, "f32: 1.23400001e+01\n"));
1119 }
1120 {
1121 var buf1: [32]u8 = undefined;
1122 const value: f64 = -12.34e10;
1123 const result = try bufPrint(buf1[0..], "f64: {e}\n", value);
1124 testing.expect(mem.eql(u8, result, "f64: -1.234e+11\n"));
1125 }
1126 {
1127 // This fails on release due to a minor rounding difference.
1128 // --release-fast outputs 9.999960000000001e-40 vs. the expected.
1129 // TODO fix this, it should be the same in Debug and ReleaseFast
1130 if (builtin.mode == builtin.Mode.Debug) {
1131 var buf1: [32]u8 = undefined;
1132 const value: f64 = 9.999960e-40;
1133 const result = try bufPrint(buf1[0..], "f64: {e}\n", value);
1134 testing.expect(mem.eql(u8, result, "f64: 9.99996e-40\n"));
1135 }
1136 }
1137}1276}
11381277
1139test "fmt.float.scientific.precision" {1278test "float.scientific.precision" {
1140 {1279 try testFmt("f64: 1.40971e-42", "f64: {e:.5}", f64(1.409706e-42));
1141 var buf1: [32]u8 = undefined;1280 try testFmt("f64: 1.00000e-09", "f64: {e:.5}", f64(@bitCast(f32, u32(814313563))));
1142 const value: f64 = 1.409706e-42;1281 try testFmt("f64: 7.81250e-03", "f64: {e:.5}", f64(@bitCast(f32, u32(1006632960))));
1143 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);1282 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
1144 testing.expect(mem.eql(u8, result, "f64: 1.40971e-42\n"));1283 // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
1145 }1284 try testFmt("f64: 1.00001e+05", "f64: {e:.5}", f64(@bitCast(f32, u32(1203982400))));
1146 {
1147 var buf1: [32]u8 = undefined;
1148 const value: f64 = @bitCast(f32, u32(814313563));
1149 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
1150 testing.expect(mem.eql(u8, result, "f64: 1.00000e-09\n"));
1151 }
1152 {
1153 var buf1: [32]u8 = undefined;
1154 const value: f64 = @bitCast(f32, u32(1006632960));
1155 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
1156 testing.expect(mem.eql(u8, result, "f64: 7.81250e-03\n"));
1157 }
1158 {
1159 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
1160 // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
1161 var buf1: [32]u8 = undefined;
1162 const value: f64 = @bitCast(f32, u32(1203982400));
1163 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
1164 testing.expect(mem.eql(u8, result, "f64: 1.00001e+05\n"));
1165 }
1166}1285}
11671286
1168test "fmt.float.special" {1287test "float.special" {
1169 {1288 try testFmt("f64: nan", "f64: {}", math.nan_f64);
1170 var buf1: [32]u8 = undefined;1289 // negative nan is not defined by IEE 754,
1171 const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64);1290 // and ARM thus normalizes it to positive nan
1172 testing.expect(mem.eql(u8, result, "f64: nan\n"));
1173 }
1174 if (builtin.arch != builtin.Arch.arm) {1291 if (builtin.arch != builtin.Arch.arm) {
1175 // negative nan is not defined by IEE 754,1292 try testFmt("f64: -nan", "f64: {}", -math.nan_f64);
1176 // and ARM thus normalizes it to positive nan
1177 var buf1: [32]u8 = undefined;
1178 const result = try bufPrint(buf1[0..], "f64: {}\n", -math.nan_f64);
1179 testing.expect(mem.eql(u8, result, "f64: -nan\n"));
1180 }
1181 {
1182 var buf1: [32]u8 = undefined;
1183 const result = try bufPrint(buf1[0..], "f64: {}\n", math.inf_f64);
1184 testing.expect(mem.eql(u8, result, "f64: inf\n"));
1185 }
1186 {
1187 var buf1: [32]u8 = undefined;
1188 const result = try bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64);
1189 testing.expect(mem.eql(u8, result, "f64: -inf\n"));
1190 }1293 }
1294 try testFmt("f64: inf", "f64: {}", math.inf_f64);
1295 try testFmt("f64: -inf", "f64: {}", -math.inf_f64);
1191}1296}
11921297
1193test "fmt.float.decimal" {1298test "float.decimal" {
1194 {1299 try testFmt("f64: 152314000000000000000000000000", "f64: {d}", f64(1.52314e+29));
1195 var buf1: [64]u8 = undefined;1300 try testFmt("f32: 1.1", "f32: {d:.1}", f32(1.1234));
1196 const value: f64 = 1.52314e+29;1301 try testFmt("f32: 1234.57", "f32: {d:.2}", f32(1234.567));
1197 const result = try bufPrint(buf1[0..], "f64: {.}\n", value);1302 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
1198 testing.expect(mem.eql(u8, result, "f64: 152314000000000000000000000000\n"));1303 // -11.12339... is rounded back up to -11.1234
1199 }1304 try testFmt("f32: -11.1234", "f32: {d:.4}", f32(-11.1234));
1200 {1305 try testFmt("f32: 91.12345", "f32: {d:.5}", f32(91.12345));
1201 var buf1: [32]u8 = undefined;1306 try testFmt("f64: 91.1234567890", "f64: {d:.10}", f64(91.12345678901235));
1202 const value: f32 = 1.1234;1307 try testFmt("f64: 0.00000", "f64: {d:.5}", f64(0.0));
1203 const result = try bufPrint(buf1[0..], "f32: {.1}\n", value);1308 try testFmt("f64: 6", "f64: {d:.0}", f64(5.700));
1204 testing.expect(mem.eql(u8, result, "f32: 1.1\n"));1309 try testFmt("f64: 10.0", "f64: {d:.1}", f64(9.999));
1205 }1310 try testFmt("f64: 1.000", "f64: {d:.3}", f64(1.0));
1206 {1311 try testFmt("f64: 0.00030000", "f64: {d:.8}", f64(0.0003));
1207 var buf1: [32]u8 = undefined;1312 try testFmt("f64: 0.00000", "f64: {d:.5}", f64(1.40130e-45));
1208 const value: f32 = 1234.567;1313 try testFmt("f64: 0.00000", "f64: {d:.5}", f64(9.999960e-40));
1209 const result = try bufPrint(buf1[0..], "f32: {.2}\n", value);
1210 testing.expect(mem.eql(u8, result, "f32: 1234.57\n"));
1211 }
1212 {
1213 var buf1: [32]u8 = undefined;
1214 const value: f32 = -11.1234;
1215 const result = try bufPrint(buf1[0..], "f32: {.4}\n", value);
1216 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
1217 // -11.12339... is rounded back up to -11.1234
1218 testing.expect(mem.eql(u8, result, "f32: -11.1234\n"));
1219 }
1220 {
1221 var buf1: [32]u8 = undefined;
1222 const value: f32 = 91.12345;
1223 const result = try bufPrint(buf1[0..], "f32: {.5}\n", value);
1224 testing.expect(mem.eql(u8, result, "f32: 91.12345\n"));
1225 }
1226 {
1227 var buf1: [32]u8 = undefined;
1228 const value: f64 = 91.12345678901235;
1229 const result = try bufPrint(buf1[0..], "f64: {.10}\n", value);
1230 testing.expect(mem.eql(u8, result, "f64: 91.1234567890\n"));
1231 }
1232 {
1233 var buf1: [32]u8 = undefined;
1234 const value: f64 = 0.0;
1235 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1236 testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
1237 }
1238 {
1239 var buf1: [32]u8 = undefined;
1240 const value: f64 = 5.700;
1241 const result = try bufPrint(buf1[0..], "f64: {.0}\n", value);
1242 testing.expect(mem.eql(u8, result, "f64: 6\n"));
1243 }
1244 {
1245 var buf1: [32]u8 = undefined;
1246 const value: f64 = 9.999;
1247 const result = try bufPrint(buf1[0..], "f64: {.1}\n", value);
1248 testing.expect(mem.eql(u8, result, "f64: 10.0\n"));
1249 }
1250 {
1251 var buf1: [32]u8 = undefined;
1252 const value: f64 = 1.0;
1253 const result = try bufPrint(buf1[0..], "f64: {.3}\n", value);
1254 testing.expect(mem.eql(u8, result, "f64: 1.000\n"));
1255 }
1256 {
1257 var buf1: [32]u8 = undefined;
1258 const value: f64 = 0.0003;
1259 const result = try bufPrint(buf1[0..], "f64: {.8}\n", value);
1260 testing.expect(mem.eql(u8, result, "f64: 0.00030000\n"));
1261 }
1262 {
1263 var buf1: [32]u8 = undefined;
1264 const value: f64 = 1.40130e-45;
1265 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1266 testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
1267 }
1268 {
1269 var buf1: [32]u8 = undefined;
1270 const value: f64 = 9.999960e-40;
1271 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1272 testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
1273 }
1274}1314}
12751315
1276test "fmt.float.libc.sanity" {1316test "float.libc.sanity" {
1277 {1317 try testFmt("f64: 0.00001", "f64: {d:.5}", f64(@bitCast(f32, u32(916964781))));
1278 var buf1: [32]u8 = undefined;1318 try testFmt("f64: 0.00001", "f64: {d:.5}", f64(@bitCast(f32, u32(925353389))));
1279 const value: f64 = f64(@bitCast(f32, u32(916964781)));1319 try testFmt("f64: 0.10000", "f64: {d:.5}", f64(@bitCast(f32, u32(1036831278))));
1280 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1320 try testFmt("f64: 1.00000", "f64: {d:.5}", f64(@bitCast(f32, u32(1065353133))));
1281 testing.expect(mem.eql(u8, result, "f64: 0.00001\n"));1321 try testFmt("f64: 10.00000", "f64: {d:.5}", f64(@bitCast(f32, u32(1092616192))));
1282 }1322
1283 {
1284 var buf1: [32]u8 = undefined;
1285 const value: f64 = f64(@bitCast(f32, u32(925353389)));
1286 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1287 testing.expect(mem.eql(u8, result, "f64: 0.00001\n"));
1288 }
1289 {
1290 var buf1: [32]u8 = undefined;
1291 const value: f64 = f64(@bitCast(f32, u32(1036831278)));
1292 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1293 testing.expect(mem.eql(u8, result, "f64: 0.10000\n"));
1294 }
1295 {
1296 var buf1: [32]u8 = undefined;
1297 const value: f64 = f64(@bitCast(f32, u32(1065353133)));
1298 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1299 testing.expect(mem.eql(u8, result, "f64: 1.00000\n"));
1300 }
1301 {
1302 var buf1: [32]u8 = undefined;
1303 const value: f64 = f64(@bitCast(f32, u32(1092616192)));
1304 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1305 testing.expect(mem.eql(u8, result, "f64: 10.00000\n"));
1306 }
1307 // libc differences1323 // libc differences
1308 {1324 //
1309 var buf1: [32]u8 = undefined;1325 // This is 0.015625 exactly according to gdb. We thus round down,
1310 // This is 0.015625 exactly according to gdb. We thus round down,1326 // however glibc rounds up for some reason. This occurs for all
1311 // however glibc rounds up for some reason. This occurs for all1327 // floats of the form x.yyyy25 on a precision point.
1312 // floats of the form x.yyyy25 on a precision point.1328 try testFmt("f64: 0.01563", "f64: {d:.5}", f64(@bitCast(f32, u32(1015021568))));
1313 const value: f64 = f64(@bitCast(f32, u32(1015021568)));1329 // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
1314 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1330 // also rounds to 630 so I'm inclined to believe libc is not
1315 testing.expect(mem.eql(u8, result, "f64: 0.01563\n"));1331 // optimal here.
1316 }1332 try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", f64(@bitCast(f32, u32(1518338049))));
1317 // std-windows-x86_64-Debug-bare test case fails
1318 {
1319 // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
1320 // also rounds to 630 so I'm inclined to believe libc is not
1321 // optimal here.
1322 var buf1: [32]u8 = undefined;
1323 const value: f64 = f64(@bitCast(f32, u32(1518338049)));
1324 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1325 testing.expect(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));
1326 }
1327}1333}
13281334
1329test "fmt.custom" {1335test "custom" {
1330 const Vec2 = struct {1336 const Vec2 = struct {
1331 const SelfType = @This();1337 const SelfType = @This();
1332 x: f32,1338 x: f32,
...@@ -1335,20 +1341,17 @@ test "fmt.custom" {...@@ -1335,20 +1341,17 @@ test "fmt.custom" {
1335 pub fn format(1341 pub fn format(
1336 self: SelfType,1342 self: SelfType,
1337 comptime fmt: []const u8,1343 comptime fmt: []const u8,
1344 comptime options: FormatOptions,
1338 context: var,1345 context: var,
1339 comptime Errors: type,1346 comptime Errors: type,
1340 output: fn (@typeOf(context), []const u8) Errors!void,1347 output: fn (@typeOf(context), []const u8) Errors!void,
1341 ) Errors!void {1348 ) Errors!void {
1342 switch (fmt.len) {1349 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
1343 0 => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y),1350 return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", self.x, self.y);
1344 1 => switch (fmt[0]) {1351 } else if (comptime std.mem.eql(u8, fmt, "d")) {
1345 //point format1352 return std.fmt.format(context, Errors, output, "{d:.3}x{d:.3}", self.x, self.y);
1346 'p' => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y),1353 } else {
1347 //dimension format1354 @compileError("Unknown format character: '" ++ fmt ++ "'");
1348 'd' => return std.fmt.format(context, Errors, output, "{.3}x{.3}", self.x, self.y),
1349 else => unreachable,
1350 },
1351 else => unreachable,
1352 }1355 }
1353 }1356 }
1354 };1357 };
...@@ -1366,7 +1369,7 @@ test "fmt.custom" {...@@ -1366,7 +1369,7 @@ test "fmt.custom" {
1366 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", value);1369 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", value);
1367}1370}
13681371
1369test "fmt.struct" {1372test "struct" {
1370 const S = struct {1373 const S = struct {
1371 a: u32,1374 a: u32,
1372 b: anyerror,1375 b: anyerror,
...@@ -1380,7 +1383,7 @@ test "fmt.struct" {...@@ -1380,7 +1383,7 @@ test "fmt.struct" {
1380 try testFmt("S{ .a = 456, .b = error.Unused }", "{}", inst);1383 try testFmt("S{ .a = 456, .b = error.Unused }", "{}", inst);
1381}1384}
13821385
1383test "fmt.union" {1386test "union" {
1384 const TU = union(enum) {1387 const TU = union(enum) {
1385 float: f32,1388 float: f32,
1386 int: u32,1389 int: u32,
...@@ -1410,7 +1413,7 @@ test "fmt.union" {...@@ -1410,7 +1413,7 @@ test "fmt.union" {
1410 testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));1413 testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
1411}1414}
14121415
1413test "fmt.enum" {1416test "enum" {
1414 const E = enum {1417 const E = enum {
1415 One,1418 One,
1416 Two,1419 Two,
...@@ -1422,7 +1425,7 @@ test "fmt.enum" {...@@ -1422,7 +1425,7 @@ test "fmt.enum" {
1422 try testFmt("E.Two", "{}", inst);1425 try testFmt("E.Two", "{}", inst);
1423}1426}
14241427
1425test "fmt.struct.self-referential" {1428test "struct.self-referential" {
1426 const S = struct {1429 const S = struct {
1427 const SelfType = @This();1430 const SelfType = @This();
1428 a: ?*SelfType,1431 a: ?*SelfType,
...@@ -1436,7 +1439,7 @@ test "fmt.struct.self-referential" {...@@ -1436,7 +1439,7 @@ test "fmt.struct.self-referential" {
1436 try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst);1439 try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst);
1437}1440}
14381441
1439test "fmt.bytes.hex" {1442test "bytes.hex" {
1440 const some_bytes = "\xCA\xFE\xBA\xBE";1443 const some_bytes = "\xCA\xFE\xBA\xBE";
1441 try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", some_bytes);1444 try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", some_bytes);
1442 try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", some_bytes);1445 try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", some_bytes);
...@@ -1478,7 +1481,7 @@ pub fn trim(buf: []const u8) []const u8 {...@@ -1478,7 +1481,7 @@ pub fn trim(buf: []const u8) []const u8 {
1478 return buf[start..end];1481 return buf[start..end];
1479}1482}
14801483
1481test "fmt.trim" {1484test "trim" {
1482 testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));1485 testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
1483 testing.expect(mem.eql(u8, "", trim(" ")));1486 testing.expect(mem.eql(u8, "", trim(" ")));
1484 testing.expect(mem.eql(u8, "", trim("")));1487 testing.expect(mem.eql(u8, "", trim("")));
...@@ -1505,22 +1508,22 @@ pub fn hexToBytes(out: []u8, input: []const u8) !void {...@@ -1505,22 +1508,22 @@ pub fn hexToBytes(out: []u8, input: []const u8) !void {
1505 }1508 }
1506}1509}
15071510
1508test "fmt.hexToBytes" {1511test "hexToBytes" {
1509 const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";1512 const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
1510 var pb: [32]u8 = undefined;1513 var pb: [32]u8 = undefined;
1511 try hexToBytes(pb[0..], test_hex_str);1514 try hexToBytes(pb[0..], test_hex_str);
1512 try testFmt(test_hex_str, "{X}", pb);1515 try testFmt(test_hex_str, "{X}", pb);
1513}1516}
15141517
1515test "fmt.formatIntValue with comptime_int" {1518test "formatIntValue with comptime_int" {
1516 const value: comptime_int = 123456789123456789;1519 const value: comptime_int = 123456789123456789;
15171520
1518 var buf = try std.Buffer.init(std.debug.global_allocator, "");1521 var buf = try std.Buffer.init(std.debug.global_allocator, "");
1519 try formatIntValue(value, "", &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);1522 try formatIntValue(value, "", FormatOptions{}, &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);
1520 assert(mem.eql(u8, buf.toSlice(), "123456789123456789"));1523 assert(mem.eql(u8, buf.toSlice(), "123456789123456789"));
1521}1524}
15221525
1523test "fmt.formatType max_depth" {1526test "formatType max_depth" {
1524 const Vec2 = struct {1527 const Vec2 = struct {
1525 const SelfType = @This();1528 const SelfType = @This();
1526 x: f32,1529 x: f32,
...@@ -1529,11 +1532,16 @@ test "fmt.formatType max_depth" {...@@ -1529,11 +1532,16 @@ test "fmt.formatType max_depth" {
1529 pub fn format(1532 pub fn format(
1530 self: SelfType,1533 self: SelfType,
1531 comptime fmt: []const u8,1534 comptime fmt: []const u8,
1535 comptime options: FormatOptions,
1532 context: var,1536 context: var,
1533 comptime Errors: type,1537 comptime Errors: type,
1534 output: fn (@typeOf(context), []const u8) Errors!void,1538 output: fn (@typeOf(context), []const u8) Errors!void,
1535 ) Errors!void {1539 ) Errors!void {
1536 return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y);1540 if (fmt.len == 0) {
1541 return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", self.x, self.y);
1542 } else {
1543 @compileError("Unknown format string: '" ++ fmt ++ "'");
1544 }
1537 }1545 }
1538 };1546 };
1539 const E = enum {1547 const E = enum {
...@@ -1565,18 +1573,34 @@ test "fmt.formatType max_depth" {...@@ -1565,18 +1573,34 @@ test "fmt.formatType max_depth" {
1565 inst.tu.ptr = &inst.tu;1573 inst.tu.ptr = &inst.tu;
15661574
1567 var buf0 = try std.Buffer.init(std.debug.global_allocator, "");1575 var buf0 = try std.Buffer.init(std.debug.global_allocator, "");
1568 try formatType(inst, "", &buf0, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0);1576 try formatType(inst, "", FormatOptions{}, &buf0, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0);
1569 assert(mem.eql(u8, buf0.toSlice(), "S{ ... }"));1577 assert(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
15701578
1571 var buf1 = try std.Buffer.init(std.debug.global_allocator, "");1579 var buf1 = try std.Buffer.init(std.debug.global_allocator, "");
1572 try formatType(inst, "", &buf1, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1);1580 try formatType(inst, "", FormatOptions{}, &buf1, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1);
1573 assert(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));1581 assert(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
15741582
1575 var buf2 = try std.Buffer.init(std.debug.global_allocator, "");1583 var buf2 = try std.Buffer.init(std.debug.global_allocator, "");
1576 try formatType(inst, "", &buf2, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2);1584 try formatType(inst, "", FormatOptions{}, &buf2, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2);
1577 assert(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));1585 assert(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
15781586
1579 var buf3 = try std.Buffer.init(std.debug.global_allocator, "");1587 var buf3 = try std.Buffer.init(std.debug.global_allocator, "");
1580 try formatType(inst, "", &buf3, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3);1588 try formatType(inst, "", FormatOptions{}, &buf3, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3);
1581 assert(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));1589 assert(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
1582}1590}
1591
1592test "positional" {
1593 try testFmt("2 1 0", "{2} {1} {0}", usize(0), usize(1), usize(2));
1594 try testFmt("2 1 0", "{2} {1} {}", usize(0), usize(1), usize(2));
1595 try testFmt("0 0", "{0} {0}", usize(0));
1596 try testFmt("0 1", "{} {1}", usize(0), usize(1));
1597 try testFmt("1 0 0 1", "{1} {} {0} {}", usize(0), usize(1));
1598}
1599
1600test "positional with specifier" {
1601 try testFmt("10.0", "{0d:.1}", f64(9.999));
1602}
1603
1604test "positional/alignment/width/precision" {
1605 try testFmt("10.0", "{0d: >3.1}", f64(9.999));
1606}
std/heap.zig+4-2
...@@ -8,6 +8,8 @@ const builtin = @import("builtin");...@@ -8,6 +8,8 @@ const builtin = @import("builtin");
8const c = std.c;8const c = std.c;
9const maxInt = std.math.maxInt;9const maxInt = std.math.maxInt;
1010
11pub const LoggingAllocator = @import("heap/logging_allocator.zig").LoggingAllocator;
12
11const Allocator = mem.Allocator;13const Allocator = mem.Allocator;
1214
13pub const c_allocator = &c_allocator_state;15pub const c_allocator = &c_allocator_state;
...@@ -360,9 +362,9 @@ pub const ArenaAllocator = struct {...@@ -360,9 +362,9 @@ pub const ArenaAllocator = struct {
360 var it = self.buffer_list.first;362 var it = self.buffer_list.first;
361 while (it) |node| {363 while (it) |node| {
362 // this has to occur before the free because the free frees node364 // this has to occur before the free because the free frees node
363 it = node.next;365 const next_it = node.next;
364
365 self.child_allocator.free(node.data);366 self.child_allocator.free(node.data);
367 it = next_it;
366 }368 }
367 }369 }
368370
std/heap/logging_allocator.zig created+53
...@@ -0,0 +1,53 @@
1const std = @import("../std.zig");
2const Allocator = std.mem.Allocator;
3
4const AnyErrorOutStream = std.io.OutStream(anyerror);
5
6/// This allocator is used in front of another allocator and logs to the provided stream
7/// on every call to the allocator. Stream errors are ignored.
8/// If https://github.com/ziglang/zig/issues/2586 is implemented, this API can be improved.
9pub const LoggingAllocator = struct {
10 allocator: Allocator,
11 parent_allocator: *Allocator,
12 out_stream: *AnyErrorOutStream,
13
14 const Self = @This();
15
16 pub fn init(parent_allocator: *Allocator, out_stream: *AnyErrorOutStream) Self {
17 return Self{
18 .allocator = Allocator{
19 .reallocFn = realloc,
20 .shrinkFn = shrink,
21 },
22 .parent_allocator = parent_allocator,
23 .out_stream = out_stream,
24 };
25 }
26
27 fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
28 const self = @fieldParentPtr(Self, "allocator", allocator);
29 if (old_mem.len == 0) {
30 self.out_stream.print("allocation of {} ", new_size) catch {};
31 } else {
32 self.out_stream.print("resize from {} to {} ", old_mem.len, new_size) catch {};
33 }
34 const result = self.parent_allocator.reallocFn(self.parent_allocator, old_mem, old_align, new_size, new_align);
35 if (result) |buff| {
36 self.out_stream.print("success!\n") catch {};
37 } else |err| {
38 self.out_stream.print("failure!\n") catch {};
39 }
40 return result;
41 }
42
43 fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
44 const self = @fieldParentPtr(Self, "allocator", allocator);
45 const result = self.parent_allocator.shrinkFn(self.parent_allocator, old_mem, old_align, new_size, new_align);
46 if (new_size == 0) {
47 self.out_stream.print("free of {} bytes success!\n", old_mem.len) catch {};
48 } else {
49 self.out_stream.print("shrink from {} bytes to {} bytes success!\n", old_mem.len, new_size) catch {};
50 }
51 return result;
52 }
53};
std/http.zig created+5
...@@ -0,0 +1,5 @@
1test "std.http" {
2 _ = @import("http/headers.zig");
3}
4
5pub const Headers = @import("http/headers.zig").Headers;
std/http/headers.zig created+614
...@@ -0,0 +1,614 @@
1// HTTP Header data structure/type
2// Based on lua-http's http.header module
3//
4// Design criteria:
5// - the same header field is allowed more than once
6// - must be able to fetch separate occurrences (important for some headers e.g. Set-Cookie)
7// - optionally available as comma separated list
8// - http2 adds flag to headers that they should never be indexed
9// - header order should be recoverable
10//
11// Headers are implemented as an array of entries.
12// An index of field name => array indices is kept.
13
14const std = @import("../std.zig");
15const debug = std.debug;
16const assert = debug.assert;
17const testing = std.testing;
18const mem = std.mem;
19const Allocator = mem.Allocator;
20
21fn never_index_default(name: []const u8) bool {
22 if (mem.eql(u8, "authorization", name)) return true;
23 if (mem.eql(u8, "proxy-authorization", name)) return true;
24 if (mem.eql(u8, "cookie", name)) return true;
25 if (mem.eql(u8, "set-cookie", name)) return true;
26 return false;
27}
28
29const HeaderEntry = struct {
30 allocator: *Allocator,
31 pub name: []const u8,
32 pub value: []u8,
33 pub never_index: bool,
34
35 const Self = @This();
36
37 fn init(allocator: *Allocator, name: []const u8, value: []const u8, never_index: ?bool) !Self {
38 return Self{
39 .allocator = allocator,
40 .name = name, // takes reference
41 .value = try mem.dupe(allocator, u8, value),
42 .never_index = never_index orelse never_index_default(name),
43 };
44 }
45
46 fn deinit(self: Self) void {
47 self.allocator.free(self.value);
48 }
49
50 pub fn modify(self: *Self, value: []const u8, never_index: ?bool) !void {
51 const old_len = self.value.len;
52 if (value.len > old_len) {
53 self.value = try self.allocator.realloc(self.value, value.len);
54 } else if (value.len < old_len) {
55 self.value = self.allocator.shrink(self.value, value.len);
56 }
57 mem.copy(u8, self.value, value);
58 self.never_index = never_index orelse never_index_default(self.name);
59 }
60
61 fn compare(a: HeaderEntry, b: HeaderEntry) bool {
62 if (a.name.ptr != b.name.ptr and a.name.len != b.name.len) {
63 // Things beginning with a colon *must* be before others
64 const a_is_colon = a.name[0] == ':';
65 const b_is_colon = b.name[0] == ':';
66 if (a_is_colon and !b_is_colon) {
67 return true;
68 } else if (!a_is_colon and b_is_colon) {
69 return false;
70 }
71
72 // Sort lexicographically on header name
73 return mem.compare(u8, a.name, b.name) == mem.Compare.LessThan;
74 }
75
76 // Sort lexicographically on header value
77 if (!mem.eql(u8, a.value, b.value)) {
78 return mem.compare(u8, a.value, b.value) == mem.Compare.LessThan;
79 }
80
81 // Doesn't matter here; need to pick something for sort consistency
82 return a.never_index;
83 }
84};
85
86var test_memory: [32 * 1024]u8 = undefined;
87var test_fba_state = std.heap.FixedBufferAllocator.init(&test_memory);
88const test_allocator = &test_fba_state.allocator;
89
90test "HeaderEntry" {
91 var e = try HeaderEntry.init(test_allocator, "foo", "bar", null);
92 defer e.deinit();
93 testing.expectEqualSlices(u8, "foo", e.name);
94 testing.expectEqualSlices(u8, "bar", e.value);
95 testing.expectEqual(false, e.never_index);
96
97 try e.modify("longer value", null);
98 testing.expectEqualSlices(u8, "longer value", e.value);
99
100 // shorter value
101 try e.modify("x", null);
102 testing.expectEqualSlices(u8, "x", e.value);
103}
104
105const HeaderList = std.ArrayList(HeaderEntry);
106const HeaderIndexList = std.ArrayList(usize);
107const HeaderIndex = std.AutoHashMap([]const u8, HeaderIndexList);
108
109pub const Headers = struct {
110 // the owned header field name is stored in the index as part of the key
111 allocator: *Allocator,
112 data: HeaderList,
113 index: HeaderIndex,
114
115 const Self = @This();
116
117 pub fn init(allocator: *Allocator) Self {
118 return Self{
119 .allocator = allocator,
120 .data = HeaderList.init(allocator),
121 .index = HeaderIndex.init(allocator),
122 };
123 }
124
125 pub fn deinit(self: Self) void {
126 {
127 var it = self.index.iterator();
128 while (it.next()) |kv| {
129 var dex = &kv.value;
130 dex.deinit();
131 self.allocator.free(kv.key);
132 }
133 self.index.deinit();
134 }
135 {
136 var it = self.data.iterator();
137 while (it.next()) |entry| {
138 entry.deinit();
139 }
140 self.data.deinit();
141 }
142 }
143
144 pub fn clone(self: Self, allocator: *Allocator) !Self {
145 var other = Headers.init(allocator);
146 errdefer other.deinit();
147 try other.data.ensureCapacity(self.data.count());
148 try other.index.initCapacity(self.index.entries.len);
149 var it = self.data.iterator();
150 while (it.next()) |entry| {
151 try other.append(entry.name, entry.value, entry.never_index);
152 }
153 return other;
154 }
155
156 pub fn count(self: Self) usize {
157 return self.data.count();
158 }
159
160 pub const Iterator = HeaderList.Iterator;
161
162 pub fn iterator(self: Self) Iterator {
163 return self.data.iterator();
164 }
165
166 pub fn append(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
167 const n = self.data.count() + 1;
168 try self.data.ensureCapacity(n);
169 var entry: HeaderEntry = undefined;
170 if (self.index.get(name)) |kv| {
171 entry = try HeaderEntry.init(self.allocator, kv.key, value, never_index);
172 errdefer entry.deinit();
173 var dex = &kv.value;
174 try dex.append(n - 1);
175 } else {
176 const name_dup = try mem.dupe(self.allocator, u8, name);
177 errdefer self.allocator.free(name_dup);
178 entry = try HeaderEntry.init(self.allocator, name_dup, value, never_index);
179 errdefer entry.deinit();
180 var dex = HeaderIndexList.init(self.allocator);
181 try dex.append(n - 1);
182 errdefer dex.deinit();
183 _ = try self.index.put(name, dex);
184 }
185 self.data.appendAssumeCapacity(entry);
186 }
187
188 /// If the header already exists, replace the current value, otherwise append it to the list of headers.
189 /// If the header has multiple entries then returns an error.
190 pub fn upsert(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
191 if (self.index.get(name)) |kv| {
192 const dex = kv.value;
193 if (dex.count() != 1)
194 return error.CannotUpsertMultiValuedField;
195 var e = &self.data.at(dex.at(0));
196 try e.modify(value, never_index);
197 } else {
198 try self.append(name, value, never_index);
199 }
200 }
201
202 /// Returns boolean indicating if the field is present.
203 pub fn contains(self: Self, name: []const u8) bool {
204 return self.index.contains(name);
205 }
206
207 /// Returns boolean indicating if something was deleted.
208 pub fn delete(self: *Self, name: []const u8) bool {
209 if (self.index.remove(name)) |kv| {
210 var dex = &kv.value;
211 // iterate backwards
212 var i = dex.count();
213 while (i > 0) {
214 i -= 1;
215 const data_index = dex.at(i);
216 const removed = self.data.orderedRemove(data_index);
217 assert(mem.eql(u8, removed.name, name));
218 removed.deinit();
219 }
220 dex.deinit();
221 self.allocator.free(kv.key);
222 self.rebuild_index();
223 return true;
224 } else {
225 return false;
226 }
227 }
228
229 /// Removes the element at the specified index.
230 /// Moves items down to fill the empty space.
231 pub fn orderedRemove(self: *Self, i: usize) void {
232 const removed = self.data.orderedRemove(i);
233 const kv = self.index.get(removed.name).?;
234 var dex = &kv.value;
235 if (dex.count() == 1) {
236 // was last item; delete the index
237 _ = self.index.remove(kv.key);
238 dex.deinit();
239 removed.deinit();
240 self.allocator.free(kv.key);
241 } else {
242 dex.shrink(dex.count() - 1);
243 removed.deinit();
244 }
245 // if it was the last item; no need to rebuild index
246 if (i != self.data.count()) {
247 self.rebuild_index();
248 }
249 }
250
251 /// Removes the element at the specified index.
252 /// The empty slot is filled from the end of the list.
253 pub fn swapRemove(self: *Self, i: usize) void {
254 const removed = self.data.swapRemove(i);
255 const kv = self.index.get(removed.name).?;
256 var dex = &kv.value;
257 if (dex.count() == 1) {
258 // was last item; delete the index
259 _ = self.index.remove(kv.key);
260 dex.deinit();
261 removed.deinit();
262 self.allocator.free(kv.key);
263 } else {
264 dex.shrink(dex.count() - 1);
265 removed.deinit();
266 }
267 // if it was the last item; no need to rebuild index
268 if (i != self.data.count()) {
269 self.rebuild_index();
270 }
271 }
272
273 /// Access the header at the specified index.
274 pub fn at(self: Self, i: usize) HeaderEntry {
275 return self.data.at(i);
276 }
277
278 /// Returns a list of indices containing headers with the given name.
279 /// The returned list should not be modified by the caller.
280 pub fn getIndices(self: Self, name: []const u8) ?HeaderIndexList {
281 if (self.index.get(name)) |kv| {
282 return kv.value;
283 } else {
284 return null;
285 }
286 }
287
288 /// Returns a slice containing each header with the given name.
289 pub fn get(self: Self, allocator: *Allocator, name: []const u8) !?[]const HeaderEntry {
290 const dex = self.getIndices(name) orelse return null;
291
292 const buf = try allocator.alloc(HeaderEntry, dex.count());
293 var it = dex.iterator();
294 var n: usize = 0;
295 while (it.next()) |idx| {
296 buf[n] = self.data.at(idx);
297 n += 1;
298 }
299 return buf;
300 }
301
302 /// Returns all headers with the given name as a comma seperated string.
303 ///
304 /// Useful for HTTP headers that follow RFC-7230 section 3.2.2:
305 /// A recipient MAY combine multiple header fields with the same field
306 /// name into one "field-name: field-value" pair, without changing the
307 /// semantics of the message, by appending each subsequent field value to
308 /// the combined field value in order, separated by a comma. The order
309 /// in which header fields with the same field name are received is
310 /// therefore significant to the interpretation of the combined field
311 /// value
312 pub fn getCommaSeparated(self: Self, allocator: *Allocator, name: []const u8) !?[]u8 {
313 const dex = self.getIndices(name) orelse return null;
314
315 // adapted from mem.join
316 const total_len = blk: {
317 var sum: usize = dex.count() - 1; // space for separator(s)
318 var it = dex.iterator();
319 while (it.next()) |idx|
320 sum += self.data.at(idx).value.len;
321 break :blk sum;
322 };
323
324 const buf = try allocator.alloc(u8, total_len);
325 errdefer allocator.free(buf);
326
327 const first_value = self.data.at(dex.at(0)).value;
328 mem.copy(u8, buf, first_value);
329 var buf_index: usize = first_value.len;
330 for (dex.toSlice()[1..]) |idx| {
331 const value = self.data.at(idx).value;
332 buf[buf_index] = ',';
333 buf_index += 1;
334 mem.copy(u8, buf[buf_index..], value);
335 buf_index += value.len;
336 }
337
338 // No need for shrink since buf is exactly the correct size.
339 return buf;
340 }
341
342 fn rebuild_index(self: *Self) void {
343 { // clear out the indexes
344 var it = self.index.iterator();
345 while (it.next()) |kv| {
346 var dex = &kv.value;
347 dex.len = 0; // keeps capacity available
348 }
349 }
350 { // fill up indexes again; we know capacity is fine from before
351 var it = self.data.iterator();
352 while (it.next()) |entry| {
353 var dex = &self.index.get(entry.name).?.value;
354 dex.appendAssumeCapacity(it.count);
355 }
356 }
357 }
358
359 pub fn sort(self: *Self) void {
360 std.sort.sort(HeaderEntry, self.data.toSlice(), HeaderEntry.compare);
361 self.rebuild_index();
362 }
363
364 pub fn format(
365 self: Self,
366 comptime fmt: []const u8,
367 options: std.fmt.FormatOptions,
368 context: var,
369 comptime Errors: type,
370 output: fn (@typeOf(context), []const u8) Errors!void,
371 ) Errors!void {
372 var it = self.iterator();
373 while (it.next()) |entry| {
374 try output(context, entry.name);
375 try output(context, ": ");
376 try output(context, entry.value);
377 try output(context, "\n");
378 }
379 }
380};
381
382test "Headers.iterator" {
383 var h = Headers.init(test_allocator);
384 defer h.deinit();
385 try h.append("foo", "bar", null);
386 try h.append("cookie", "somevalue", null);
387
388 var count: i32 = 0;
389 var it = h.iterator();
390 while (it.next()) |e| {
391 if (count == 0) {
392 testing.expectEqualSlices(u8, "foo", e.name);
393 testing.expectEqualSlices(u8, "bar", e.value);
394 testing.expectEqual(false, e.never_index);
395 } else if (count == 1) {
396 testing.expectEqualSlices(u8, "cookie", e.name);
397 testing.expectEqualSlices(u8, "somevalue", e.value);
398 testing.expectEqual(true, e.never_index);
399 }
400 count += 1;
401 }
402 testing.expectEqual(i32(2), count);
403}
404
405test "Headers.contains" {
406 var h = Headers.init(test_allocator);
407 defer h.deinit();
408 try h.append("foo", "bar", null);
409 try h.append("cookie", "somevalue", null);
410
411 testing.expectEqual(true, h.contains("foo"));
412 testing.expectEqual(false, h.contains("flooble"));
413}
414
415test "Headers.delete" {
416 var h = Headers.init(test_allocator);
417 defer h.deinit();
418 try h.append("foo", "bar", null);
419 try h.append("baz", "qux", null);
420 try h.append("cookie", "somevalue", null);
421
422 testing.expectEqual(false, h.delete("not-present"));
423 testing.expectEqual(usize(3), h.count());
424
425 testing.expectEqual(true, h.delete("foo"));
426 testing.expectEqual(usize(2), h.count());
427 {
428 const e = h.at(0);
429 testing.expectEqualSlices(u8, "baz", e.name);
430 testing.expectEqualSlices(u8, "qux", e.value);
431 testing.expectEqual(false, e.never_index);
432 }
433 {
434 const e = h.at(1);
435 testing.expectEqualSlices(u8, "cookie", e.name);
436 testing.expectEqualSlices(u8, "somevalue", e.value);
437 testing.expectEqual(true, e.never_index);
438 }
439
440 testing.expectEqual(false, h.delete("foo"));
441}
442
443test "Headers.orderedRemove" {
444 var h = Headers.init(test_allocator);
445 defer h.deinit();
446 try h.append("foo", "bar", null);
447 try h.append("baz", "qux", null);
448 try h.append("cookie", "somevalue", null);
449
450 h.orderedRemove(0);
451 testing.expectEqual(usize(2), h.count());
452 {
453 const e = h.at(0);
454 testing.expectEqualSlices(u8, "baz", e.name);
455 testing.expectEqualSlices(u8, "qux", e.value);
456 testing.expectEqual(false, e.never_index);
457 }
458 {
459 const e = h.at(1);
460 testing.expectEqualSlices(u8, "cookie", e.name);
461 testing.expectEqualSlices(u8, "somevalue", e.value);
462 testing.expectEqual(true, e.never_index);
463 }
464}
465
466test "Headers.swapRemove" {
467 var h = Headers.init(test_allocator);
468 defer h.deinit();
469 try h.append("foo", "bar", null);
470 try h.append("baz", "qux", null);
471 try h.append("cookie", "somevalue", null);
472
473 h.swapRemove(0);
474 testing.expectEqual(usize(2), h.count());
475 {
476 const e = h.at(0);
477 testing.expectEqualSlices(u8, "cookie", e.name);
478 testing.expectEqualSlices(u8, "somevalue", e.value);
479 testing.expectEqual(true, e.never_index);
480 }
481 {
482 const e = h.at(1);
483 testing.expectEqualSlices(u8, "baz", e.name);
484 testing.expectEqualSlices(u8, "qux", e.value);
485 testing.expectEqual(false, e.never_index);
486 }
487}
488
489test "Headers.at" {
490 var h = Headers.init(test_allocator);
491 defer h.deinit();
492 try h.append("foo", "bar", null);
493 try h.append("cookie", "somevalue", null);
494
495 {
496 const e = h.at(0);
497 testing.expectEqualSlices(u8, "foo", e.name);
498 testing.expectEqualSlices(u8, "bar", e.value);
499 testing.expectEqual(false, e.never_index);
500 }
501 {
502 const e = h.at(1);
503 testing.expectEqualSlices(u8, "cookie", e.name);
504 testing.expectEqualSlices(u8, "somevalue", e.value);
505 testing.expectEqual(true, e.never_index);
506 }
507}
508
509test "Headers.getIndices" {
510 var h = Headers.init(test_allocator);
511 defer h.deinit();
512 try h.append("foo", "bar", null);
513 try h.append("set-cookie", "x=1", null);
514 try h.append("set-cookie", "y=2", null);
515
516 testing.expect(null == h.getIndices("not-present"));
517 testing.expectEqualSlices(usize, [_]usize{0}, h.getIndices("foo").?.toSliceConst());
518 testing.expectEqualSlices(usize, [_]usize{ 1, 2 }, h.getIndices("set-cookie").?.toSliceConst());
519}
520
521test "Headers.get" {
522 var h = Headers.init(test_allocator);
523 defer h.deinit();
524 try h.append("foo", "bar", null);
525 try h.append("set-cookie", "x=1", null);
526 try h.append("set-cookie", "y=2", null);
527
528 {
529 const v = try h.get(test_allocator, "not-present");
530 testing.expect(null == v);
531 }
532 {
533 const v = (try h.get(test_allocator, "foo")).?;
534 defer test_allocator.free(v);
535 const e = v[0];
536 testing.expectEqualSlices(u8, "foo", e.name);
537 testing.expectEqualSlices(u8, "bar", e.value);
538 testing.expectEqual(false, e.never_index);
539 }
540 {
541 const v = (try h.get(test_allocator, "set-cookie")).?;
542 defer test_allocator.free(v);
543 {
544 const e = v[0];
545 testing.expectEqualSlices(u8, "set-cookie", e.name);
546 testing.expectEqualSlices(u8, "x=1", e.value);
547 testing.expectEqual(true, e.never_index);
548 }
549 {
550 const e = v[1];
551 testing.expectEqualSlices(u8, "set-cookie", e.name);
552 testing.expectEqualSlices(u8, "y=2", e.value);
553 testing.expectEqual(true, e.never_index);
554 }
555 }
556}
557
558test "Headers.getCommaSeparated" {
559 var h = Headers.init(test_allocator);
560 defer h.deinit();
561 try h.append("foo", "bar", null);
562 try h.append("set-cookie", "x=1", null);
563 try h.append("set-cookie", "y=2", null);
564
565 {
566 const v = try h.getCommaSeparated(test_allocator, "not-present");
567 testing.expect(null == v);
568 }
569 {
570 const v = (try h.getCommaSeparated(test_allocator, "foo")).?;
571 defer test_allocator.free(v);
572 testing.expectEqualSlices(u8, "bar", v);
573 }
574 {
575 const v = (try h.getCommaSeparated(test_allocator, "set-cookie")).?;
576 defer test_allocator.free(v);
577 testing.expectEqualSlices(u8, "x=1,y=2", v);
578 }
579}
580
581test "Headers.sort" {
582 var h = Headers.init(test_allocator);
583 defer h.deinit();
584 try h.append("foo", "bar", null);
585 try h.append("cookie", "somevalue", null);
586
587 h.sort();
588 {
589 const e = h.at(0);
590 testing.expectEqualSlices(u8, "cookie", e.name);
591 testing.expectEqualSlices(u8, "somevalue", e.value);
592 testing.expectEqual(true, e.never_index);
593 }
594 {
595 const e = h.at(1);
596 testing.expectEqualSlices(u8, "foo", e.name);
597 testing.expectEqualSlices(u8, "bar", e.value);
598 testing.expectEqual(false, e.never_index);
599 }
600}
601
602test "Headers.format" {
603 var h = Headers.init(test_allocator);
604 defer h.deinit();
605 try h.append("foo", "bar", null);
606 try h.append("cookie", "somevalue", null);
607
608 var buf: [100]u8 = undefined;
609 testing.expectEqualSlices(u8,
610 \\foo: bar
611 \\cookie: somevalue
612 \\
613 , try std.fmt.bufPrint(buf[0..], "{}", h));
614}
std/io.zig+10-10
...@@ -164,32 +164,32 @@ pub fn InStream(comptime ReadError: type) type {...@@ -164,32 +164,32 @@ pub fn InStream(comptime ReadError: type) type {
164164
165 /// Reads a native-endian integer165 /// Reads a native-endian integer
166 pub fn readIntNative(self: *Self, comptime T: type) !T {166 pub fn readIntNative(self: *Self, comptime T: type) !T {
167 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;167 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
168 try self.readNoEof(bytes[0..]);168 try self.readNoEof(bytes[0..]);
169 return mem.readIntNative(T, &bytes);169 return mem.readIntNative(T, &bytes);
170 }170 }
171171
172 /// Reads a foreign-endian integer172 /// Reads a foreign-endian integer
173 pub fn readIntForeign(self: *Self, comptime T: type) !T {173 pub fn readIntForeign(self: *Self, comptime T: type) !T {
174 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;174 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
175 try self.readNoEof(bytes[0..]);175 try self.readNoEof(bytes[0..]);
176 return mem.readIntForeign(T, &bytes);176 return mem.readIntForeign(T, &bytes);
177 }177 }
178178
179 pub fn readIntLittle(self: *Self, comptime T: type) !T {179 pub fn readIntLittle(self: *Self, comptime T: type) !T {
180 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;180 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
181 try self.readNoEof(bytes[0..]);181 try self.readNoEof(bytes[0..]);
182 return mem.readIntLittle(T, &bytes);182 return mem.readIntLittle(T, &bytes);
183 }183 }
184184
185 pub fn readIntBig(self: *Self, comptime T: type) !T {185 pub fn readIntBig(self: *Self, comptime T: type) !T {
186 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;186 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
187 try self.readNoEof(bytes[0..]);187 try self.readNoEof(bytes[0..]);
188 return mem.readIntBig(T, &bytes);188 return mem.readIntBig(T, &bytes);
189 }189 }
190190
191 pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {191 pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
192 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;192 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
193 try self.readNoEof(bytes[0..]);193 try self.readNoEof(bytes[0..]);
194 return mem.readInt(T, &bytes, endian);194 return mem.readInt(T, &bytes, endian);
195 }195 }
...@@ -249,32 +249,32 @@ pub fn OutStream(comptime WriteError: type) type {...@@ -249,32 +249,32 @@ pub fn OutStream(comptime WriteError: type) type {
249249
250 /// Write a native-endian integer.250 /// Write a native-endian integer.
251 pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {251 pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
252 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;252 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
253 mem.writeIntNative(T, &bytes, value);253 mem.writeIntNative(T, &bytes, value);
254 return self.writeFn(self, bytes);254 return self.writeFn(self, bytes);
255 }255 }
256256
257 /// Write a foreign-endian integer.257 /// Write a foreign-endian integer.
258 pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {258 pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
259 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;259 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
260 mem.writeIntForeign(T, &bytes, value);260 mem.writeIntForeign(T, &bytes, value);
261 return self.writeFn(self, bytes);261 return self.writeFn(self, bytes);
262 }262 }
263263
264 pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {264 pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
265 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;265 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
266 mem.writeIntLittle(T, &bytes, value);266 mem.writeIntLittle(T, &bytes, value);
267 return self.writeFn(self, bytes);267 return self.writeFn(self, bytes);
268 }268 }
269269
270 pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {270 pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
271 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;271 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
272 mem.writeIntBig(T, &bytes, value);272 mem.writeIntBig(T, &bytes, value);
273 return self.writeFn(self, bytes);273 return self.writeFn(self, bytes);
274 }274 }
275275
276 pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {276 pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
277 var bytes: [(T.bit_count + 7 )/ 8]u8 = undefined;277 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;
278 mem.writeInt(T, &bytes, value, endian);278 mem.writeInt(T, &bytes, value, endian);
279 return self.writeFn(self, bytes);279 return self.writeFn(self, bytes);
280 }280 }
std/io/test.zig+4-1
...@@ -597,7 +597,10 @@ test "c out stream" {...@@ -597,7 +597,10 @@ test "c out stream" {
597597
598 const filename = c"tmp_io_test_file.txt";598 const filename = c"tmp_io_test_file.txt";
599 const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;599 const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;
600 defer fs.deleteFileC(filename) catch {};600 defer {
601 _ = std.c.fclose(out_file);
602 fs.deleteFileC(filename) catch {};
603 }
601604
602 const out_stream = &io.COutStream.init(out_file).stream;605 const out_stream = &io.COutStream.init(out_file).stream;
603 try out_stream.print("hi: {}\n", i32(123));606 try out_stream.print("hi: {}\n", i32(123));
std/json.zig+2-1
...@@ -876,8 +876,9 @@ pub const TokenStream = struct {...@@ -876,8 +876,9 @@ pub const TokenStream = struct {
876876
877 pub fn next(self: *TokenStream) !?Token {877 pub fn next(self: *TokenStream) !?Token {
878 if (self.token) |token| {878 if (self.token) |token| {
879 const copy = token;
879 self.token = null;880 self.token = null;
880 return token;881 return copy;
881 }882 }
882883
883 var t1: ?Token = undefined;884 var t1: ?Token = undefined;
std/math/big/int.zig+1
...@@ -519,6 +519,7 @@ pub const Int = struct {...@@ -519,6 +519,7 @@ pub const Int = struct {
519 pub fn format(519 pub fn format(
520 self: Int,520 self: Int,
521 comptime fmt: []const u8,521 comptime fmt: []const u8,
522 comptime options: std.fmt.FormatOptions,
522 context: var,523 context: var,
523 comptime FmtError: type,524 comptime FmtError: type,
524 output: fn (@typeOf(context), []const u8) FmtError!void,525 output: fn (@typeOf(context), []const u8) FmtError!void,
std/mem.zig+6
...@@ -1481,6 +1481,7 @@ test "subArrayPtr" {...@@ -1481,6 +1481,7 @@ test "subArrayPtr" {
1481}1481}
14821482
1483/// Round an address up to the nearest aligned address1483/// Round an address up to the nearest aligned address
1484/// The alignment must be a power of 2 and greater than 0.
1484pub fn alignForward(addr: usize, alignment: usize) usize {1485pub fn alignForward(addr: usize, alignment: usize) usize {
1485 return alignBackward(addr + (alignment - 1), alignment);1486 return alignBackward(addr + (alignment - 1), alignment);
1486}1487}
...@@ -1500,13 +1501,18 @@ test "alignForward" {...@@ -1500,13 +1501,18 @@ test "alignForward" {
1500 testing.expect(alignForward(17, 8) == 24);1501 testing.expect(alignForward(17, 8) == 24);
1501}1502}
15021503
1504/// Round an address up to the previous aligned address
1505/// The alignment must be a power of 2 and greater than 0.
1503pub fn alignBackward(addr: usize, alignment: usize) usize {1506pub fn alignBackward(addr: usize, alignment: usize) usize {
1507 assert(@popCount(usize, alignment) == 1);
1504 // 000010000 // example addr1508 // 000010000 // example addr
1505 // 000001111 // subtract 11509 // 000001111 // subtract 1
1506 // 111110000 // binary not1510 // 111110000 // binary not
1507 return addr & ~(alignment - 1);1511 return addr & ~(alignment - 1);
1508}1512}
15091513
1514/// Given an address and an alignment, return true if the address is a multiple of the alignment
1515/// The alignment must be a power of 2 and greater than 0.
1510pub fn isAligned(addr: usize, alignment: usize) bool {1516pub fn isAligned(addr: usize, alignment: usize) bool {
1511 return alignBackward(addr, alignment) == addr;1517 return alignBackward(addr, alignment) == addr;
1512}1518}
std/net.zig-1
...@@ -33,7 +33,6 @@ pub const Address = struct {...@@ -33,7 +33,6 @@ pub const Address = struct {
3333
34 pub fn initIp6(ip6: *const Ip6Addr, _port: u16) Address {34 pub fn initIp6(ip6: *const Ip6Addr, _port: u16) Address {
35 return Address{35 return Address{
36 .family = os.AF_INET6,
37 .os_addr = os.sockaddr{36 .os_addr = os.sockaddr{
38 .in6 = os.sockaddr_in6{37 .in6 = os.sockaddr_in6{
39 .family = os.AF_INET6,38 .family = os.AF_INET6,
std/os/windows.zig+2
...@@ -348,6 +348,7 @@ pub const DeleteFileError = error{...@@ -348,6 +348,7 @@ pub const DeleteFileError = error{
348 FileNotFound,348 FileNotFound,
349 AccessDenied,349 AccessDenied,
350 NameTooLong,350 NameTooLong,
351 FileBusy,
351 Unexpected,352 Unexpected,
352};353};
353354
...@@ -363,6 +364,7 @@ pub fn DeleteFileW(filename: [*]const u16) DeleteFileError!void {...@@ -363,6 +364,7 @@ pub fn DeleteFileW(filename: [*]const u16) DeleteFileError!void {
363 ERROR.ACCESS_DENIED => return error.AccessDenied,364 ERROR.ACCESS_DENIED => return error.AccessDenied,
364 ERROR.FILENAME_EXCED_RANGE => return error.NameTooLong,365 ERROR.FILENAME_EXCED_RANGE => return error.NameTooLong,
365 ERROR.INVALID_PARAMETER => return error.NameTooLong,366 ERROR.INVALID_PARAMETER => return error.NameTooLong,
367 ERROR.SHARING_VIOLATION => return error.FileBusy,
366 else => |err| return unexpectedError(err),368 else => |err| return unexpectedError(err),
367 }369 }
368 }370 }
std/special/bootstrap.zig+6-7
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1// This file is in a package which has the root source file exposed as "@root".1// This file is included in the compilation unit when exporting an executable.
2// It is included in the compilation unit when exporting an executable.
32
4const root = @import("@root");3const root = @import("root");
5const std = @import("std");4const std = @import("std");
6const builtin = @import("builtin");5const builtin = @import("builtin");
7const assert = std.debug.assert;6const assert = std.debug.assert;
...@@ -114,20 +113,20 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {...@@ -114,20 +113,20 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
114// and we want fewer call frames in stack traces.113// and we want fewer call frames in stack traces.
115inline fn callMain() u8 {114inline fn callMain() u8 {
116 switch (@typeId(@typeOf(root.main).ReturnType)) {115 switch (@typeId(@typeOf(root.main).ReturnType)) {
117 builtin.TypeId.NoReturn => {116 .NoReturn => {
118 root.main();117 root.main();
119 },118 },
120 builtin.TypeId.Void => {119 .Void => {
121 root.main();120 root.main();
122 return 0;121 return 0;
123 },122 },
124 builtin.TypeId.Int => {123 .Int => {
125 if (@typeOf(root.main).ReturnType.bit_count != 8) {124 if (@typeOf(root.main).ReturnType.bit_count != 8) {
126 @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'");125 @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'");
127 }126 }
128 return root.main();127 return root.main();
129 },128 },
130 builtin.TypeId.ErrorUnion => {129 .ErrorUnion => {
131 root.main() catch |err| {130 root.main() catch |err| {
132 std.debug.warn("error: {}\n", @errorName(err));131 std.debug.warn("error: {}\n", @errorName(err));
133 if (builtin.os != builtin.Os.zen) {132 if (builtin.os != builtin.Os.zen) {
std/special/build_runner.zig+2-2
...@@ -167,7 +167,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {...@@ -167,7 +167,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
167167
168 const allocator = builder.allocator;168 const allocator = builder.allocator;
169 for (builder.top_level_steps.toSliceConst()) |top_level_step| {169 for (builder.top_level_steps.toSliceConst()) |top_level_step| {
170 try out_stream.print(" {s22} {}\n", top_level_step.step.name, top_level_step.description);170 try out_stream.print(" {s:22} {}\n", top_level_step.step.name, top_level_step.description);
171 }171 }
172172
173 try out_stream.write(173 try out_stream.write(
...@@ -188,7 +188,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {...@@ -188,7 +188,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
188 for (builder.available_options_list.toSliceConst()) |option| {188 for (builder.available_options_list.toSliceConst()) |option| {
189 const name = try fmt.allocPrint(allocator, " -D{}=[{}]", option.name, Builder.typeIdName(option.type_id));189 const name = try fmt.allocPrint(allocator, " -D{}=[{}]", option.name, Builder.typeIdName(option.type_id));
190 defer allocator.free(name);190 defer allocator.free(name);
191 try out_stream.print("{s24} {}\n", name, option.description);191 try out_stream.print("{s:24} {}\n", name, option.description);
192 }192 }
193 }193 }
194194
std/special/c.zig+26-13
...@@ -254,19 +254,32 @@ export fn fmod(x: f64, y: f64) f64 {...@@ -254,19 +254,32 @@ export fn fmod(x: f64, y: f64) f64 {
254254
255// TODO add intrinsics for these (and probably the double version too)255// TODO add intrinsics for these (and probably the double version too)
256// and have the math stuff use the intrinsic. same as @mod and @rem256// and have the math stuff use the intrinsic. same as @mod and @rem
257export fn floorf(x: f32) f32 {257export fn floorf(x: f32) f32 {return math.floor(x);}
258 return math.floor(x);258export fn ceilf(x: f32) f32 {return math.ceil(x);}
259}259export fn floor(x: f64) f64 {return math.floor(x);}
260export fn ceilf(x: f32) f32 {260export fn ceil(x: f64) f64 {return math.ceil(x);}
261 return math.ceil(x);261export fn fma(a: f64, b: f64, c: f64) f64 {return math.fma(f64, a, b, c);}
262}262export fn fmaf(a: f32, b: f32, c: f32) f32 {return math.fma(f32, a, b, c);}
263export fn floor(x: f64) f64 {263export fn sin(a: f64) f64 {return math.sin(a);}
264 return math.floor(x);264export fn sinf(a: f32) f32 {return math.sin(a);}
265}265export fn cos(a: f64) f64 {return math.cos(a);}
266export fn ceil(x: f64) f64 {266export fn cosf(a: f32) f32 {return math.cos(a);}
267 return math.ceil(x);267export fn exp(a: f64) f64 {return math.exp(a);}
268}268export fn expf(a: f32) f32 {return math.exp(a);}
269269export fn exp2(a: f64) f64 {return math.exp2(a);}
270export fn exp2f(a: f32) f32 {return math.exp2(a);}
271export fn log(a: f64) f64 {return math.ln(a);}
272export fn logf(a: f32) f32 {return math.ln(a);}
273export fn log2(a: f64) f64 {return math.log2(a);}
274export fn log2f(a: f32) f32 {return math.log2(a);}
275export fn log10(a: f64) f64 {return math.log10(a);}
276export fn log10f(a: f32) f32 {return math.log10(a);}
277export fn fabs(a: f64) f64 {return math.fabs(a);}
278export fn fabsf(a: f32) f32 {return math.fabs(a);}
279export fn trunc(a: f64) f64 {return math.trunc(a);}
280export fn truncf(a: f32) f32 {return math.trunc(a);}
281export fn round(a: f64) f64 {return math.round(a);}
282export fn roundf(a: f32) f32 {return math.round(a);}
270fn generic_fmod(comptime T: type, x: T, y: T) T {283fn generic_fmod(comptime T: type, x: T, y: T) T {
271 @setRuntimeSafety(false);284 @setRuntimeSafety(false);
272285
std/special/compiler_rt.zig+39-6
...@@ -405,15 +405,15 @@ const use_thumb_1 = usesThumb1(builtin.arch);...@@ -405,15 +405,15 @@ const use_thumb_1 = usesThumb1(builtin.arch);
405405
406fn usesThumb1(arch: builtin.Arch) bool {406fn usesThumb1(arch: builtin.Arch) bool {
407 return switch (arch) {407 return switch (arch) {
408 .arm => switch (arch.arm) {408 .arm => |sub_arch| switch (sub_arch) {
409 .v6m => true,409 .v6m => true,
410 else => false,410 else => false,
411 },411 },
412 .armeb => switch (arch.armeb) {412 .armeb => |sub_arch| switch (sub_arch) {
413 .v6m => true,413 .v6m => true,
414 else => false,414 else => false,
415 },415 },
416 .thumb => switch (arch.thumb) {416 .thumb => |sub_arch| switch (sub_arch) {
417 .v5,417 .v5,
418 .v5te,418 .v5te,
419 .v4t,419 .v4t,
...@@ -423,7 +423,7 @@ fn usesThumb1(arch: builtin.Arch) bool {...@@ -423,7 +423,7 @@ fn usesThumb1(arch: builtin.Arch) bool {
423 => true,423 => true,
424 else => false,424 else => false,
425 },425 },
426 .thumbeb => switch (arch.thumbeb) {426 .thumbeb => |sub_arch| switch (sub_arch) {
427 .v5,427 .v5,
428 .v5te,428 .v5te,
429 .v4t,429 .v4t,
...@@ -471,6 +471,22 @@ test "usesThumb1" {...@@ -471,6 +471,22 @@ test "usesThumb1" {
471 //etc.471 //etc.
472}472}
473473
474const use_thumb_1_pre_armv6 = usesThumb1PreArmv6(builtin.arch);
475
476fn usesThumb1PreArmv6(arch: builtin.Arch) bool {
477 return switch (arch) {
478 .thumb => |sub_arch| switch (sub_arch) {
479 .v5, .v5te, .v4t => true,
480 else => false,
481 },
482 .thumbeb => |sub_arch| switch (sub_arch) {
483 .v5, .v5te, .v4t => true,
484 else => false,
485 },
486 else => false,
487 };
488}
489
474nakedcc fn __aeabi_memcpy() noreturn {490nakedcc fn __aeabi_memcpy() noreturn {
475 @setRuntimeSafety(false);491 @setRuntimeSafety(false);
476 if (use_thumb_1) {492 if (use_thumb_1) {
...@@ -505,7 +521,16 @@ nakedcc fn __aeabi_memmove() noreturn {...@@ -505,7 +521,16 @@ nakedcc fn __aeabi_memmove() noreturn {
505521
506nakedcc fn __aeabi_memset() noreturn {522nakedcc fn __aeabi_memset() noreturn {
507 @setRuntimeSafety(false);523 @setRuntimeSafety(false);
508 if (use_thumb_1) {524 if (use_thumb_1_pre_armv6) {
525 asm volatile (
526 \\ eors r1, r2
527 \\ eors r2, r1
528 \\ eors r1, r2
529 \\ push {r7, lr}
530 \\ b memset
531 \\ pop {r7, pc}
532 );
533 } else if (use_thumb_1) {
509 asm volatile (534 asm volatile (
510 \\ mov r3, r1535 \\ mov r3, r1
511 \\ mov r1, r2536 \\ mov r1, r2
...@@ -527,7 +552,15 @@ nakedcc fn __aeabi_memset() noreturn {...@@ -527,7 +552,15 @@ nakedcc fn __aeabi_memset() noreturn {
527552
528nakedcc fn __aeabi_memclr() noreturn {553nakedcc fn __aeabi_memclr() noreturn {
529 @setRuntimeSafety(false);554 @setRuntimeSafety(false);
530 if (use_thumb_1) {555 if (use_thumb_1_pre_armv6) {
556 asm volatile (
557 \\ adds r2, r1, #0
558 \\ movs r1, #0
559 \\ push {r7, lr}
560 \\ bl memset
561 \\ pop {r7, pc}
562 );
563 } else if (use_thumb_1) {
531 asm volatile (564 asm volatile (
532 \\ mov r2, r1565 \\ mov r2, r1
533 \\ movs r1, #0566 \\ movs r1, #0
std/special/compiler_rt/comparetf2.zig+9-6
...@@ -73,12 +73,15 @@ pub extern fn __getf2(a: f128, b: f128) c_int {...@@ -73,12 +73,15 @@ pub extern fn __getf2(a: f128, b: f128) c_int {
7373
74 if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;74 if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
75 if ((aAbs | bAbs) == 0) return GE_EQUAL;75 if ((aAbs | bAbs) == 0) return GE_EQUAL;
76 return if ((aInt & bInt) >= 0) if (aInt < bInt)76 // zig fmt issue here, see https://github.com/ziglang/zig/issues/2661
77 GE_LESS77 return if ((aInt & bInt) >= 0)
78 else if (aInt == bInt)78 if (aInt < bInt)
79 GE_EQUAL79 GE_LESS
80 else80 else if (aInt == bInt)
81 GE_GREATER else if (aInt > bInt)81 GE_EQUAL
82 else
83 GE_GREATER
84 else if (aInt > bInt)
82 GE_LESS85 GE_LESS
83 else if (aInt == bInt)86 else if (aInt == bInt)
84 GE_EQUAL87 GE_EQUAL
std/special/panic.zig+3-4
...@@ -9,16 +9,15 @@ const std = @import("std");...@@ -9,16 +9,15 @@ const std = @import("std");
9pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {9pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
10 @setCold(true);10 @setCold(true);
11 switch (builtin.os) {11 switch (builtin.os) {
12 // TODO: fix panic in zen12 .freestanding => {
13 builtin.Os.freestanding, builtin.Os.zen => {
14 while (true) {}13 while (true) {}
15 },14 },
16 builtin.Os.wasi => {15 .wasi => {
17 std.debug.warn("{}", msg);16 std.debug.warn("{}", msg);
18 _ = std.os.wasi.proc_raise(std.os.wasi.SIGABRT);17 _ = std.os.wasi.proc_raise(std.os.wasi.SIGABRT);
19 unreachable;18 unreachable;
20 },19 },
21 builtin.Os.uefi => {20 .uefi => {
22 // TODO look into using the debug info and logging helpful messages21 // TODO look into using the debug info and logging helpful messages
23 std.os.abort();22 std.os.abort();
24 },23 },
std/std.zig+2
...@@ -37,6 +37,7 @@ pub const fs = @import("fs.zig");...@@ -37,6 +37,7 @@ pub const fs = @import("fs.zig");
37pub const hash = @import("hash.zig");37pub const hash = @import("hash.zig");
38pub const hash_map = @import("hash_map.zig");38pub const hash_map = @import("hash_map.zig");
39pub const heap = @import("heap.zig");39pub const heap = @import("heap.zig");
40pub const http = @import("http.zig");
40pub const io = @import("io.zig");41pub const io = @import("io.zig");
41pub const json = @import("json.zig");42pub const json = @import("json.zig");
42pub const lazyInit = @import("lazy_init.zig").lazyInit;43pub const lazyInit = @import("lazy_init.zig").lazyInit;
...@@ -89,6 +90,7 @@ test "std" {...@@ -89,6 +90,7 @@ test "std" {
89 _ = @import("fs.zig");90 _ = @import("fs.zig");
90 _ = @import("hash.zig");91 _ = @import("hash.zig");
91 _ = @import("heap.zig");92 _ = @import("heap.zig");
93 _ = @import("http.zig");
92 _ = @import("io.zig");94 _ = @import("io.zig");
93 _ = @import("json.zig");95 _ = @import("json.zig");
94 _ = @import("lazy_init.zig");96 _ = @import("lazy_init.zig");
std/zig/parse.zig+2-2
...@@ -2833,8 +2833,8 @@ fn parseIf(arena: *Allocator, it: *TokenIterator, tree: *Tree, bodyParseFn: Node...@@ -2833,8 +2833,8 @@ fn parseIf(arena: *Allocator, it: *TokenIterator, tree: *Tree, bodyParseFn: Node
28332833
2834 const else_token = eatToken(it, .Keyword_else) orelse return node;2834 const else_token = eatToken(it, .Keyword_else) orelse return node;
2835 const payload = try parsePayload(arena, it, tree);2835 const payload = try parsePayload(arena, it, tree);
2836 const else_expr = try expectNode(arena, it, tree, parseExpr, AstError{2836 const else_expr = try expectNode(arena, it, tree, bodyParseFn, AstError{
2837 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },2837 .InvalidToken = AstError.InvalidToken{ .token = it.index },
2838 });2838 });
2839 const else_node = try arena.create(Node.Else);2839 const else_node = try arena.create(Node.Else);
2840 else_node.* = Node.Else{2840 else_node.* = Node.Else{
std/zig/parser_test.zig+14-2
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1// TODO remove `use` keyword eventually1// TODO remove `use` keyword eventually: https://github.com/ziglang/zig/issues/2591
2test "zig fmt: change use to usingnamespace" {2test "zig fmt: change use to usingnamespace" {
3 try testTransform(3 try testTransform(
4 \\use @import("std");4 \\use @import("std");
...@@ -1105,7 +1105,7 @@ test "zig fmt: first line comment in struct initializer" {...@@ -1105,7 +1105,7 @@ test "zig fmt: first line comment in struct initializer" {
1105 try testCanonical(1105 try testCanonical(
1106 \\pub async fn acquire(self: *Self) HeldLock {1106 \\pub async fn acquire(self: *Self) HeldLock {
1107 \\ return HeldLock{1107 \\ return HeldLock{
1108 \\ // TODO guaranteed allocation elision1108 \\ // guaranteed allocation elision
1109 \\ .held = await (async self.lock.acquire() catch unreachable),1109 \\ .held = await (async self.lock.acquire() catch unreachable),
1110 \\ .value = &self.private_data,1110 \\ .value = &self.private_data,
1111 \\ };1111 \\ };
...@@ -2234,6 +2234,18 @@ test "zig fmt: multiline string in array" {...@@ -2234,6 +2234,18 @@ test "zig fmt: multiline string in array" {
2234 );2234 );
2235}2235}
22362236
2237test "zig fmt: if type expr" {
2238 try testCanonical(
2239 \\const mycond = true;
2240 \\pub fn foo() if (mycond) i32 else void {
2241 \\ if (mycond) {
2242 \\ return 42;
2243 \\ }
2244 \\}
2245 \\
2246 );
2247}
2248
2237const std = @import("std");2249const std = @import("std");
2238const mem = std.mem;2250const mem = std.mem;
2239const warn = std.debug.warn;2251const warn = std.debug.warn;
std/zig/render.zig+3-3
...@@ -939,10 +939,10 @@ fn renderExpression(...@@ -939,10 +939,10 @@ fn renderExpression(
939 }939 }
940940
941 switch (container_decl.init_arg_expr) {941 switch (container_decl.init_arg_expr) {
942 ast.Node.ContainerDecl.InitArg.None => {942 .None => {
943 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.Space); // union943 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.Space); // union
944 },944 },
945 ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {945 .Enum => |enum_tag_type| {
946 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union946 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
947947
948 const lparen = tree.nextToken(container_decl.kind_token);948 const lparen = tree.nextToken(container_decl.kind_token);
...@@ -962,7 +962,7 @@ fn renderExpression(...@@ -962,7 +962,7 @@ fn renderExpression(
962 try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.Space); // )962 try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.Space); // )
963 }963 }
964 },964 },
965 ast.Node.ContainerDecl.InitArg.Type => |type_expr| {965 .Type => |type_expr| {
966 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union966 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
967967
968 const lparen = tree.nextToken(container_decl.kind_token);968 const lparen = tree.nextToken(container_decl.kind_token);
test/compare_output.zig+1-1
...@@ -122,7 +122,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -122,7 +122,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
122 \\122 \\
123 \\pub fn main() void {123 \\pub fn main() void {
124 \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;124 \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream;
125 \\ stdout.print("Hello, world!\n{d4} {x3} {c}\n", u32(12), u16(0x12), u8('a')) catch unreachable;125 \\ stdout.print("Hello, world!\n{d:4} {x:3} {c}\n", u32(12), u16(0x12), u8('a')) catch unreachable;
126 \\}126 \\}
127 , "Hello, world!\n0012 012 a\n");127 , "Hello, world!\n0012 012 a\n");
128128
test/compile_errors.zig+85-41
...@@ -2,13 +2,22 @@ const tests = @import("tests.zig");...@@ -2,13 +2,22 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "slice passed as array init type with elems",
7 \\export fn entry() void {
8 \\ const x = []u8{1, 2};
9 \\}
10 ,
11 "tmp.zig:2:15: error: expected array type or [_], found slice",
12 );
13
5 cases.add(14 cases.add(
6 "slice passed as array init type",15 "slice passed as array init type",
7 \\export fn entry() void {16 \\export fn entry() void {
8 \\ const x = []u8{};17 \\ const x = []u8{};
9 \\}18 \\}
10 ,19 ,
11 "tmp.zig:2:19: error: expected array type or [_], found slice",20 "tmp.zig:2:15: error: expected array type or [_], found slice",
12 );21 );
1322
14 cases.add(23 cases.add(
...@@ -49,16 +58,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -49,16 +58,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
49 \\const Foo = struct {58 \\const Foo = struct {
50 \\ a: undefined,59 \\ a: undefined,
51 \\};60 \\};
52 \\const Bar = union {61 \\export fn entry1() void {
53 \\ a: undefined,
54 \\};
55 \\pub fn main() void {
56 \\ const foo: Foo = undefined;62 \\ const foo: Foo = undefined;
57 \\ const bar: Bar = undefined;
58 \\}63 \\}
59 ,64 ,
60 "tmp.zig:2:8: error: expected type 'type', found '(undefined)'",65 "tmp.zig:2:8: error: expected type 'type', found '(undefined)'",
61 "tmp.zig:5:8: error: expected type 'type', found '(undefined)'",
62 );66 );
6367
64 cases.add(68 cases.add(
...@@ -461,13 +465,25 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -461,13 +465,25 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
461 \\const G = packed struct {465 \\const G = packed struct {
462 \\ x: Enum,466 \\ x: Enum,
463 \\};467 \\};
464 \\export fn entry() void {468 \\export fn entry1() void {
465 \\ var a: A = undefined;469 \\ var a: A = undefined;
470 \\}
471 \\export fn entry2() void {
466 \\ var b: B = undefined;472 \\ var b: B = undefined;
473 \\}
474 \\export fn entry3() void {
467 \\ var r: C = undefined;475 \\ var r: C = undefined;
476 \\}
477 \\export fn entry4() void {
468 \\ var d: D = undefined;478 \\ var d: D = undefined;
479 \\}
480 \\export fn entry5() void {
469 \\ var e: E = undefined;481 \\ var e: E = undefined;
482 \\}
483 \\export fn entry6() void {
470 \\ var f: F = undefined;484 \\ var f: F = undefined;
485 \\}
486 \\export fn entry7() void {
471 \\ var g: G = undefined;487 \\ var g: G = undefined;
472 \\}488 \\}
473 \\const S = struct {489 \\const S = struct {
...@@ -489,7 +505,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -489,7 +505,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
489 "tmp.zig:14:5: error: non-packed, non-extern struct 'U' not allowed in packed struct; no guaranteed in-memory representation",505 "tmp.zig:14:5: error: non-packed, non-extern struct 'U' not allowed in packed struct; no guaranteed in-memory representation",
490 "tmp.zig:17:5: error: type '?anyerror' not allowed in packed struct; no guaranteed in-memory representation",506 "tmp.zig:17:5: error: type '?anyerror' not allowed in packed struct; no guaranteed in-memory representation",
491 "tmp.zig:20:5: error: type 'Enum' not allowed in packed struct; no guaranteed in-memory representation",507 "tmp.zig:20:5: error: type 'Enum' not allowed in packed struct; no guaranteed in-memory representation",
492 "tmp.zig:38:14: note: enum declaration does not specify an integer tag type",508 "tmp.zig:50:14: note: enum declaration does not specify an integer tag type",
493 );509 );
494510
495 cases.addCase(x: {511 cases.addCase(x: {
...@@ -721,7 +737,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -721,7 +737,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
721 \\ var oops = @bitCast(u7, byte);737 \\ var oops = @bitCast(u7, byte);
722 \\}738 \\}
723 ,739 ,
724 "tmp.zig:2:16: error: destination type 'u7' has 7 bits but source type 'u8' has 8 bits",740 "tmp.zig:2:25: error: destination type 'u7' has 7 bits but source type 'u8' has 8 bits",
725 );741 );
726742
727 cases.add(743 cases.add(
...@@ -1381,7 +1397,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1381,7 +1397,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1381 \\ for (xx) |f| {}1397 \\ for (xx) |f| {}
1382 \\}1398 \\}
1383 ,1399 ,
1384 "tmp.zig:7:15: error: variable of type 'Foo' must be const or comptime",1400 "tmp.zig:7:5: error: values of type 'Foo' must be comptime known, but index value is runtime known",
1385 );1401 );
13861402
1387 cases.add(1403 cases.add(
...@@ -2250,6 +2266,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2250,6 +2266,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2250 \\}2266 \\}
2251 \\2267 \\
2252 \\extern fn bar(x: *void) void { }2268 \\extern fn bar(x: *void) void { }
2269 \\export fn entry2() void {
2270 \\ bar(&{});
2271 \\}
2253 ,2272 ,
2254 "tmp.zig:1:30: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'ccc'",2273 "tmp.zig:1:30: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'ccc'",
2255 "tmp.zig:7:18: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'ccc'",2274 "tmp.zig:7:18: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'ccc'",
...@@ -2576,7 +2595,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2576,7 +2595,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2576 \\2595 \\
2577 \\fn b() void {}2596 \\fn b() void {}
2578 ,2597 ,
2579 "tmp.zig:3:5: error: unreachable code",2598 "tmp.zig:3:6: error: unreachable code",
2580 );2599 );
25812600
2582 cases.add(2601 cases.add(
...@@ -2596,7 +2615,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2596,7 +2615,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2596 \\}2615 \\}
2597 ,2616 ,
2598 "tmp.zig:3:5: error: use of undeclared identifier 'b'",2617 "tmp.zig:3:5: error: use of undeclared identifier 'b'",
2599 "tmp.zig:4:5: error: use of undeclared identifier 'c'",
2600 );2618 );
26012619
2602 cases.add(2620 cases.add(
...@@ -2662,7 +2680,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2662,7 +2680,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2662 \\ const a: noreturn = {};2680 \\ const a: noreturn = {};
2663 \\}2681 \\}
2664 ,2682 ,
2665 "tmp.zig:2:14: error: variable of type 'noreturn' not allowed",2683 "tmp.zig:2:25: error: expected type 'noreturn', found 'void'",
2666 );2684 );
26672685
2668 cases.add(2686 cases.add(
...@@ -2725,9 +2743,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2725,9 +2743,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2725 \\ var bad : bool = undefined;2743 \\ var bad : bool = undefined;
2726 \\ bad[bad] = bad[bad];2744 \\ bad[bad] = bad[bad];
2727 \\}2745 \\}
2746 \\export fn g() void {
2747 \\ var bad : bool = undefined;
2748 \\ _ = bad[bad];
2749 \\}
2728 ,2750 ,
2729 "tmp.zig:3:8: error: array access of non-array type 'bool'",2751 "tmp.zig:3:8: error: array access of non-array type 'bool'",
2730 "tmp.zig:3:19: error: array access of non-array type 'bool'",2752 "tmp.zig:7:12: error: array access of non-array type 'bool'",
2731 );2753 );
27322754
2733 cases.add(2755 cases.add(
...@@ -2737,9 +2759,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2737,9 +2759,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2737 \\ var bad = false;2759 \\ var bad = false;
2738 \\ array[bad] = array[bad];2760 \\ array[bad] = array[bad];
2739 \\}2761 \\}
2762 \\export fn g() void {
2763 \\ var array = "aoeu";
2764 \\ var bad = false;
2765 \\ _ = array[bad];
2766 \\}
2740 ,2767 ,
2741 "tmp.zig:4:11: error: expected type 'usize', found 'bool'",2768 "tmp.zig:4:11: error: expected type 'usize', found 'bool'",
2742 "tmp.zig:4:24: error: expected type 'usize', found 'bool'",2769 "tmp.zig:9:15: error: expected type 'usize', found 'bool'",
2743 );2770 );
27442771
2745 cases.add(2772 cases.add(
...@@ -2757,12 +2784,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2757,12 +2784,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2757 "missing else clause",2784 "missing else clause",
2758 \\fn f(b: bool) void {2785 \\fn f(b: bool) void {
2759 \\ const x : i32 = if (b) h: { break :h 1; };2786 \\ const x : i32 = if (b) h: { break :h 1; };
2787 \\}
2788 \\fn g(b: bool) void {
2760 \\ const y = if (b) h: { break :h i32(1); };2789 \\ const y = if (b) h: { break :h i32(1); };
2761 \\}2790 \\}
2762 \\export fn entry() void { f(true); }2791 \\export fn entry() void { f(true); g(true); }
2763 ,2792 ,
2764 "tmp.zig:2:42: error: integer value 1 cannot be implicitly casted to type 'void'",2793 "tmp.zig:2:42: error: integer value 1 cannot be implicitly casted to type 'void'",
2765 "tmp.zig:3:15: error: incompatible types: 'i32' and 'void'",2794 "tmp.zig:5:15: error: incompatible types: 'i32' and 'void'",
2766 );2795 );
27672796
2768 cases.add(2797 cases.add(
...@@ -2773,9 +2802,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2773,9 +2802,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2773 \\ a.foo = 1;2802 \\ a.foo = 1;
2774 \\ const y = a.bar;2803 \\ const y = a.bar;
2775 \\}2804 \\}
2805 \\export fn g() void {
2806 \\ var a : A = undefined;
2807 \\ const y = a.bar;
2808 \\}
2776 ,2809 ,
2777 "tmp.zig:4:6: error: no member named 'foo' in struct 'A'",2810 "tmp.zig:4:6: error: no member named 'foo' in struct 'A'",
2778 "tmp.zig:5:16: error: no member named 'bar' in struct 'A'",2811 "tmp.zig:9:16: error: no member named 'bar' in struct 'A'",
2779 );2812 );
27802813
2781 cases.add(2814 cases.add(
...@@ -2920,7 +2953,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2920,7 +2953,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2920 \\ _ = foo;2953 \\ _ = foo;
2921 \\}2954 \\}
2922 ,2955 ,
2923 "tmp.zig:1:19: error: type '[3]u16' does not support struct initialization syntax",2956 "tmp.zig:1:21: error: type '[3]u16' does not support struct initialization syntax",
2924 );2957 );
29252958
2926 cases.add(2959 cases.add(
...@@ -3239,7 +3272,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3239,7 +3272,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3239 \\3272 \\
3240 \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); }3273 \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); }
3241 ,3274 ,
3242 "tmp.zig:5:25: error: unable to evaluate constant expression",3275 "tmp.zig:5:18: error: unable to evaluate constant expression",
3243 "tmp.zig:2:12: note: called from here",3276 "tmp.zig:2:12: note: called from here",
3244 "tmp.zig:2:8: note: called from here",3277 "tmp.zig:2:8: note: called from here",
3245 );3278 );
...@@ -3856,7 +3889,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3856,7 +3889,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3856 \\ return 2;3889 \\ return 2;
3857 \\}3890 \\}
3858 ,3891 ,
3859 "tmp.zig:2:15: error: values of type 'comptime_int' must be comptime known",3892 "tmp.zig:5:17: error: cannot store runtime value in type 'comptime_int'",
3860 );3893 );
38613894
3862 cases.add(3895 cases.add(
...@@ -5108,7 +5141,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5108,7 +5141,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5108 \\ const array = [2]u8{1, 2, 3};5141 \\ const array = [2]u8{1, 2, 3};
5109 \\}5142 \\}
5110 ,5143 ,
5111 "tmp.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal",5144 "tmp.zig:2:31: error: index 2 outside array of size 2",
5112 );5145 );
51135146
5114 cases.add(5147 cases.add(
...@@ -5125,36 +5158,47 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5125,36 +5158,47 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
51255158
5126 cases.add(5159 cases.add(
5127 "non-const variables of things that require const variables",5160 "non-const variables of things that require const variables",
5128 \\const Opaque = @OpaqueType();5161 \\export fn entry1() void {
5129 \\
5130 \\export fn entry(opaque: *Opaque) void {
5131 \\ var m2 = &2;5162 \\ var m2 = &2;
5132 \\ const y: u32 = m2.*;5163 \\}
5133 \\5164 \\export fn entry2() void {
5134 \\ var a = undefined;5165 \\ var a = undefined;
5166 \\}
5167 \\export fn entry3() void {
5135 \\ var b = 1;5168 \\ var b = 1;
5169 \\}
5170 \\export fn entry4() void {
5136 \\ var c = 1.0;5171 \\ var c = 1.0;
5172 \\}
5173 \\export fn entry5() void {
5137 \\ var d = null;5174 \\ var d = null;
5175 \\}
5176 \\export fn entry6(opaque: *Opaque) void {
5138 \\ var e = opaque.*;5177 \\ var e = opaque.*;
5178 \\}
5179 \\export fn entry7() void {
5139 \\ var f = i32;5180 \\ var f = i32;
5181 \\}
5182 \\export fn entry8() void {
5140 \\ var h = (Foo {}).bar;5183 \\ var h = (Foo {}).bar;
5141 \\5184 \\}
5185 \\export fn entry9() void {
5142 \\ var z: noreturn = return;5186 \\ var z: noreturn = return;
5143 \\}5187 \\}
5144 \\5188 \\const Opaque = @OpaqueType();
5145 \\const Foo = struct {5189 \\const Foo = struct {
5146 \\ fn bar(self: *const Foo) void {}5190 \\ fn bar(self: *const Foo) void {}
5147 \\};5191 \\};
5148 ,5192 ,
5149 "tmp.zig:4:4: error: variable of type '*comptime_int' must be const or comptime",5193 "tmp.zig:2:4: error: variable of type '*comptime_int' must be const or comptime",
5150 "tmp.zig:7:4: error: variable of type '(undefined)' must be const or comptime",5194 "tmp.zig:5:4: error: variable of type '(undefined)' must be const or comptime",
5151 "tmp.zig:8:4: error: variable of type 'comptime_int' must be const or comptime",5195 "tmp.zig:8:4: error: variable of type 'comptime_int' must be const or comptime",
5152 "tmp.zig:9:4: error: variable of type 'comptime_float' must be const or comptime",5196 "tmp.zig:11:4: error: variable of type 'comptime_float' must be const or comptime",
5153 "tmp.zig:10:4: error: variable of type '(null)' must be const or comptime",5197 "tmp.zig:14:4: error: variable of type '(null)' must be const or comptime",
5154 "tmp.zig:11:4: error: variable of type 'Opaque' not allowed",5198 "tmp.zig:17:4: error: variable of type 'Opaque' not allowed",
5155 "tmp.zig:12:4: error: variable of type 'type' must be const or comptime",5199 "tmp.zig:20:4: error: variable of type 'type' must be const or comptime",
5156 "tmp.zig:13:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime",5200 "tmp.zig:23:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime",
5157 "tmp.zig:15:4: error: unreachable code",5201 "tmp.zig:26:4: error: unreachable code",
5158 );5202 );
51595203
5160 cases.add(5204 cases.add(
...@@ -5300,7 +5344,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5300,7 +5344,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5300 \\ }5344 \\ }
5301 \\}5345 \\}
5302 ,5346 ,
5303 "tmp.zig:37:16: error: cannot store runtime value in compile time variable",5347 "tmp.zig:37:29: error: cannot store runtime value in compile time variable",
5304 );5348 );
53055349
5306 cases.add(5350 cases.add(
...@@ -5924,7 +5968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5924,7 +5968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5924 \\ const foo = Foo { .Bar = x, .Baz = u8 };5968 \\ const foo = Foo { .Bar = x, .Baz = u8 };
5925 \\}5969 \\}
5926 ,5970 ,
5927 "tmp.zig:7:30: error: unable to evaluate constant expression",5971 "tmp.zig:7:23: error: unable to evaluate constant expression",
5928 );5972 );
59295973
5930 cases.add(5974 cases.add(
...@@ -5938,7 +5982,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5938,7 +5982,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5938 \\ const foo = Foo { .Bar = x };5982 \\ const foo = Foo { .Bar = x };
5939 \\}5983 \\}
5940 ,5984 ,
5941 "tmp.zig:7:30: error: unable to evaluate constant expression",5985 "tmp.zig:7:23: error: unable to evaluate constant expression",
5942 );5986 );
59435987
5944 cases.addTest(5988 cases.addTest(
test/stage1/behavior.zig+2
...@@ -69,6 +69,8 @@ comptime {...@@ -69,6 +69,8 @@ comptime {
69 _ = @import("behavior/optional.zig");69 _ = @import("behavior/optional.zig");
70 _ = @import("behavior/pointers.zig");70 _ = @import("behavior/pointers.zig");
71 _ = @import("behavior/popcount.zig");71 _ = @import("behavior/popcount.zig");
72 _ = @import("behavior/muladd.zig");
73 _ = @import("behavior/floatop.zig");
72 _ = @import("behavior/ptrcast.zig");74 _ = @import("behavior/ptrcast.zig");
73 _ = @import("behavior/pub_enum.zig");75 _ = @import("behavior/pub_enum.zig");
74 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");76 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
test/stage1/behavior/array.zig+8-2
...@@ -172,6 +172,12 @@ fn plusOne(x: u32) u32 {...@@ -172,6 +172,12 @@ fn plusOne(x: u32) u32 {
172 return x + 1;172 return x + 1;
173}173}
174174
175test "runtime initialize array elem and then implicit cast to slice" {
176 var two: i32 = 2;
177 const x: []const i32 = [_]i32{two};
178 expect(x[0] == 2);
179}
180
175test "array literal as argument to function" {181test "array literal as argument to function" {
176 const S = struct {182 const S = struct {
177 fn entry(two: i32) void {183 fn entry(two: i32) void {
...@@ -227,7 +233,7 @@ test "double nested array to const slice cast in array literal" {...@@ -227,7 +233,7 @@ test "double nested array to const slice cast in array literal" {
227233
228 const cases2 = [_][]const i32{234 const cases2 = [_][]const i32{
229 [_]i32{1},235 [_]i32{1},
230 [_]i32{ two, 3 },236 &[_]i32{ two, 3 },
231 };237 };
232 expect(cases2.len == 2);238 expect(cases2.len == 2);
233 expect(cases2[0].len == 1);239 expect(cases2[0].len == 1);
...@@ -238,7 +244,7 @@ test "double nested array to const slice cast in array literal" {...@@ -238,7 +244,7 @@ test "double nested array to const slice cast in array literal" {
238244
239 const cases3 = [_][]const []const i32{245 const cases3 = [_][]const []const i32{
240 [_][]const i32{[_]i32{1}},246 [_][]const i32{[_]i32{1}},
241 [_][]const i32{[_]i32{ two, 3 }},247 &[_][]const i32{&[_]i32{ two, 3 }},
242 [_][]const i32{248 [_][]const i32{
243 [_]i32{4},249 [_]i32{4},
244 [_]i32{ 5, 6, 7 },250 [_]i32{ 5, 6, 7 },
test/stage1/behavior/bitcast.zig+13
...@@ -112,3 +112,16 @@ test "bitcast packed struct to integer and back" {...@@ -112,3 +112,16 @@ test "bitcast packed struct to integer and back" {
112 S.doTheTest();112 S.doTheTest();
113 comptime S.doTheTest();113 comptime S.doTheTest();
114}114}
115
116test "implicit cast to error union by returning" {
117 const S = struct {
118 fn entry() void {
119 expect((func(-1) catch unreachable) == maxInt(u64));
120 }
121 pub fn func(sz: i64) anyerror!u64 {
122 return @bitCast(u64, sz);
123 }
124 };
125 S.entry();
126 comptime S.entry();
127}
test/stage1/behavior/cast.zig+37
...@@ -482,3 +482,40 @@ test "@intCast to u0 and use the result" {...@@ -482,3 +482,40 @@ test "@intCast to u0 and use the result" {
482 S.doTheTest(0, 1, 0);482 S.doTheTest(0, 1, 0);
483 comptime S.doTheTest(0, 1, 0);483 comptime S.doTheTest(0, 1, 0);
484}484}
485
486test "peer type resolution: unreachable, null, slice" {
487 const S = struct {
488 fn doTheTest(num: usize, word: []const u8) void {
489 const result = switch (num) {
490 0 => null,
491 1 => word,
492 else => unreachable,
493 };
494 expect(mem.eql(u8, result.?, "hi"));
495 }
496 };
497 S.doTheTest(1, "hi");
498}
499
500test "peer type resolution: unreachable, error set, unreachable" {
501 const Error = error {
502 FileDescriptorAlreadyPresentInSet,
503 OperationCausesCircularLoop,
504 FileDescriptorNotRegistered,
505 SystemResources,
506 UserResourceLimitReached,
507 FileDescriptorIncompatibleWithEpoll,
508 Unexpected,
509 };
510 var err = Error.SystemResources;
511 const transformed_err = switch (err) {
512 error.FileDescriptorAlreadyPresentInSet => unreachable,
513 error.OperationCausesCircularLoop => unreachable,
514 error.FileDescriptorNotRegistered => unreachable,
515 error.SystemResources => error.SystemResources,
516 error.UserResourceLimitReached => error.UserResourceLimitReached,
517 error.FileDescriptorIncompatibleWithEpoll => unreachable,
518 error.Unexpected => unreachable,
519 };
520 expect(transformed_err == error.SystemResources);
521}
test/stage1/behavior/defer.zig+17
...@@ -76,3 +76,20 @@ fn testNestedFnErrDefer() anyerror!void {...@@ -76,3 +76,20 @@ fn testNestedFnErrDefer() anyerror!void {
76 };76 };
77 return S.baz();77 return S.baz();
78}78}
79
80test "return variable while defer expression in scope to modify it" {
81 const S = struct {
82 fn doTheTest() void {
83 expect(notNull().? == 1);
84 }
85
86 fn notNull() ?u8 {
87 var res: ?u8 = 1;
88 defer res = null;
89 return res;
90 }
91 };
92
93 S.doTheTest();
94 comptime S.doTheTest();
95}
test/stage1/behavior/error.zig+40
...@@ -335,3 +335,43 @@ test "debug info for optional error set" {...@@ -335,3 +335,43 @@ test "debug info for optional error set" {
335 const SomeError = error{Hello};335 const SomeError = error{Hello};
336 var a_local_variable: ?SomeError = null;336 var a_local_variable: ?SomeError = null;
337}337}
338
339test "nested catch" {
340 const S = struct {
341 fn entry() void {
342 expectError(error.Bad, func());
343 }
344 fn fail() anyerror!Foo {
345 return error.Wrong;
346 }
347 fn func() anyerror!Foo {
348 const x = fail() catch
349 fail() catch
350 return error.Bad;
351 unreachable;
352 }
353 const Foo = struct {
354 field: i32,
355 };
356 };
357 S.entry();
358 comptime S.entry();
359}
360
361test "implicit cast to optional to error union to return result loc" {
362 const S = struct {
363 fn entry() void {
364 if (func(undefined)) |opt| {
365 expect(opt != null);
366 } else |_| @panic("expected non error");
367 }
368 fn func(f: *Foo) anyerror!?*Foo {
369 return f;
370 }
371 const Foo = struct {
372 field: i32,
373 };
374 };
375 S.entry();
376 //comptime S.entry(); TODO
377}
test/stage1/behavior/eval.zig+12-2
...@@ -190,6 +190,17 @@ fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {...@@ -190,6 +190,17 @@ fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
190 }190 }
191}191}
192192
193test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
194 var runtime = [1]i32{3};
195 comptime var i: usize = 0;
196 inline while (i < 2) : (i += 1) {
197 const result = if (i == 0) [1]i32{2} else runtime;
198 }
199 comptime {
200 expect(i == 2);
201 }
202}
203
193fn max(comptime T: type, a: T, b: T) T {204fn max(comptime T: type, a: T, b: T) T {
194 if (T == bool) {205 if (T == bool) {
195 return a or b;206 return a or b;
...@@ -756,8 +767,7 @@ test "comptime bitwise operators" {...@@ -756,8 +767,7 @@ test "comptime bitwise operators" {
756test "*align(1) u16 is the same as *align(1:0:2) u16" {767test "*align(1) u16 is the same as *align(1:0:2) u16" {
757 comptime {768 comptime {
758 expect(*align(1:0:2) u16 == *align(1) u16);769 expect(*align(1:0:2) u16 == *align(1) u16);
759 // TODO add parsing support for this syntax770 expect(*align(:0:2) u16 == *u16);
760 //expect(*align(:0:2) u16 == *u16);
761 }771 }
762}772}
763773
test/stage1/behavior/floatop.zig created+243
...@@ -0,0 +1,243 @@
1const expect = @import("std").testing.expect;
2const pi = @import("std").math.pi;
3const e = @import("std").math.e;
4
5test "@sqrt" {
6 comptime testSqrt();
7 testSqrt();
8}
9
10fn testSqrt() void {
11 {
12 var a: f16 = 4;
13 expect(@sqrt(f16, a) == 2);
14 }
15 {
16 var a: f32 = 9;
17 expect(@sqrt(f32, a) == 3);
18 }
19 {
20 var a: f64 = 25;
21 expect(@sqrt(f64, a) == 5);
22 }
23 {
24 const a: comptime_float = 25.0;
25 expect(@sqrt(comptime_float, a) == 5.0);
26 }
27 // Waiting on a c.zig implementation
28 //{
29 // var a: f128 = 49;
30 // expect(@sqrt(f128, a) == 7);
31 //}
32}
33
34test "@sin" {
35 comptime testSin();
36 testSin();
37}
38
39fn testSin() void {
40 // TODO - this is actually useful and should be implemented
41 // (all the trig functions for f16)
42 // but will probably wait till self-hosted
43 //{
44 // var a: f16 = pi;
45 // expect(@sin(f16, a/2) == 1);
46 //}
47 {
48 var a: f32 = 0;
49 expect(@sin(f32, a) == 0);
50 }
51 {
52 var a: f64 = 0;
53 expect(@sin(f64, a) == 0);
54 }
55 // TODO
56 //{
57 // var a: f16 = pi;
58 // expect(@sqrt(f128, a/2) == 1);
59 //}
60}
61
62test "@cos" {
63 comptime testCos();
64 testCos();
65}
66
67fn testCos() void {
68 {
69 var a: f32 = 0;
70 expect(@cos(f32, a) == 1);
71 }
72 {
73 var a: f64 = 0;
74 expect(@cos(f64, a) == 1);
75 }
76}
77
78test "@exp" {
79 comptime testExp();
80 testExp();
81}
82
83fn testExp() void {
84 {
85 var a: f32 = 0;
86 expect(@exp(f32, a) == 1);
87 }
88 {
89 var a: f64 = 0;
90 expect(@exp(f64, a) == 1);
91 }
92}
93
94test "@exp2" {
95 comptime testExp2();
96 testExp2();
97}
98
99fn testExp2() void {
100 {
101 var a: f32 = 2;
102 expect(@exp2(f32, a) == 4);
103 }
104 {
105 var a: f64 = 2;
106 expect(@exp2(f64, a) == 4);
107 }
108}
109
110test "@ln" {
111 // Old musl (and glibc?), and our current math.ln implementation do not return 1
112 // so also accept those values.
113 comptime testLn();
114 testLn();
115}
116
117fn testLn() void {
118 {
119 var a: f32 = e;
120 expect(@ln(f32, a) == 1 or @ln(f32, a) == @bitCast(f32, u32(0x3f7fffff)));
121 }
122 {
123 var a: f64 = e;
124 expect(@ln(f64, a) == 1 or @ln(f64, a) == @bitCast(f64, u64(0x3ff0000000000000)));
125 }
126}
127
128test "@log2" {
129 comptime testLog2();
130 testLog2();
131}
132
133fn testLog2() void {
134 {
135 var a: f32 = 4;
136 expect(@log2(f32, a) == 2);
137 }
138 {
139 var a: f64 = 4;
140 expect(@log2(f64, a) == 2);
141 }
142}
143
144test "@log10" {
145 comptime testLog10();
146 testLog10();
147}
148
149fn testLog10() void {
150 {
151 var a: f32 = 100;
152 expect(@log10(f32, a) == 2);
153 }
154 {
155 var a: f64 = 1000;
156 expect(@log10(f64, a) == 3);
157 }
158}
159
160test "@fabs" {
161 comptime testFabs();
162 testFabs();
163}
164
165fn testFabs() void {
166 {
167 var a: f32 = -2.5;
168 var b: f32 = 2.5;
169 expect(@fabs(f32, a) == 2.5);
170 expect(@fabs(f32, b) == 2.5);
171 }
172 {
173 var a: f64 = -2.5;
174 var b: f64 = 2.5;
175 expect(@fabs(f64, a) == 2.5);
176 expect(@fabs(f64, b) == 2.5);
177 }
178}
179
180test "@floor" {
181 comptime testFloor();
182 testFloor();
183}
184
185fn testFloor() void {
186 {
187 var a: f32 = 2.1;
188 expect(@floor(f32, a) == 2);
189 }
190 {
191 var a: f64 = 3.5;
192 expect(@floor(f64, a) == 3);
193 }
194}
195
196test "@ceil" {
197 comptime testCeil();
198 testCeil();
199}
200
201fn testCeil() void {
202 {
203 var a: f32 = 2.1;
204 expect(@ceil(f32, a) == 3);
205 }
206 {
207 var a: f64 = 3.5;
208 expect(@ceil(f64, a) == 4);
209 }
210}
211
212test "@trunc" {
213 comptime testTrunc();
214 testTrunc();
215}
216
217fn testTrunc() void {
218 {
219 var a: f32 = 2.1;
220 expect(@trunc(f32, a) == 2);
221 }
222 {
223 var a: f64 = -3.5;
224 expect(@trunc(f64, a) == -3);
225 }
226}
227
228// This is waiting on library support for the Windows build (not sure why the other's don't need it)
229//test "@nearbyInt" {
230// comptime testNearbyInt();
231// testNearbyInt();
232//}
233
234//fn testNearbyInt() void {
235// {
236// var a: f32 = 2.1;
237// expect(@nearbyInt(f32, a) == 2);
238// }
239// {
240// var a: f64 = -3.75;
241// expect(@nearbyInt(f64, a) == -4);
242// }
243//}
test/stage1/behavior/fn.zig+23
...@@ -205,3 +205,26 @@ test "extern struct with stdcallcc fn pointer" {...@@ -205,3 +205,26 @@ test "extern struct with stdcallcc fn pointer" {
205 s.ptr = S.foo;205 s.ptr = S.foo;
206 expect(s.ptr() == 1234);206 expect(s.ptr() == 1234);
207}207}
208
209test "implicit cast fn call result to optional in field result" {
210 const S = struct {
211 fn entry() void {
212 var x = Foo{
213 .field = optionalPtr(),
214 };
215 expect(x.field.?.* == 999);
216 }
217
218 const glob: i32 = 999;
219
220 fn optionalPtr() *const i32 {
221 return &glob;
222 }
223
224 const Foo = struct {
225 field: ?*const i32,
226 };
227 };
228 S.entry();
229 comptime S.entry();
230}
test/stage1/behavior/for.zig+32
...@@ -110,3 +110,35 @@ fn testContinueOuter() void {...@@ -110,3 +110,35 @@ fn testContinueOuter() void {
110 }110 }
111 expect(counter == array.len);111 expect(counter == array.len);
112}112}
113
114test "2 break statements and an else" {
115 const S = struct {
116 fn entry(t: bool, f: bool) void {
117 var buf: [10]u8 = undefined;
118 var ok = false;
119 ok = for (buf) |item| {
120 if (f) break false;
121 if (t) break true;
122 } else false;
123 expect(ok);
124 }
125 };
126 S.entry(true, false);
127 comptime S.entry(true, false);
128}
129
130test "for with null and T peer types and inferred result location type" {
131 const S = struct {
132 fn doTheTest(slice: []const u8) void {
133 if (for (slice) |item| {
134 if (item == 10) {
135 break item;
136 }
137 } else null) |v| {
138 @panic("fail");
139 }
140 }
141 };
142 S.doTheTest([_]u8{ 1, 2 });
143 comptime S.doTheTest([_]u8{ 1, 2 });
144}
test/stage1/behavior/if.zig+11
...@@ -52,3 +52,14 @@ test "unwrap mutable global var" {...@@ -52,3 +52,14 @@ test "unwrap mutable global var" {
52 expect(e == error.SomeError);52 expect(e == error.SomeError);
53 }53 }
54}54}
55
56test "labeled break inside comptime if inside runtime if" {
57 var answer: i32 = 0;
58 var c = true;
59 if (c) {
60 answer = if (true) blk: {
61 break :blk i32(42);
62 };
63 }
64 expect(answer == 42);
65}
test/stage1/behavior/misc.zig+8
...@@ -698,3 +698,11 @@ test "unicode escape in character literal" {...@@ -698,3 +698,11 @@ test "unicode escape in character literal" {
698 var a: u24 = '\U01f4a9';698 var a: u24 = '\U01f4a9';
699 expect(a == 128169);699 expect(a == 128169);
700}700}
701
702test "result location zero sized array inside struct field implicit cast to slice" {
703 const E = struct {
704 entries: []u32,
705 };
706 var foo = E{ .entries = [_]u32{} };
707 expect(foo.entries.len == 0);
708}
test/stage1/behavior/muladd.zig created+34
...@@ -0,0 +1,34 @@
1const expect = @import("std").testing.expect;
2
3test "@mulAdd" {
4 comptime testMulAdd();
5 testMulAdd();
6}
7
8fn testMulAdd() void {
9 {
10 var a: f16 = 5.5;
11 var b: f16 = 2.5;
12 var c: f16 = 6.25;
13 expect(@mulAdd(f16, a, b, c) == 20);
14 }
15 {
16 var a: f32 = 5.5;
17 var b: f32 = 2.5;
18 var c: f32 = 6.25;
19 expect(@mulAdd(f32, a, b, c) == 20);
20 }
21 {
22 var a: f64 = 5.5;
23 var b: f64 = 2.5;
24 var c: f64 = 6.25;
25 expect(@mulAdd(f64, a, b, c) == 20);
26 }
27 // Awaits implementation in libm.zig
28 //{
29 // var a: f16 = 5.5;
30 // var b: f128 = 2.5;
31 // var c: f128 = 6.25;
32 // expect(@mulAdd(f128, a, b, c) == 20);
33 //}
34}
\ No newline at end of file
test/stage1/behavior/optional.zig+23-2
...@@ -76,6 +76,27 @@ test "unwrap function call with optional pointer return value" {...@@ -76,6 +76,27 @@ test "unwrap function call with optional pointer return value" {
76 }76 }
77 };77 };
78 S.entry();78 S.entry();
79 // TODO https://github.com/ziglang/zig/issues/190179 comptime S.entry();
80 //comptime S.entry();80}
81
82test "nested orelse" {
83 const S = struct {
84 fn entry() void {
85 expect(func() == null);
86 }
87 fn maybe() ?Foo {
88 return null;
89 }
90 fn func() ?Foo {
91 const x = maybe() orelse
92 maybe() orelse
93 return null;
94 unreachable;
95 }
96 const Foo = struct {
97 field: i32,
98 };
99 };
100 S.entry();
101 comptime S.entry();
81}102}
test/stage1/behavior/struct.zig+21
...@@ -578,3 +578,24 @@ test "default struct initialization fields" {...@@ -578,3 +578,24 @@ test "default struct initialization fields" {
578 };578 };
579 expectEqual(1239, x.a + x.b);579 expectEqual(1239, x.a + x.b);
580}580}
581
582test "extern fn returns struct by value" {
583 const S = struct {
584 fn entry() void {
585 var x = makeBar(10);
586 expectEqual(i32(10), x.handle);
587 }
588
589 const ExternBar = extern struct {
590 handle: i32,
591 };
592
593 extern fn makeBar(t: i32) ExternBar {
594 return ExternBar{
595 .handle = t,
596 };
597 }
598 };
599 S.entry();
600 comptime S.entry();
601}
test/stage1/behavior/switch.zig+31
...@@ -360,3 +360,34 @@ test "switch prongs with error set cases make a new error set type for capture v...@@ -360,3 +360,34 @@ test "switch prongs with error set cases make a new error set type for capture v
360 S.doTheTest();360 S.doTheTest();
361 comptime S.doTheTest();361 comptime S.doTheTest();
362}362}
363
364test "return result loc and then switch with range implicit casted to error union" {
365 const S = struct {
366 fn doTheTest() void {
367 expect((func(0xb) catch unreachable) == 0xb);
368 }
369 fn func(d: u8) anyerror!u8 {
370 return switch (d) {
371 0xa...0xf => d,
372 else => unreachable,
373 };
374 }
375 };
376 S.doTheTest();
377 comptime S.doTheTest();
378}
379
380test "switch with null and T peer types and inferred result location type" {
381 const S = struct {
382 fn doTheTest(c: u8) void {
383 if (switch (c) {
384 0 => true,
385 else => null,
386 }) |v| {
387 @panic("fail");
388 }
389 }
390 };
391 S.doTheTest(1);
392 comptime S.doTheTest(1);
393}
test/stage1/behavior/union.zig+20
...@@ -402,3 +402,23 @@ test "comptime union field value equality" {...@@ -402,3 +402,23 @@ test "comptime union field value equality" {
402 expect(a0 != a1);402 expect(a0 != a1);
403 expect(b0 != b1);403 expect(b0 != b1);
404}404}
405
406test "return union init with void payload" {
407 const S = struct {
408 fn entry() void {
409 expect(func().state == State.one);
410 }
411 const Outer = union(enum) {
412 state: State,
413 };
414 const State = union(enum) {
415 one: void,
416 two: u32,
417 };
418 fn func() Outer {
419 return Outer{ .state = State{ .one = {} }};
420 }
421 };
422 S.entry();
423 comptime S.entry();
424}
test/stage1/behavior/vector.zig+13
...@@ -61,3 +61,16 @@ test "vector bit operators" {...@@ -61,3 +61,16 @@ test "vector bit operators" {
61 S.doTheTest();61 S.doTheTest();
62 comptime S.doTheTest();62 comptime S.doTheTest();
63}63}
64
65test "implicit cast vector to array" {
66 const S = struct {
67 fn doTheTest() void {
68 var a: @Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
69 var result_array: [4]i32 = a;
70 result_array = a;
71 expect(mem.eql(i32, result_array, [4]i32{ 1, 2, 3, 4 }));
72 }
73 };
74 S.doTheTest();
75 comptime S.doTheTest();
76}
test/stage1/behavior/while.zig+45
...@@ -226,3 +226,48 @@ fn returnFalse() bool {...@@ -226,3 +226,48 @@ fn returnFalse() bool {
226fn returnTrue() bool {226fn returnTrue() bool {
227 return true;227 return true;
228}228}
229
230test "while bool 2 break statements and an else" {
231 const S = struct {
232 fn entry(t: bool, f: bool) void {
233 var ok = false;
234 ok = while (t) {
235 if (f) break false;
236 if (t) break true;
237 } else false;
238 expect(ok);
239 }
240 };
241 S.entry(true, false);
242 comptime S.entry(true, false);
243}
244
245test "while optional 2 break statements and an else" {
246 const S = struct {
247 fn entry(opt_t: ?bool, f: bool) void {
248 var ok = false;
249 ok = while (opt_t) |t| {
250 if (f) break false;
251 if (t) break true;
252 } else false;
253 expect(ok);
254 }
255 };
256 S.entry(true, false);
257 comptime S.entry(true, false);
258}
259
260test "while error 2 break statements and an else" {
261 const S = struct {
262 fn entry(opt_t: anyerror!bool, f: bool) void {
263 var ok = false;
264 ok = while (opt_t) |t| {
265 if (f) break false;
266 if (t) break true;
267 } else |_| false;
268 expect(ok);
269 }
270 };
271 S.entry(true, false);
272 comptime S.entry(true, false);
273}
test/tests.zig+13-15
...@@ -811,23 +811,21 @@ pub const CompileErrorContext = struct {...@@ -811,23 +811,21 @@ pub const CompileErrorContext = struct {
811 pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {811 pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
812 const b = self.b;812 const b = self.b;
813813
814 for (self.modes) |mode| {814 const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {}", case.name) catch unreachable;
815 const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})", case.name, @tagName(mode)) catch unreachable;815 if (self.test_filter) |filter| {
816 if (self.test_filter) |filter| {816 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
817 if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;817 }
818 }
819818
820 const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode);819 const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, .Debug);
821 self.step.dependOn(&compile_and_cmp_errors.step);820 self.step.dependOn(&compile_and_cmp_errors.step);
822821
823 for (case.sources.toSliceConst()) |src_file| {822 for (case.sources.toSliceConst()) |src_file| {
824 const expanded_src_path = fs.path.join(823 const expanded_src_path = fs.path.join(
825 b.allocator,824 b.allocator,
826 [_][]const u8{ b.cache_root, src_file.filename },825 [_][]const u8{ b.cache_root, src_file.filename },
827 ) catch unreachable;826 ) catch unreachable;
828 const write_src = b.addWriteFile(expanded_src_path, src_file.source);827 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
829 compile_and_cmp_errors.step.dependOn(&write_src.step);828 compile_and_cmp_errors.step.dependOn(&write_src.step);
830 }
831 }829 }
832 }830 }
833};831};