authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-03 00:42:00-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-03 00:42:00-05:00
log1d77f8db289e6eefce827fe37d27e72b68362943
tree62bcadb5abcf45076583c362cb68e254067020f0
parent6bfaf262d5a1d18482a813c7022ffb03a18f52a8
parent0ea50b3157f00ab56b2752dfa8c70edb4bce2af7

Merge branch 'master' into llvm6


14 files changed, 647 insertions(+), 1385 deletions(-)

CMakeLists.txt+1
...@@ -605,6 +605,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/index.zig" DESTINATION "${ZIG_...@@ -605,6 +605,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/index.zig" DESTINATION "${ZIG_
605install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/util.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")605install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/util.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")
606install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")606install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
607install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")607install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
608install(FILES "${CMAKE_SOURCE_DIR}/std/unicode.zig" DESTINATION "${ZIG_STD_DEST}")
608install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")609install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")
609install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap_lib.zig" DESTINATION "${ZIG_STD_DEST}/special")610install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap_lib.zig" DESTINATION "${ZIG_STD_DEST}/special")
610install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_file_template.zig" DESTINATION "${ZIG_STD_DEST}/special")611install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_file_template.zig" DESTINATION "${ZIG_STD_DEST}/special")
build.zig+1
...@@ -276,6 +276,7 @@ pub fn installStdLib(b: &Builder) {...@@ -276,6 +276,7 @@ pub fn installStdLib(b: &Builder) {
276 "os/windows/util.zig",276 "os/windows/util.zig",
277 "rand.zig",277 "rand.zig",
278 "sort.zig",278 "sort.zig",
279 "unicode.zig",
279 "special/bootstrap.zig",280 "special/bootstrap.zig",
280 "special/bootstrap_lib.zig",281 "special/bootstrap_lib.zig",
281 "special/build_file_template.zig",282 "special/build_file_template.zig",
doc/langref.html.in+1-1
...@@ -298,7 +298,7 @@ pub fn main() -&gt; %void {...@@ -298,7 +298,7 @@ pub fn main() -&gt; %void {
298 <li>Ascii control characters, except for U+000a (LF): U+0000 - U+0009, U+000b - U+0001f, U+007f. (Note that Windows line endings (CRLF) are not allowed, and hard tabs are not allowed.)</li>298 <li>Ascii control characters, except for U+000a (LF): U+0000 - U+0009, U+000b - U+0001f, U+007f. (Note that Windows line endings (CRLF) are not allowed, and hard tabs are not allowed.)</li>
299 <li>Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li>299 <li>Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li>
300 </ul>300 </ul>
301 <p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code. A non-empty zig source must end with the line terminator character.</p>301 <p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possbly the last line of the file).</p>
302 <p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/zig-lang/zig/issues/663">issue #663</a></p>302 <p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/zig-lang/zig/issues/663">issue #663</a></p>
303 <h2 id="values">Values</h2>303 <h2 id="values">Values</h2>
304 <pre><code class="zig">const warn = @import("std").debug.warn;304 <pre><code class="zig">const warn = @import("std").debug.warn;
src-self-hosted/module.zig+4-1
...@@ -213,11 +213,14 @@ pub const Module = struct {...@@ -213,11 +213,14 @@ pub const Module = struct {
213 };213 };
214 %defer self.allocator.free(root_src_real_path);214 %defer self.allocator.free(root_src_real_path);
215215
216 const source_code = io.readFileAlloc(root_src_real_path, self.allocator) %% |err| {216 const source_code = io.readFileAllocExtra(root_src_real_path, self.allocator, 3) %% |err| {
217 %return printError("unable to open '{}': {}", root_src_real_path, err);217 %return printError("unable to open '{}': {}", root_src_real_path, err);
218 return err;218 return err;
219 };219 };
220 %defer self.allocator.free(source_code);220 %defer self.allocator.free(source_code);
221 source_code[source_code.len - 3] = '\n';
222 source_code[source_code.len - 2] = '\n';
223 source_code[source_code.len - 1] = '\n';
221224
222 warn("====input:====\n");225 warn("====input:====\n");
223226
src-self-hosted/parser.zig+7-1
...@@ -1086,7 +1086,13 @@ pub const Parser = struct {...@@ -1086,7 +1086,13 @@ pub const Parser = struct {
1086var fixed_buffer_mem: [100 * 1024]u8 = undefined;1086var fixed_buffer_mem: [100 * 1024]u8 = undefined;
10871087
1088fn testParse(source: []const u8, allocator: &mem.Allocator) -> %[]u8 {1088fn testParse(source: []const u8, allocator: &mem.Allocator) -> %[]u8 {
1089 var tokenizer = Tokenizer.init(source);1089 var padded_source: [0x100]u8 = undefined;
1090 std.mem.copy(u8, padded_source[0..source.len], source);
1091 padded_source[source.len + 0] = '\n';
1092 padded_source[source.len + 1] = '\n';
1093 padded_source[source.len + 2] = '\n';
1094
1095 var tokenizer = Tokenizer.init(padded_source[0..source.len + 3]);
1090 var parser = Parser.init(&tokenizer, allocator, "(memory buffer)");1096 var parser = Parser.init(&tokenizer, allocator, "(memory buffer)");
1091 defer parser.deinit();1097 defer parser.deinit();
10921098
src-self-hosted/tokenizer.zig+66-138
...@@ -70,7 +70,6 @@ pub const Token = struct {...@@ -70,7 +70,6 @@ pub const Token = struct {
70 Identifier,70 Identifier,
71 StringLiteral: StrLitKind,71 StringLiteral: StrLitKind,
72 Eof,72 Eof,
73 NoEolAtEof,
74 Builtin,73 Builtin,
75 Bang,74 Bang,
76 Equal,75 Equal,
...@@ -140,7 +139,6 @@ pub const Token = struct {...@@ -140,7 +139,6 @@ pub const Token = struct {
140pub const Tokenizer = struct {139pub const Tokenizer = struct {
141 buffer: []const u8,140 buffer: []const u8,
142 index: usize,141 index: usize,
143 actual_file_end: usize,
144 pending_invalid_token: ?Token,142 pending_invalid_token: ?Token,
145143
146 pub const Location = struct {144 pub const Location = struct {
...@@ -179,17 +177,15 @@ pub const Tokenizer = struct {...@@ -179,17 +177,15 @@ pub const Tokenizer = struct {
179 std.debug.warn("{} \"{}\"\n", @tagName(token.id), self.buffer[token.start..token.end]);177 std.debug.warn("{} \"{}\"\n", @tagName(token.id), self.buffer[token.start..token.end]);
180 }178 }
181179
180 /// buffer must end with "\n\n\n". This is so that attempting to decode
181 /// a the 3 trailing bytes of a 4-byte utf8 sequence is never a buffer overflow.
182 pub fn init(buffer: []const u8) -> Tokenizer {182 pub fn init(buffer: []const u8) -> Tokenizer {
183 var source_len = buffer.len;183 std.debug.assert(buffer[buffer.len - 1] == '\n');
184 while (source_len > 0) : (source_len -= 1) {184 std.debug.assert(buffer[buffer.len - 2] == '\n');
185 if (buffer[source_len - 1] == '\n') break;185 std.debug.assert(buffer[buffer.len - 3] == '\n');
186 // last line is incomplete, so skip it, and give an error when we get there.
187 }
188
189 return Tokenizer {186 return Tokenizer {
190 .buffer = buffer[0..source_len],187 .buffer = buffer,
191 .index = 0,188 .index = 0,
192 .actual_file_end = buffer.len,
193 .pending_invalid_token = null,189 .pending_invalid_token = null,
194 };190 };
195 }191 }
...@@ -512,17 +508,14 @@ pub const Tokenizer = struct {...@@ -512,17 +508,14 @@ pub const Tokenizer = struct {
512 }508 }
513 }509 }
514 result.end = self.index;510 result.end = self.index;
511
515 if (result.id == Token.Id.Eof) {512 if (result.id == Token.Id.Eof) {
516 if (self.pending_invalid_token) |token| {513 if (self.pending_invalid_token) |token| {
517 self.pending_invalid_token = null;514 self.pending_invalid_token = null;
518 return token;515 return token;
519 }516 }
520 if (self.actual_file_end != self.buffer.len) {
521 // instead of an Eof, give an error token
522 result.id = Token.Id.NoEolAtEof;
523 result.end = self.actual_file_end;
524 }
525 }517 }
518
526 return result;519 return result;
527 }520 }
528521
...@@ -553,161 +546,96 @@ pub const Tokenizer = struct {...@@ -553,161 +546,96 @@ pub const Tokenizer = struct {
553 return 0;546 return 0;
554 } else {547 } else {
555 // check utf8-encoded character.548 // check utf8-encoded character.
556 // remember that the last byte in the buffer is guaranteed to be '\n',549 const length = std.unicode.utf8ByteSequenceLength(c0) %% return 1;
557 // which means we really don't need to do bounds checks here,550 // the last 3 bytes in the buffer are guaranteed to be '\n',
558 // as long as we check one byte at a time for being a continuation byte.551 // which means we don't need to do any bounds checking here.
559 var value: u32 = undefined;552 const bytes = self.buffer[self.index..self.index + length];
560 var length: u3 = undefined;553 switch (length) {
561 if (c0 & 0b11100000 == 0b11000000) {value = c0 & 0b00011111; length = 2;}554 2 => {
562 else if (c0 & 0b11110000 == 0b11100000) {value = c0 & 0b00001111; length = 3;}555 const value = std.unicode.utf8Decode2(bytes) %% return length;
563 else if (c0 & 0b11111000 == 0b11110000) {value = c0 & 0b00000111; length = 4;}556 if (value == 0x85) return length; // U+0085 (NEL)
564 else return 1; // unexpected continuation or too many leading 1's557 },
565558 3 => {
566 const c1 = self.buffer[self.index + 1];559 const value = std.unicode.utf8Decode3(bytes) %% return length;
567 if (c1 & 0b11000000 != 0b10000000) return 1; // expected continuation560 if (value == 0x2028) return length; // U+2028 (LS)
568 value <<= 6;561 if (value == 0x2029) return length; // U+2029 (PS)
569 value |= c1 & 0b00111111;562 },
570 if (length == 2) {563 4 => {
571 if (value < 0x80) return length; // overlong564 _ = std.unicode.utf8Decode4(bytes) %% return length;
572 if (value == 0x85) return length; // U+0085 (NEL)565 },
573 self.index += length - 1;566 else => unreachable,
574 return 0;
575 }
576 const c2 = self.buffer[self.index + 2];
577 if (c2 & 0b11000000 != 0b10000000) return 2; // expected continuation
578 value <<= 6;
579 value |= c2 & 0b00111111;
580 if (length == 3) {
581 if (value < 0x800) return length; // overlong
582 if (value == 0x2028) return length; // U+2028 (LS)
583 if (value == 0x2029) return length; // U+2029 (PS)
584 if (0xd800 <= value and value <= 0xdfff) return length; // surrogate halves not allowed in utf8
585 self.index += length - 1;
586 return 0;
587 }
588 const c3 = self.buffer[self.index + 3];
589 if (c3 & 0b11000000 != 0b10000000) return 3; // expected continuation
590 value <<= 6;
591 value |= c3 & 0b00111111;
592 if (length == 4) {
593 if (value < 0x10000) return length; // overlong
594 if (value > 0x10FFFF) return length; // out of bounds
595 self.index += length - 1;
596 return 0;
597 }567 }
598 unreachable;568 self.index += length - 1;
569 return 0;
599 }570 }
600 }571 }
601};572};
602573
603574
604575
605test "tokenizer - source must end with eol" {576test "tokenizer" {
606 testTokenizeWithEol("", []Token.Id {577 testTokenize("test", []Token.Id {
607 }, true);
608 testTokenizeWithEol("no newline", []Token.Id {
609 }, false);
610 testTokenizeWithEol("test\n", []Token.Id {
611 Token.Id.Keyword_test,
612 }, true);
613 testTokenizeWithEol("test\nno newline", []Token.Id {
614 Token.Id.Keyword_test,578 Token.Id.Keyword_test,
615 }, false);579 });
616}580}
617581
618test "tokenizer - invalid token characters" {582test "tokenizer - invalid token characters" {
619 testTokenize("#\n", []Token.Id{Token.Id.Invalid});583 testTokenize("#", []Token.Id{Token.Id.Invalid});
620 testTokenize("`\n", []Token.Id{Token.Id.Invalid});584 testTokenize("`", []Token.Id{Token.Id.Invalid});
621}585}
622586
623test "tokenizer - invalid literal/comment characters" {587test "tokenizer - invalid literal/comment characters" {
624 testTokenize("\"\x00\"\n", []Token.Id {588 testTokenize("\"\x00\"", []Token.Id {
625 Token.Id { .StringLiteral = Token.StrLitKind.Normal },589 Token.Id { .StringLiteral = Token.StrLitKind.Normal },
626 Token.Id.Invalid,590 Token.Id.Invalid,
627 });591 });
628 testTokenize("//\x00\n", []Token.Id {592 testTokenize("//\x00", []Token.Id {
629 Token.Id.Invalid,593 Token.Id.Invalid,
630 });594 });
631 testTokenize("//\x1f\n", []Token.Id {595 testTokenize("//\x1f", []Token.Id {
632 Token.Id.Invalid,596 Token.Id.Invalid,
633 });597 });
634 testTokenize("//\x7f\n", []Token.Id {598 testTokenize("//\x7f", []Token.Id {
635 Token.Id.Invalid,599 Token.Id.Invalid,
636 });600 });
637}601}
638602
639test "tokenizer - valid unicode" {603test "tokenizer - utf8" {
640 testTokenize("//\xc2\x80\n", []Token.Id{});604 testTokenize("//\xc2\x80", []Token.Id{});
641 testTokenize("//\xdf\xbf\n", []Token.Id{});605 testTokenize("//\xf4\x8f\xbf\xbf", []Token.Id{});
642 testTokenize("//\xe0\xa0\x80\n", []Token.Id{});
643 testTokenize("//\xe1\x80\x80\n", []Token.Id{});
644 testTokenize("//\xef\xbf\xbf\n", []Token.Id{});
645 testTokenize("//\xf0\x90\x80\x80\n", []Token.Id{});
646 testTokenize("//\xf1\x80\x80\x80\n", []Token.Id{});
647 testTokenize("//\xf3\xbf\xbf\xbf\n", []Token.Id{});
648 testTokenize("//\xf4\x8f\xbf\xbf\n", []Token.Id{});
649}
650
651test "tokenizer - invalid unicode continuation bytes" {
652 // unexpected continuation
653 testTokenize("//\x80\n", []Token.Id{Token.Id.Invalid});
654 testTokenize("//\xbf\n", []Token.Id{Token.Id.Invalid});
655 // too many leading 1's
656 testTokenize("//\xf8\n", []Token.Id{Token.Id.Invalid});
657 testTokenize("//\xff\n", []Token.Id{Token.Id.Invalid});
658 // expected continuation for 2 byte sequences
659 testTokenize("//\xc2\x00\n", []Token.Id{Token.Id.Invalid});
660 testTokenize("//\xc2\xc0\n", []Token.Id{Token.Id.Invalid});
661 // expected continuation for 3 byte sequences
662 testTokenize("//\xe0\x00\n", []Token.Id{Token.Id.Invalid});
663 testTokenize("//\xe0\xc0\n", []Token.Id{Token.Id.Invalid});
664 testTokenize("//\xe0\xa0\n", []Token.Id{Token.Id.Invalid});
665 testTokenize("//\xe0\xa0\x00\n", []Token.Id{Token.Id.Invalid});
666 testTokenize("//\xe0\xa0\xc0\n", []Token.Id{Token.Id.Invalid});
667 // expected continuation for 4 byte sequences
668 testTokenize("//\xf0\x00\n", []Token.Id{Token.Id.Invalid});
669 testTokenize("//\xf0\xc0\n", []Token.Id{Token.Id.Invalid});
670 testTokenize("//\xf0\x90\x00\n", []Token.Id{Token.Id.Invalid});
671 testTokenize("//\xf0\x90\xc0\n", []Token.Id{Token.Id.Invalid});
672 testTokenize("//\xf0\x90\x80\x00\n", []Token.Id{Token.Id.Invalid});
673 testTokenize("//\xf0\x90\x80\xc0\n", []Token.Id{Token.Id.Invalid});
674}606}
675607
676test "tokenizer - overlong utf8 codepoint" {608test "tokenizer - invalid utf8" {
677 testTokenize("//\xc0\x80\n", []Token.Id{Token.Id.Invalid});609 testTokenize("//\x80", []Token.Id{Token.Id.Invalid});
678 testTokenize("//\xc1\xbf\n", []Token.Id{Token.Id.Invalid});610 testTokenize("//\xbf", []Token.Id{Token.Id.Invalid});
679 testTokenize("//\xe0\x80\x80\n", []Token.Id{Token.Id.Invalid});611 testTokenize("//\xf8", []Token.Id{Token.Id.Invalid});
680 testTokenize("//\xe0\x9f\xbf\n", []Token.Id{Token.Id.Invalid});612 testTokenize("//\xff", []Token.Id{Token.Id.Invalid});
681 testTokenize("//\xf0\x80\x80\x80\n", []Token.Id{Token.Id.Invalid});613 testTokenize("//\xc2\xc0", []Token.Id{Token.Id.Invalid});
682 testTokenize("//\xf0\x8f\xbf\xbf\n", []Token.Id{Token.Id.Invalid});614 testTokenize("//\xe0", []Token.Id{Token.Id.Invalid});
615 testTokenize("//\xf0", []Token.Id{Token.Id.Invalid});
616 testTokenize("//\xf0\x90\x80\xc0", []Token.Id{Token.Id.Invalid});
683}617}
684618
685test "tokenizer - misc invalid utf8" {619test "tokenizer - illegal unicode codepoints" {
686 // codepoint out of bounds
687 testTokenize("//\xf4\x90\x80\x80\n", []Token.Id{Token.Id.Invalid});
688 testTokenize("//\xf7\xbf\xbf\xbf\n", []Token.Id{Token.Id.Invalid});
689 // unicode newline characters.U+0085, U+2028, U+2029620 // unicode newline characters.U+0085, U+2028, U+2029
690 testTokenize("//\xc2\x84\n", []Token.Id{});621 testTokenize("//\xc2\x84", []Token.Id{});
691 testTokenize("//\xc2\x85\n", []Token.Id{Token.Id.Invalid});622 testTokenize("//\xc2\x85", []Token.Id{Token.Id.Invalid});
692 testTokenize("//\xc2\x86\n", []Token.Id{});623 testTokenize("//\xc2\x86", []Token.Id{});
693 testTokenize("//\xe2\x80\xa7\n", []Token.Id{});624 testTokenize("//\xe2\x80\xa7", []Token.Id{});
694 testTokenize("//\xe2\x80\xa8\n", []Token.Id{Token.Id.Invalid});625 testTokenize("//\xe2\x80\xa8", []Token.Id{Token.Id.Invalid});
695 testTokenize("//\xe2\x80\xa9\n", []Token.Id{Token.Id.Invalid});626 testTokenize("//\xe2\x80\xa9", []Token.Id{Token.Id.Invalid});
696 testTokenize("//\xe2\x80\xaa\n", []Token.Id{});627 testTokenize("//\xe2\x80\xaa", []Token.Id{});
697 // surrogate halves
698 testTokenize("//\xed\x9f\x80\n", []Token.Id{});
699 testTokenize("//\xed\xa0\x80\n", []Token.Id{Token.Id.Invalid});
700 testTokenize("//\xed\xbf\xbf\n", []Token.Id{Token.Id.Invalid});
701 testTokenize("//\xee\x80\x80\n", []Token.Id{});
702 // surrogate halves are invalid, even in surrogate pairs
703 testTokenize("//\xed\xa0\xad\xed\xb2\xa9\n", []Token.Id{Token.Id.Invalid});
704}628}
705629
706fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) {630fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) {
707 testTokenizeWithEol(source, expected_tokens, true);631 // (test authors, just make this bigger if you need it)
708}632 var padded_source: [0x100]u8 = undefined;
709fn testTokenizeWithEol(source: []const u8, expected_tokens: []const Token.Id, expected_eol_at_eof: bool) {633 std.mem.copy(u8, padded_source[0..source.len], source);
710 var tokenizer = Tokenizer.init(source);634 padded_source[source.len + 0] = '\n';
635 padded_source[source.len + 1] = '\n';
636 padded_source[source.len + 2] = '\n';
637
638 var tokenizer = Tokenizer.init(padded_source[0..source.len + 3]);
711 for (expected_tokens) |expected_token_id| {639 for (expected_tokens) |expected_token_id| {
712 const token = tokenizer.next();640 const token = tokenizer.next();
713 std.debug.assert(@TagType(Token.Id)(token.id) == @TagType(Token.Id)(expected_token_id));641 std.debug.assert(@TagType(Token.Id)(token.id) == @TagType(Token.Id)(expected_token_id));
...@@ -718,5 +646,5 @@ fn testTokenizeWithEol(source: []const u8, expected_tokens: []const Token.Id, ex...@@ -718,5 +646,5 @@ fn testTokenizeWithEol(source: []const u8, expected_tokens: []const Token.Id, ex
718 else => {},646 else => {},
719 }647 }
720 }648 }
721 std.debug.assert(tokenizer.next().id == if (expected_eol_at_eof) Token.Id.Eof else Token.Id.NoEolAtEof);649 std.debug.assert(tokenizer.next().id == Token.Id.Eof);
722}650}
src/ir.cpp+267-1233
...@@ -31,8 +31,7 @@ struct IrAnalyze {...@@ -31,8 +31,7 @@ struct IrAnalyze {
31 IrBuilder old_irb;31 IrBuilder old_irb;
32 IrBuilder new_irb;32 IrBuilder new_irb;
33 IrExecContext exec_context;33 IrExecContext exec_context;
34 ZigList<IrBasicBlock *> old_bb_queue;34 size_t old_bb_index;
35 size_t block_queue_index;
36 size_t instruction_index;35 size_t instruction_index;
37 TypeTableEntry *explicit_return_type;36 TypeTableEntry *explicit_return_type;
38 ZigList<IrInstruction *> implicit_return_type_list;37 ZigList<IrInstruction *> implicit_return_type_list;
...@@ -159,12 +158,6 @@ static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const c...@@ -159,12 +158,6 @@ static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const c
159 return result;158 return result;
160}159}
161160
162static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) {
163 IrBasicBlock *result = ir_create_basic_block(irb, scope, name_hint);
164 irb->exec->basic_block_list.append(result);
165 return result;
166}
167
168static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {161static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
169 IrBasicBlock *new_bb = ir_create_basic_block(irb, other_bb->scope, other_bb->name_hint);162 IrBasicBlock *new_bb = ir_create_basic_block(irb, other_bb->scope, other_bb->name_hint);
170 ir_link_new_bb(new_bb, other_bb);163 ir_link_new_bb(new_bb, other_bb);
...@@ -2258,1031 +2251,58 @@ static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *so...@@ -2258,1031 +2251,58 @@ static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *so
2258 return &instruction->base;2251 return &instruction->base;
2259}2252}
22602253
2261static IrInstruction *ir_build_set_eval_branch_quota(IrBuilder *irb, Scope *scope, AstNode *source_node,2254static IrInstruction *ir_build_set_eval_branch_quota(IrBuilder *irb, Scope *scope, AstNode *source_node,
2262 IrInstruction *new_quota)2255 IrInstruction *new_quota)
2263{2256{
2264 IrInstructionSetEvalBranchQuota *instruction = ir_build_instruction<IrInstructionSetEvalBranchQuota>(irb, scope, source_node);2257 IrInstructionSetEvalBranchQuota *instruction = ir_build_instruction<IrInstructionSetEvalBranchQuota>(irb, scope, source_node);
2265 instruction->new_quota = new_quota;2258 instruction->new_quota = new_quota;
2266
2267 ir_ref_instruction(new_quota, irb->current_basic_block);
2268
2269 return &instruction->base;
2270}
2271
2272static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
2273 IrInstruction *align_bytes, IrInstruction *target)
2274{
2275 IrInstructionAlignCast *instruction = ir_build_instruction<IrInstructionAlignCast>(irb, scope, source_node);
2276 instruction->align_bytes = align_bytes;
2277 instruction->target = target;
2278
2279 if (align_bytes) ir_ref_instruction(align_bytes, irb->current_basic_block);
2280 ir_ref_instruction(target, irb->current_basic_block);
2281
2282 return &instruction->base;
2283}
2284
2285static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2286 IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);
2287
2288 return &instruction->base;
2289}
2290
2291static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, AstNode *source_node,
2292 IrInstruction *align_bytes)
2293{
2294 IrInstructionSetAlignStack *instruction = ir_build_instruction<IrInstructionSetAlignStack>(irb, scope, source_node);
2295 instruction->align_bytes = align_bytes;
2296
2297 ir_ref_instruction(align_bytes, irb->current_basic_block);
2298
2299 return &instruction->base;
2300}
2301
2302static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
2303 IrInstruction *fn_type, IrInstruction *arg_index)
2304{
2305 IrInstructionArgType *instruction = ir_build_instruction<IrInstructionArgType>(irb, scope, source_node);
2306 instruction->fn_type = fn_type;
2307 instruction->arg_index = arg_index;
2308
2309 ir_ref_instruction(fn_type, irb->current_basic_block);
2310 ir_ref_instruction(arg_index, irb->current_basic_block);
2311
2312 return &instruction->base;
2313}
2314
2315static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
2316 return nullptr;
2317}
2318
2319static IrInstruction *ir_instruction_condbr_get_dep(IrInstructionCondBr *instruction, size_t index) {
2320 switch (index) {
2321 case 0: return instruction->condition;
2322 default: return nullptr;
2323 }
2324}
2325
2326static IrInstruction *ir_instruction_switchbr_get_dep(IrInstructionSwitchBr *instruction, size_t index) {
2327 switch (index) {
2328 case 0: return instruction->target_value;
2329 }
2330 size_t case_index = index - 2;
2331 if (case_index < instruction->case_count) return instruction->cases[case_index].value;
2332 return nullptr;
2333}
2334
2335static IrInstruction *ir_instruction_switchvar_get_dep(IrInstructionSwitchVar *instruction, size_t index) {
2336 switch (index) {
2337 case 0: return instruction->target_value_ptr;
2338 case 1: return instruction->prong_value;
2339 default: return nullptr;
2340 }
2341}
2342
2343static IrInstruction *ir_instruction_switchtarget_get_dep(IrInstructionSwitchTarget *instruction, size_t index) {
2344 switch (index) {
2345 case 0: return instruction->target_value_ptr;
2346 default: return nullptr;
2347 }
2348}
2349
2350static IrInstruction *ir_instruction_phi_get_dep(IrInstructionPhi *instruction, size_t index) {
2351 if (index < instruction->incoming_count) return instruction->incoming_values[index];
2352 return nullptr;
2353}
2354
2355static IrInstruction *ir_instruction_unop_get_dep(IrInstructionUnOp *instruction, size_t index) {
2356 switch (index) {
2357 case 0: return instruction->value;
2358 default: return nullptr;
2359 }
2360}
2361
2362static IrInstruction *ir_instruction_binop_get_dep(IrInstructionBinOp *instruction, size_t index) {
2363 switch (index) {
2364 case 0: return instruction->op1;
2365 case 1: return instruction->op2;
2366 default: return nullptr;
2367 }
2368}
2369
2370static IrInstruction *ir_instruction_declvar_get_dep(IrInstructionDeclVar *instruction, size_t index) {
2371 if (index == 0) return instruction->init_value;
2372 index -= 1;
2373
2374 if (instruction->align_value != nullptr) {
2375 if (index == 0) return instruction->align_value;
2376 index -= 1;
2377 }
2378
2379 if (instruction->var_type != nullptr) {
2380 if (index == 0) return instruction->var_type;
2381 index -= 1;
2382 }
2383
2384 return nullptr;
2385}
2386
2387static IrInstruction *ir_instruction_export_get_dep(IrInstructionExport *instruction, size_t index) {
2388 if (index < 1) return instruction->name;
2389 index -= 1;
2390
2391 if (index < 1) return instruction->target;
2392 index -= 1;
2393
2394 if (instruction->linkage != nullptr) {
2395 if (index < 1) return instruction->linkage;
2396 index -= 1;
2397 }
2398
2399 return nullptr;
2400}
2401
2402static IrInstruction *ir_instruction_loadptr_get_dep(IrInstructionLoadPtr *instruction, size_t index) {
2403 switch (index) {
2404 case 0: return instruction->ptr;
2405 default: return nullptr;
2406 }
2407}
2408
2409static IrInstruction *ir_instruction_storeptr_get_dep(IrInstructionStorePtr *instruction, size_t index) {
2410 switch (index) {
2411 case 0: return instruction->ptr;
2412 case 1: return instruction->value;
2413 default: return nullptr;
2414 }
2415}
2416
2417static IrInstruction *ir_instruction_fieldptr_get_dep(IrInstructionFieldPtr *instruction, size_t index) {
2418 switch (index) {
2419 case 0: return instruction->container_ptr;
2420 default: return nullptr;
2421 }
2422}
2423
2424static IrInstruction *ir_instruction_structfieldptr_get_dep(IrInstructionStructFieldPtr *instruction, size_t index) {
2425 switch (index) {
2426 case 0: return instruction->struct_ptr;
2427 default: return nullptr;
2428 }
2429}
2430
2431static IrInstruction *ir_instruction_unionfieldptr_get_dep(IrInstructionUnionFieldPtr *instruction, size_t index) {
2432 switch (index) {
2433 case 0: return instruction->union_ptr;
2434 default: return nullptr;
2435 }
2436}
2437
2438static IrInstruction *ir_instruction_elemptr_get_dep(IrInstructionElemPtr *instruction, size_t index) {
2439 switch (index) {
2440 case 0: return instruction->array_ptr;
2441 case 1: return instruction->elem_index;
2442 default: return nullptr;
2443 }
2444}
2445
2446static IrInstruction *ir_instruction_varptr_get_dep(IrInstructionVarPtr *instruction, size_t index) {
2447 switch (index) {
2448 case 0: return instruction->var->decl_instruction; // can be null
2449 default: return nullptr;
2450 }
2451}
2452
2453static IrInstruction *ir_instruction_call_get_dep(IrInstructionCall *instruction, size_t index) {
2454 if (index == 0) return instruction->fn_ref;
2455 size_t arg_index = index - 1;
2456 if (arg_index < instruction->arg_count) return instruction->args[arg_index];
2457 return nullptr;
2458}
2459
2460static IrInstruction *ir_instruction_const_get_dep(IrInstructionConst *instruction, size_t index) {
2461 return nullptr;
2462}
2463
2464static IrInstruction *ir_instruction_return_get_dep(IrInstructionReturn *instruction, size_t index) {
2465 switch (index) {
2466 case 0: return instruction->value;
2467 default: return nullptr;
2468 }
2469}
2470
2471static IrInstruction *ir_instruction_cast_get_dep(IrInstructionCast *instruction, size_t index) {
2472 switch (index) {
2473 case 0: return instruction->value;
2474 default: return nullptr;
2475 }
2476}
2477
2478static IrInstruction *ir_instruction_containerinitlist_get_dep(IrInstructionContainerInitList *instruction,
2479 size_t index)
2480{
2481 if (index == 0) return instruction->container_type;
2482 size_t item_index = index - 1;
2483 if (item_index < instruction->item_count) return instruction->items[item_index];
2484 return nullptr;
2485}
2486
2487static IrInstruction *ir_instruction_containerinitfields_get_dep(IrInstructionContainerInitFields *instruction,
2488 size_t index)
2489{
2490 if (index == 0) return instruction->container_type;
2491 size_t field_index = index - 1;
2492 if (field_index < instruction->field_count) return instruction->fields[field_index].value;
2493 return nullptr;
2494}
2495
2496static IrInstruction *ir_instruction_structinit_get_dep(IrInstructionStructInit *instruction, size_t index) {
2497 if (index < instruction->field_count) return instruction->fields[index].value;
2498 return nullptr;
2499}
2500
2501static IrInstruction *ir_instruction_unioninit_get_dep(IrInstructionUnionInit *instruction, size_t index) {
2502 switch (index) {
2503 case 0: return instruction->init_value;
2504 default: return nullptr;
2505 }
2506}
2507
2508static IrInstruction *ir_instruction_unreachable_get_dep(IrInstructionUnreachable *instruction, size_t index) {
2509 return nullptr;
2510}
2511
2512static IrInstruction *ir_instruction_typeof_get_dep(IrInstructionTypeOf *instruction, size_t index) {
2513 switch (index) {
2514 case 0: return instruction->value;
2515 default: return nullptr;
2516 }
2517}
2518
2519static IrInstruction *ir_instruction_toptrtype_get_dep(IrInstructionToPtrType *instruction, size_t index) {
2520 switch (index) {
2521 case 0: return instruction->value;
2522 default: return nullptr;
2523 }
2524}
2525
2526static IrInstruction *ir_instruction_ptrtypechild_get_dep(IrInstructionPtrTypeChild *instruction, size_t index) {
2527 switch (index) {
2528 case 0: return instruction->value;
2529 default: return nullptr;
2530 }
2531}
2532
2533static IrInstruction *ir_instruction_setdebugsafety_get_dep(IrInstructionSetDebugSafety *instruction, size_t index) {
2534 switch (index) {
2535 case 0: return instruction->scope_value;
2536 case 1: return instruction->debug_safety_on;
2537 default: return nullptr;
2538 }
2539}
2540
2541static IrInstruction *ir_instruction_setfloatmode_get_dep(IrInstructionSetFloatMode *instruction, size_t index) {
2542 switch (index) {
2543 case 0: return instruction->scope_value;
2544 case 1: return instruction->mode_value;
2545 default: return nullptr;
2546 }
2547}
2548
2549static IrInstruction *ir_instruction_arraytype_get_dep(IrInstructionArrayType *instruction, size_t index) {
2550 switch (index) {
2551 case 0: return instruction->size;
2552 case 1: return instruction->child_type;
2553 default: return nullptr;
2554 }
2555}
2556
2557static IrInstruction *ir_instruction_slicetype_get_dep(IrInstructionSliceType *instruction, size_t index) {
2558 switch (index) {
2559 case 0: return instruction->child_type;
2560 default: return nullptr;
2561 }
2562}
2563
2564static IrInstruction *ir_instruction_asm_get_dep(IrInstructionAsm *instruction, size_t index) {
2565 AstNode *asm_node = instruction->base.source_node;
2566 if (index < asm_node->data.asm_expr.output_list.length) return instruction->output_types[index];
2567 size_t input_index = index - asm_node->data.asm_expr.output_list.length;
2568 if (input_index < asm_node->data.asm_expr.input_list.length) return instruction->input_list[input_index];
2569 return nullptr;
2570}
2571
2572static IrInstruction *ir_instruction_sizeof_get_dep(IrInstructionSizeOf *instruction, size_t index) {
2573 switch (index) {
2574 case 0: return instruction->type_value;
2575 default: return nullptr;
2576 }
2577}
2578
2579static IrInstruction *ir_instruction_testnonnull_get_dep(IrInstructionTestNonNull *instruction, size_t index) {
2580 switch (index) {
2581 case 0: return instruction->value;
2582 default: return nullptr;
2583 }
2584}
2585
2586static IrInstruction *ir_instruction_unwrapmaybe_get_dep(IrInstructionUnwrapMaybe *instruction, size_t index) {
2587 switch (index) {
2588 case 0: return instruction->value;
2589 default: return nullptr;
2590 }
2591}
2592
2593static IrInstruction *ir_instruction_maybewrap_get_dep(IrInstructionMaybeWrap *instruction, size_t index) {
2594 switch (index) {
2595 case 0: return instruction->value;
2596 default: return nullptr;
2597 }
2598}
2599
2600static IrInstruction *ir_instruction_uniontag_get_dep(IrInstructionUnionTag *instruction, size_t index) {
2601 switch (index) {
2602 case 0: return instruction->value;
2603 default: return nullptr;
2604 }
2605}
2606
2607static IrInstruction *ir_instruction_clz_get_dep(IrInstructionClz *instruction, size_t index) {
2608 switch (index) {
2609 case 0: return instruction->value;
2610 default: return nullptr;
2611 }
2612}
2613
2614static IrInstruction *ir_instruction_ctz_get_dep(IrInstructionCtz *instruction, size_t index) {
2615 switch (index) {
2616 case 0: return instruction->value;
2617 default: return nullptr;
2618 }
2619}
2620
2621static IrInstruction *ir_instruction_import_get_dep(IrInstructionImport *instruction, size_t index) {
2622 switch (index) {
2623 case 0: return instruction->name;
2624 default: return nullptr;
2625 }
2626}
2627
2628static IrInstruction *ir_instruction_cimport_get_dep(IrInstructionCImport *instruction, size_t index) {
2629 return nullptr;
2630}
2631
2632static IrInstruction *ir_instruction_cinclude_get_dep(IrInstructionCInclude *instruction, size_t index) {
2633 switch (index) {
2634 case 0: return instruction->name;
2635 default: return nullptr;
2636 }
2637}
2638
2639static IrInstruction *ir_instruction_cdefine_get_dep(IrInstructionCDefine *instruction, size_t index) {
2640 switch (index) {
2641 case 0: return instruction->name;
2642 case 1: return instruction->value;
2643 default: return nullptr;
2644 }
2645}
2646
2647static IrInstruction *ir_instruction_cundef_get_dep(IrInstructionCUndef *instruction, size_t index) {
2648 switch (index) {
2649 case 0: return instruction->name;
2650 default: return nullptr;
2651 }
2652}
2653
2654static IrInstruction *ir_instruction_arraylen_get_dep(IrInstructionArrayLen *instruction, size_t index) {
2655 switch (index) {
2656 case 0: return instruction->array_value;
2657 default: return nullptr;
2658 }
2659}
2660
2661static IrInstruction *ir_instruction_ref_get_dep(IrInstructionRef *instruction, size_t index) {
2662 switch (index) {
2663 case 0: return instruction->value;
2664 default: return nullptr;
2665 }
2666}
2667
2668static IrInstruction *ir_instruction_minvalue_get_dep(IrInstructionMinValue *instruction, size_t index) {
2669 switch (index) {
2670 case 0: return instruction->value;
2671 default: return nullptr;
2672 }
2673}
2674
2675static IrInstruction *ir_instruction_maxvalue_get_dep(IrInstructionMaxValue *instruction, size_t index) {
2676 switch (index) {
2677 case 0: return instruction->value;
2678 default: return nullptr;
2679 }
2680}
2681
2682static IrInstruction *ir_instruction_compileerr_get_dep(IrInstructionCompileErr *instruction, size_t index) {
2683 switch (index) {
2684 case 0: return instruction->msg;
2685 default: return nullptr;
2686 }
2687}
2688
2689static IrInstruction *ir_instruction_compilelog_get_dep(IrInstructionCompileLog *instruction, size_t index) {
2690 if (index < instruction->msg_count)
2691 return instruction->msg_list[index];
2692 return nullptr;
2693}
2694
2695static IrInstruction *ir_instruction_errname_get_dep(IrInstructionErrName *instruction, size_t index) {
2696 switch (index) {
2697 case 0: return instruction->value;
2698 default: return nullptr;
2699 }
2700}
2701
2702static IrInstruction *ir_instruction_embedfile_get_dep(IrInstructionEmbedFile *instruction, size_t index) {
2703 switch (index) {
2704 case 0: return instruction->name;
2705 default: return nullptr;
2706 }
2707}
2708
2709static IrInstruction *ir_instruction_cmpxchg_get_dep(IrInstructionCmpxchg *instruction, size_t index) {
2710 switch (index) {
2711 case 0: return instruction->ptr;
2712 case 1: return instruction->cmp_value;
2713 case 2: return instruction->new_value;
2714 case 3: return instruction->success_order_value;
2715 case 4: return instruction->failure_order_value;
2716 default: return nullptr;
2717 }
2718}
2719
2720static IrInstruction *ir_instruction_fence_get_dep(IrInstructionFence *instruction, size_t index) {
2721 switch (index) {
2722 case 0: return instruction->order_value;
2723 default: return nullptr;
2724 }
2725}
2726
2727static IrInstruction *ir_instruction_truncate_get_dep(IrInstructionTruncate *instruction, size_t index) {
2728 switch (index) {
2729 case 0: return instruction->dest_type;
2730 case 1: return instruction->target;
2731 default: return nullptr;
2732 }
2733}
2734
2735static IrInstruction *ir_instruction_inttype_get_dep(IrInstructionIntType *instruction, size_t index) {
2736 switch (index) {
2737 case 0: return instruction->is_signed;
2738 case 1: return instruction->bit_count;
2739 default: return nullptr;
2740 }
2741}
2742
2743static IrInstruction *ir_instruction_boolnot_get_dep(IrInstructionBoolNot *instruction, size_t index) {
2744 switch (index) {
2745 case 0: return instruction->value;
2746 default: return nullptr;
2747 }
2748}
2749
2750static IrInstruction *ir_instruction_memset_get_dep(IrInstructionMemset *instruction, size_t index) {
2751 switch (index) {
2752 case 0: return instruction->dest_ptr;
2753 case 1: return instruction->byte;
2754 case 2: return instruction->count;
2755 default: return nullptr;
2756 }
2757}
2758
2759static IrInstruction *ir_instruction_memcpy_get_dep(IrInstructionMemcpy *instruction, size_t index) {
2760 switch (index) {
2761 case 0: return instruction->dest_ptr;
2762 case 1: return instruction->src_ptr;
2763 case 2: return instruction->count;
2764 default: return nullptr;
2765 }
2766}
2767
2768static IrInstruction *ir_instruction_slice_get_dep(IrInstructionSlice *instruction, size_t index) {
2769 switch (index) {
2770 case 0: return instruction->ptr;
2771 case 1: return instruction->start;
2772 case 2: return instruction->end;
2773 default: return nullptr;
2774 }
2775}
2776
2777static IrInstruction *ir_instruction_membercount_get_dep(IrInstructionMemberCount *instruction, size_t index) {
2778 switch (index) {
2779 case 0: return instruction->container;
2780 default: return nullptr;
2781 }
2782}
2783
2784static IrInstruction *ir_instruction_membertype_get_dep(IrInstructionMemberType *instruction, size_t index) {
2785 switch (index) {
2786 case 0: return instruction->container_type;
2787 case 1: return instruction->member_index;
2788 default: return nullptr;
2789 }
2790}
2791
2792static IrInstruction *ir_instruction_membername_get_dep(IrInstructionMemberName *instruction, size_t index) {
2793 switch (index) {
2794 case 0: return instruction->container_type;
2795 case 1: return instruction->member_index;
2796 default: return nullptr;
2797 }
2798}
2799
2800static IrInstruction *ir_instruction_breakpoint_get_dep(IrInstructionBreakpoint *instruction, size_t index) {
2801 return nullptr;
2802}
2803
2804static IrInstruction *ir_instruction_returnaddress_get_dep(IrInstructionReturnAddress *instruction, size_t index) {
2805 return nullptr;
2806}
2807
2808static IrInstruction *ir_instruction_frameaddress_get_dep(IrInstructionFrameAddress *instruction, size_t index) {
2809 return nullptr;
2810}
2811
2812static IrInstruction *ir_instruction_alignof_get_dep(IrInstructionAlignOf *instruction, size_t index) {
2813 switch (index) {
2814 case 0: return instruction->type_value;
2815 default: return nullptr;
2816 }
2817}
2818
2819static IrInstruction *ir_instruction_overflowop_get_dep(IrInstructionOverflowOp *instruction, size_t index) {
2820 switch (index) {
2821 case 0: return instruction->type_value;
2822 case 1: return instruction->op1;
2823 case 2: return instruction->op2;
2824 case 3: return instruction->result_ptr;
2825 default: return nullptr;
2826 }
2827}
2828
2829static IrInstruction *ir_instruction_testerr_get_dep(IrInstructionTestErr *instruction, size_t index) {
2830 switch (index) {
2831 case 0: return instruction->value;
2832 default: return nullptr;
2833 }
2834}
2835
2836static IrInstruction *ir_instruction_unwraperrcode_get_dep(IrInstructionUnwrapErrCode *instruction, size_t index) {
2837 switch (index) {
2838 case 0: return instruction->value;
2839 default: return nullptr;
2840 }
2841}
2842
2843static IrInstruction *ir_instruction_unwraperrpayload_get_dep(IrInstructionUnwrapErrPayload *instruction,
2844 size_t index)
2845{
2846 switch (index) {
2847 case 0: return instruction->value;
2848 default: return nullptr;
2849 }
2850}
2851
2852static IrInstruction *ir_instruction_errwrapcode_get_dep(IrInstructionErrWrapCode *instruction, size_t index) {
2853 switch (index) {
2854 case 0: return instruction->value;
2855 default: return nullptr;
2856 }
2857}
2858
2859static IrInstruction *ir_instruction_errwrappayload_get_dep(IrInstructionErrWrapPayload *instruction, size_t index) {
2860 switch (index) {
2861 case 0: return instruction->value;
2862 default: return nullptr;
2863 }
2864}
2865
2866static IrInstruction *ir_instruction_fnproto_get_dep(IrInstructionFnProto *instruction, size_t index) {
2867 if (index == 0) return instruction->return_type;
2868 size_t param_index = index - 1;
2869 if (param_index < instruction->base.source_node->data.fn_proto.params.length) {
2870 return instruction->param_types[param_index];
2871 }
2872 size_t next_index = param_index - instruction->base.source_node->data.fn_proto.params.length;
2873 if (next_index == 0 && instruction->align_value != nullptr) {
2874 return instruction->align_value;
2875 }
2876 return nullptr;
2877}
2878
2879static IrInstruction *ir_instruction_testcomptime_get_dep(IrInstructionTestComptime *instruction, size_t index) {
2880 switch (index) {
2881 case 0: return instruction->value;
2882 default: return nullptr;
2883 }
2884}
2885
2886static IrInstruction *ir_instruction_ptrcast_get_dep(IrInstructionPtrCast *instruction,
2887 size_t index)
2888{
2889 switch (index) {
2890 case 0: return instruction->ptr;
2891 case 1: return instruction->dest_type;
2892 default: return nullptr;
2893 }
2894}
2895
2896static IrInstruction *ir_instruction_bitcast_get_dep(IrInstructionBitCast *instruction,
2897 size_t index)
2898{
2899 switch (index) {
2900 case 0: return instruction->value;
2901 case 1: return instruction->dest_type;
2902 default: return nullptr;
2903 }
2904}
2905
2906static IrInstruction *ir_instruction_widenorshorten_get_dep(IrInstructionWidenOrShorten *instruction, size_t index) {
2907 switch (index) {
2908 case 0: return instruction->target;
2909 default: return nullptr;
2910 }
2911}
2912
2913static IrInstruction *ir_instruction_inttoptr_get_dep(IrInstructionIntToPtr *instruction, size_t index) {
2914 switch (index) {
2915 case 0: return instruction->target;
2916 case 1: return instruction->dest_type;
2917 default: return nullptr;
2918 }
2919}
2920
2921static IrInstruction *ir_instruction_ptrtoint_get_dep(IrInstructionPtrToInt *instruction, size_t index) {
2922 switch (index) {
2923 case 0: return instruction->target;
2924 default: return nullptr;
2925 }
2926}
2927
2928static IrInstruction *ir_instruction_inttoenum_get_dep(IrInstructionIntToEnum *instruction, size_t index) {
2929 switch (index) {
2930 case 0: return instruction->target;
2931 default: return nullptr;
2932 }
2933}
2934
2935static IrInstruction *ir_instruction_inttoerr_get_dep(IrInstructionIntToErr *instruction, size_t index) {
2936 switch (index) {
2937 case 0: return instruction->target;
2938 default: return nullptr;
2939 }
2940}
2941
2942static IrInstruction *ir_instruction_errtoint_get_dep(IrInstructionErrToInt *instruction, size_t index) {
2943 switch (index) {
2944 case 0: return instruction->target;
2945 default: return nullptr;
2946 }
2947}
2948
2949static IrInstruction *ir_instruction_checkswitchprongs_get_dep(IrInstructionCheckSwitchProngs *instruction,
2950 size_t index)
2951{
2952 if (index == 0) return instruction->target_value;
2953 size_t range_index = index - 1;
2954 if (range_index < instruction->range_count * 2) {
2955 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_index / 2];
2956 return (range_index % 2 == 0) ? range->start : range->end;
2957 }
2958 return nullptr;
2959}
2960
2961static IrInstruction *ir_instruction_checkstatementisvoid_get_dep(IrInstructionCheckStatementIsVoid *instruction,
2962 size_t index)
2963{
2964 switch (index) {
2965 case 0: return instruction->statement_value;
2966 default: return nullptr;
2967 }
2968}
2969
2970static IrInstruction *ir_instruction_typename_get_dep(IrInstructionTypeName *instruction, size_t index) {
2971 switch (index) {
2972 case 0: return instruction->type_value;
2973 default: return nullptr;
2974 }
2975}
2976
2977static IrInstruction *ir_instruction_canimplicitcast_get_dep(IrInstructionCanImplicitCast *instruction, size_t index) {
2978 switch (index) {
2979 case 0: return instruction->type_value;
2980 case 1: return instruction->target_value;
2981 default: return nullptr;
2982 }
2983}
2984
2985static IrInstruction *ir_instruction_declref_get_dep(IrInstructionDeclRef *instruction, size_t index) {
2986 return nullptr;
2987}
29882259
2989static IrInstruction *ir_instruction_panic_get_dep(IrInstructionPanic *instruction, size_t index) {2260 ir_ref_instruction(new_quota, irb->current_basic_block);
2990 switch (index) {
2991 case 0: return instruction->msg;
2992 default: return nullptr;
2993 }
2994}
29952261
2996static IrInstruction *ir_instruction_enumtagname_get_dep(IrInstructionTagName *instruction, size_t index) {2262 return &instruction->base;
2997 switch (index) {
2998 case 0: return instruction->target;
2999 default: return nullptr;
3000 }
3001}2263}
30022264
3003static IrInstruction *ir_instruction_enumtagtype_get_dep(IrInstructionTagType *instruction, size_t index) {2265static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
3004 switch (index) {2266 IrInstruction *align_bytes, IrInstruction *target)
3005 case 0: return instruction->target;2267{
3006 default: return nullptr;2268 IrInstructionAlignCast *instruction = ir_build_instruction<IrInstructionAlignCast>(irb, scope, source_node);
3007 }2269 instruction->align_bytes = align_bytes;
3008}2270 instruction->target = target;
30092271
3010static IrInstruction *ir_instruction_fieldparentptr_get_dep(IrInstructionFieldParentPtr *instruction, size_t index) {2272 if (align_bytes) ir_ref_instruction(align_bytes, irb->current_basic_block);
3011 switch (index) {2273 ir_ref_instruction(target, irb->current_basic_block);
3012 case 0: return instruction->type_value;
3013 case 1: return instruction->field_name;
3014 case 2: return instruction->field_ptr;
3015 default: return nullptr;
3016 }
3017}
30182274
3019static IrInstruction *ir_instruction_offsetof_get_dep(IrInstructionOffsetOf *instruction, size_t index) {2275 return &instruction->base;
3020 switch (index) {
3021 case 0: return instruction->type_value;
3022 case 1: return instruction->field_name;
3023 default: return nullptr;
3024 }
3025}2276}
30262277
3027static IrInstruction *ir_instruction_typeid_get_dep(IrInstructionTypeId *instruction, size_t index) {2278static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
3028 switch (index) {2279 IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);
3029 case 0: return instruction->type_value;
3030 default: return nullptr;
3031 }
3032}
30332280
3034static IrInstruction *ir_instruction_setevalbranchquota_get_dep(IrInstructionSetEvalBranchQuota *instruction, size_t index) {2281 return &instruction->base;
3035 switch (index) {
3036 case 0: return instruction->new_quota;
3037 default: return nullptr;
3038 }
3039}2282}
30402283
3041static IrInstruction *ir_instruction_ptrtypeof_get_dep(IrInstructionPtrTypeOf *instruction, size_t index) {2284static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, AstNode *source_node,
3042 switch (index) {2285 IrInstruction *align_bytes)
3043 case 0: return instruction->align_value;2286{
3044 case 1: return instruction->child_type;2287 IrInstructionSetAlignStack *instruction = ir_build_instruction<IrInstructionSetAlignStack>(irb, scope, source_node);
3045 default: return nullptr;2288 instruction->align_bytes = align_bytes;
3046 }
3047}
30482289
3049static IrInstruction *ir_instruction_aligncast_get_dep(IrInstructionAlignCast *instruction, size_t index) {2290 ir_ref_instruction(align_bytes, irb->current_basic_block);
3050 switch (index) {
3051 case 0: return instruction->target;
3052 case 1: return instruction->align_bytes; // can be null
3053 default: return nullptr;
3054 }
3055}
30562291
3057static IrInstruction *ir_instruction_opaquetype_get_dep(IrInstructionOpaqueType *instruction, size_t index) {2292 return &instruction->base;
3058 return nullptr;
3059}2293}
30602294
3061static IrInstruction *ir_instruction_setalignstack_get_dep(IrInstructionSetAlignStack *instruction, size_t index) {2295static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
3062 switch (index) {2296 IrInstruction *fn_type, IrInstruction *arg_index)
3063 case 0: return instruction->align_bytes;2297{
3064 default: return nullptr;2298 IrInstructionArgType *instruction = ir_build_instruction<IrInstructionArgType>(irb, scope, source_node);
3065 }2299 instruction->fn_type = fn_type;
3066}2300 instruction->arg_index = arg_index;
30672301
3068static IrInstruction *ir_instruction_argtype_get_dep(IrInstructionArgType *instruction, size_t index) {2302 ir_ref_instruction(fn_type, irb->current_basic_block);
3069 switch (index) {2303 ir_ref_instruction(arg_index, irb->current_basic_block);
3070 case 0: return instruction->fn_type;
3071 case 1: return instruction->arg_index;
3072 default: return nullptr;
3073 }
3074}
30752304
3076static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {2305 return &instruction->base;
3077 switch (instruction->id) {
3078 case IrInstructionIdInvalid:
3079 zig_unreachable();
3080 case IrInstructionIdBr:
3081 return ir_instruction_br_get_dep((IrInstructionBr *) instruction, index);
3082 case IrInstructionIdCondBr:
3083 return ir_instruction_condbr_get_dep((IrInstructionCondBr *) instruction, index);
3084 case IrInstructionIdSwitchBr:
3085 return ir_instruction_switchbr_get_dep((IrInstructionSwitchBr *) instruction, index);
3086 case IrInstructionIdSwitchVar:
3087 return ir_instruction_switchvar_get_dep((IrInstructionSwitchVar *) instruction, index);
3088 case IrInstructionIdSwitchTarget:
3089 return ir_instruction_switchtarget_get_dep((IrInstructionSwitchTarget *) instruction, index);
3090 case IrInstructionIdPhi:
3091 return ir_instruction_phi_get_dep((IrInstructionPhi *) instruction, index);
3092 case IrInstructionIdUnOp:
3093 return ir_instruction_unop_get_dep((IrInstructionUnOp *) instruction, index);
3094 case IrInstructionIdBinOp:
3095 return ir_instruction_binop_get_dep((IrInstructionBinOp *) instruction, index);
3096 case IrInstructionIdDeclVar:
3097 return ir_instruction_declvar_get_dep((IrInstructionDeclVar *) instruction, index);
3098 case IrInstructionIdExport:
3099 return ir_instruction_export_get_dep((IrInstructionExport *) instruction, index);
3100 case IrInstructionIdLoadPtr:
3101 return ir_instruction_loadptr_get_dep((IrInstructionLoadPtr *) instruction, index);
3102 case IrInstructionIdStorePtr:
3103 return ir_instruction_storeptr_get_dep((IrInstructionStorePtr *) instruction, index);
3104 case IrInstructionIdFieldPtr:
3105 return ir_instruction_fieldptr_get_dep((IrInstructionFieldPtr *) instruction, index);
3106 case IrInstructionIdStructFieldPtr:
3107 return ir_instruction_structfieldptr_get_dep((IrInstructionStructFieldPtr *) instruction, index);
3108 case IrInstructionIdUnionFieldPtr:
3109 return ir_instruction_unionfieldptr_get_dep((IrInstructionUnionFieldPtr *) instruction, index);
3110 case IrInstructionIdElemPtr:
3111 return ir_instruction_elemptr_get_dep((IrInstructionElemPtr *) instruction, index);
3112 case IrInstructionIdVarPtr:
3113 return ir_instruction_varptr_get_dep((IrInstructionVarPtr *) instruction, index);
3114 case IrInstructionIdCall:
3115 return ir_instruction_call_get_dep((IrInstructionCall *) instruction, index);
3116 case IrInstructionIdConst:
3117 return ir_instruction_const_get_dep((IrInstructionConst *) instruction, index);
3118 case IrInstructionIdReturn:
3119 return ir_instruction_return_get_dep((IrInstructionReturn *) instruction, index);
3120 case IrInstructionIdCast:
3121 return ir_instruction_cast_get_dep((IrInstructionCast *) instruction, index);
3122 case IrInstructionIdContainerInitList:
3123 return ir_instruction_containerinitlist_get_dep((IrInstructionContainerInitList *) instruction, index);
3124 case IrInstructionIdContainerInitFields:
3125 return ir_instruction_containerinitfields_get_dep((IrInstructionContainerInitFields *) instruction, index);
3126 case IrInstructionIdStructInit:
3127 return ir_instruction_structinit_get_dep((IrInstructionStructInit *) instruction, index);
3128 case IrInstructionIdUnionInit:
3129 return ir_instruction_unioninit_get_dep((IrInstructionUnionInit *) instruction, index);
3130 case IrInstructionIdUnreachable:
3131 return ir_instruction_unreachable_get_dep((IrInstructionUnreachable *) instruction, index);
3132 case IrInstructionIdTypeOf:
3133 return ir_instruction_typeof_get_dep((IrInstructionTypeOf *) instruction, index);
3134 case IrInstructionIdToPtrType:
3135 return ir_instruction_toptrtype_get_dep((IrInstructionToPtrType *) instruction, index);
3136 case IrInstructionIdPtrTypeChild:
3137 return ir_instruction_ptrtypechild_get_dep((IrInstructionPtrTypeChild *) instruction, index);
3138 case IrInstructionIdSetDebugSafety:
3139 return ir_instruction_setdebugsafety_get_dep((IrInstructionSetDebugSafety *) instruction, index);
3140 case IrInstructionIdSetFloatMode:
3141 return ir_instruction_setfloatmode_get_dep((IrInstructionSetFloatMode *) instruction, index);
3142 case IrInstructionIdArrayType:
3143 return ir_instruction_arraytype_get_dep((IrInstructionArrayType *) instruction, index);
3144 case IrInstructionIdSliceType:
3145 return ir_instruction_slicetype_get_dep((IrInstructionSliceType *) instruction, index);
3146 case IrInstructionIdAsm:
3147 return ir_instruction_asm_get_dep((IrInstructionAsm *) instruction, index);
3148 case IrInstructionIdSizeOf:
3149 return ir_instruction_sizeof_get_dep((IrInstructionSizeOf *) instruction, index);
3150 case IrInstructionIdTestNonNull:
3151 return ir_instruction_testnonnull_get_dep((IrInstructionTestNonNull *) instruction, index);
3152 case IrInstructionIdUnwrapMaybe:
3153 return ir_instruction_unwrapmaybe_get_dep((IrInstructionUnwrapMaybe *) instruction, index);
3154 case IrInstructionIdMaybeWrap:
3155 return ir_instruction_maybewrap_get_dep((IrInstructionMaybeWrap *) instruction, index);
3156 case IrInstructionIdUnionTag:
3157 return ir_instruction_uniontag_get_dep((IrInstructionUnionTag *) instruction, index);
3158 case IrInstructionIdClz:
3159 return ir_instruction_clz_get_dep((IrInstructionClz *) instruction, index);
3160 case IrInstructionIdCtz:
3161 return ir_instruction_ctz_get_dep((IrInstructionCtz *) instruction, index);
3162 case IrInstructionIdImport:
3163 return ir_instruction_import_get_dep((IrInstructionImport *) instruction, index);
3164 case IrInstructionIdCImport:
3165 return ir_instruction_cimport_get_dep((IrInstructionCImport *) instruction, index);
3166 case IrInstructionIdCInclude:
3167 return ir_instruction_cinclude_get_dep((IrInstructionCInclude *) instruction, index);
3168 case IrInstructionIdCDefine:
3169 return ir_instruction_cdefine_get_dep((IrInstructionCDefine *) instruction, index);
3170 case IrInstructionIdCUndef:
3171 return ir_instruction_cundef_get_dep((IrInstructionCUndef *) instruction, index);
3172 case IrInstructionIdArrayLen:
3173 return ir_instruction_arraylen_get_dep((IrInstructionArrayLen *) instruction, index);
3174 case IrInstructionIdRef:
3175 return ir_instruction_ref_get_dep((IrInstructionRef *) instruction, index);
3176 case IrInstructionIdMinValue:
3177 return ir_instruction_minvalue_get_dep((IrInstructionMinValue *) instruction, index);
3178 case IrInstructionIdMaxValue:
3179 return ir_instruction_maxvalue_get_dep((IrInstructionMaxValue *) instruction, index);
3180 case IrInstructionIdCompileErr:
3181 return ir_instruction_compileerr_get_dep((IrInstructionCompileErr *) instruction, index);
3182 case IrInstructionIdCompileLog:
3183 return ir_instruction_compilelog_get_dep((IrInstructionCompileLog *) instruction, index);
3184 case IrInstructionIdErrName:
3185 return ir_instruction_errname_get_dep((IrInstructionErrName *) instruction, index);
3186 case IrInstructionIdEmbedFile:
3187 return ir_instruction_embedfile_get_dep((IrInstructionEmbedFile *) instruction, index);
3188 case IrInstructionIdCmpxchg:
3189 return ir_instruction_cmpxchg_get_dep((IrInstructionCmpxchg *) instruction, index);
3190 case IrInstructionIdFence:
3191 return ir_instruction_fence_get_dep((IrInstructionFence *) instruction, index);
3192 case IrInstructionIdTruncate:
3193 return ir_instruction_truncate_get_dep((IrInstructionTruncate *) instruction, index);
3194 case IrInstructionIdIntType:
3195 return ir_instruction_inttype_get_dep((IrInstructionIntType *) instruction, index);
3196 case IrInstructionIdBoolNot:
3197 return ir_instruction_boolnot_get_dep((IrInstructionBoolNot *) instruction, index);
3198 case IrInstructionIdMemset:
3199 return ir_instruction_memset_get_dep((IrInstructionMemset *) instruction, index);
3200 case IrInstructionIdMemcpy:
3201 return ir_instruction_memcpy_get_dep((IrInstructionMemcpy *) instruction, index);
3202 case IrInstructionIdSlice:
3203 return ir_instruction_slice_get_dep((IrInstructionSlice *) instruction, index);
3204 case IrInstructionIdMemberCount:
3205 return ir_instruction_membercount_get_dep((IrInstructionMemberCount *) instruction, index);
3206 case IrInstructionIdMemberType:
3207 return ir_instruction_membertype_get_dep((IrInstructionMemberType *) instruction, index);
3208 case IrInstructionIdMemberName:
3209 return ir_instruction_membername_get_dep((IrInstructionMemberName *) instruction, index);
3210 case IrInstructionIdBreakpoint:
3211 return ir_instruction_breakpoint_get_dep((IrInstructionBreakpoint *) instruction, index);
3212 case IrInstructionIdReturnAddress:
3213 return ir_instruction_returnaddress_get_dep((IrInstructionReturnAddress *) instruction, index);
3214 case IrInstructionIdFrameAddress:
3215 return ir_instruction_frameaddress_get_dep((IrInstructionFrameAddress *) instruction, index);
3216 case IrInstructionIdAlignOf:
3217 return ir_instruction_alignof_get_dep((IrInstructionAlignOf *) instruction, index);
3218 case IrInstructionIdOverflowOp:
3219 return ir_instruction_overflowop_get_dep((IrInstructionOverflowOp *) instruction, index);
3220 case IrInstructionIdTestErr:
3221 return ir_instruction_testerr_get_dep((IrInstructionTestErr *) instruction, index);
3222 case IrInstructionIdUnwrapErrCode:
3223 return ir_instruction_unwraperrcode_get_dep((IrInstructionUnwrapErrCode *) instruction, index);
3224 case IrInstructionIdUnwrapErrPayload:
3225 return ir_instruction_unwraperrpayload_get_dep((IrInstructionUnwrapErrPayload *) instruction, index);
3226 case IrInstructionIdErrWrapCode:
3227 return ir_instruction_errwrapcode_get_dep((IrInstructionErrWrapCode *) instruction, index);
3228 case IrInstructionIdErrWrapPayload:
3229 return ir_instruction_errwrappayload_get_dep((IrInstructionErrWrapPayload *) instruction, index);
3230 case IrInstructionIdFnProto:
3231 return ir_instruction_fnproto_get_dep((IrInstructionFnProto *) instruction, index);
3232 case IrInstructionIdTestComptime:
3233 return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index);
3234 case IrInstructionIdPtrCast:
3235 return ir_instruction_ptrcast_get_dep((IrInstructionPtrCast *) instruction, index);
3236 case IrInstructionIdBitCast:
3237 return ir_instruction_bitcast_get_dep((IrInstructionBitCast *) instruction, index);
3238 case IrInstructionIdWidenOrShorten:
3239 return ir_instruction_widenorshorten_get_dep((IrInstructionWidenOrShorten *) instruction, index);
3240 case IrInstructionIdIntToPtr:
3241 return ir_instruction_inttoptr_get_dep((IrInstructionIntToPtr *) instruction, index);
3242 case IrInstructionIdPtrToInt:
3243 return ir_instruction_ptrtoint_get_dep((IrInstructionPtrToInt *) instruction, index);
3244 case IrInstructionIdIntToEnum:
3245 return ir_instruction_inttoenum_get_dep((IrInstructionIntToEnum *) instruction, index);
3246 case IrInstructionIdIntToErr:
3247 return ir_instruction_inttoerr_get_dep((IrInstructionIntToErr *) instruction, index);
3248 case IrInstructionIdErrToInt:
3249 return ir_instruction_errtoint_get_dep((IrInstructionErrToInt *) instruction, index);
3250 case IrInstructionIdCheckSwitchProngs:
3251 return ir_instruction_checkswitchprongs_get_dep((IrInstructionCheckSwitchProngs *) instruction, index);
3252 case IrInstructionIdCheckStatementIsVoid:
3253 return ir_instruction_checkstatementisvoid_get_dep((IrInstructionCheckStatementIsVoid *) instruction, index);
3254 case IrInstructionIdTypeName:
3255 return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index);
3256 case IrInstructionIdCanImplicitCast:
3257 return ir_instruction_canimplicitcast_get_dep((IrInstructionCanImplicitCast *) instruction, index);
3258 case IrInstructionIdDeclRef:
3259 return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index);
3260 case IrInstructionIdPanic:
3261 return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index);
3262 case IrInstructionIdTagName:
3263 return ir_instruction_enumtagname_get_dep((IrInstructionTagName *) instruction, index);
3264 case IrInstructionIdTagType:
3265 return ir_instruction_enumtagtype_get_dep((IrInstructionTagType *) instruction, index);
3266 case IrInstructionIdFieldParentPtr:
3267 return ir_instruction_fieldparentptr_get_dep((IrInstructionFieldParentPtr *) instruction, index);
3268 case IrInstructionIdOffsetOf:
3269 return ir_instruction_offsetof_get_dep((IrInstructionOffsetOf *) instruction, index);
3270 case IrInstructionIdTypeId:
3271 return ir_instruction_typeid_get_dep((IrInstructionTypeId *) instruction, index);
3272 case IrInstructionIdSetEvalBranchQuota:
3273 return ir_instruction_setevalbranchquota_get_dep((IrInstructionSetEvalBranchQuota *) instruction, index);
3274 case IrInstructionIdPtrTypeOf:
3275 return ir_instruction_ptrtypeof_get_dep((IrInstructionPtrTypeOf *) instruction, index);
3276 case IrInstructionIdAlignCast:
3277 return ir_instruction_aligncast_get_dep((IrInstructionAlignCast *) instruction, index);
3278 case IrInstructionIdOpaqueType:
3279 return ir_instruction_opaquetype_get_dep((IrInstructionOpaqueType *) instruction, index);
3280 case IrInstructionIdSetAlignStack:
3281 return ir_instruction_setalignstack_get_dep((IrInstructionSetAlignStack *) instruction, index);
3282 case IrInstructionIdArgType:
3283 return ir_instruction_argtype_get_dep((IrInstructionArgType *) instruction, index);
3284 }
3285 zig_unreachable();
3286}2306}
32872307
3288static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {2308static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
...@@ -3340,6 +2360,11 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {...@@ -3340,6 +2360,11 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
3340 irb->current_basic_block = basic_block;2360 irb->current_basic_block = basic_block;
3341}2361}
33422362
2363static void ir_set_cursor_at_end_and_append_block(IrBuilder *irb, IrBasicBlock *basic_block) {
2364 irb->exec->basic_block_list.append(basic_block);
2365 ir_set_cursor_at_end(irb, basic_block);
2366}
2367
3343static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {2368static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {
3344 while (scope) {2369 while (scope) {
3345 if (scope->id == ScopeIdDeferExpr)2370 if (scope->id == ScopeIdDeferExpr)
...@@ -3388,8 +2413,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3388,8 +2413,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3388 size_t defer_counts[2];2413 size_t defer_counts[2];
3389 ir_count_defers(irb, scope, outer_scope, defer_counts);2414 ir_count_defers(irb, scope, outer_scope, defer_counts);
3390 if (defer_counts[ReturnKindError] > 0) {2415 if (defer_counts[ReturnKindError] > 0) {
3391 IrBasicBlock *err_block = ir_build_basic_block(irb, scope, "ErrRetErr");2416 IrBasicBlock *err_block = ir_create_basic_block(irb, scope, "ErrRetErr");
3392 IrBasicBlock *ok_block = ir_build_basic_block(irb, scope, "ErrRetOk");2417 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk");
33932418
3394 IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);2419 IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);
33952420
...@@ -3402,11 +2427,11 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3402,11 +2427,11 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
34022427
3403 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime));2428 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime));
34042429
3405 ir_set_cursor_at_end(irb, err_block);2430 ir_set_cursor_at_end_and_append_block(irb, err_block);
3406 ir_gen_defers_for_block(irb, scope, outer_scope, true);2431 ir_gen_defers_for_block(irb, scope, outer_scope, true);
3407 ir_build_return(irb, scope, node, return_value);2432 ir_build_return(irb, scope, node, return_value);
34082433
3409 ir_set_cursor_at_end(irb, ok_block);2434 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3410 ir_gen_defers_for_block(irb, scope, outer_scope, false);2435 ir_gen_defers_for_block(irb, scope, outer_scope, false);
3411 return ir_build_return(irb, scope, node, return_value);2436 return ir_build_return(irb, scope, node, return_value);
3412 } else {2437 } else {
...@@ -3424,17 +2449,17 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3424,17 +2449,17 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3424 IrInstruction *err_union_val = ir_build_load_ptr(irb, scope, node, err_union_ptr);2449 IrInstruction *err_union_val = ir_build_load_ptr(irb, scope, node, err_union_ptr);
3425 IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_val);2450 IrInstruction *is_err_val = ir_build_test_err(irb, scope, node, err_union_val);
34262451
3427 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn");2452 IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");
3428 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "ErrRetContinue");2453 IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");
3429 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope));2454 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope));
3430 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));2455 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));
34312456
3432 ir_set_cursor_at_end(irb, return_block);2457 ir_set_cursor_at_end_and_append_block(irb, return_block);
3433 ir_gen_defers_for_block(irb, scope, outer_scope, true);2458 ir_gen_defers_for_block(irb, scope, outer_scope, true);
3434 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);2459 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
3435 ir_build_return(irb, scope, node, err_val);2460 ir_build_return(irb, scope, node, err_val);
34362461
3437 ir_set_cursor_at_end(irb, continue_block);2462 ir_set_cursor_at_end_and_append_block(irb, continue_block);
3438 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);2463 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);
3439 if (lval.is_ptr)2464 if (lval.is_ptr)
3440 return unwrapped_ptr;2465 return unwrapped_ptr;
...@@ -3529,13 +2554,13 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3529,13 +2554,13 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
35292554
3530 if (block_node->data.block.statements.length == 0) {2555 if (block_node->data.block.statements.length == 0) {
3531 // {}2556 // {}
3532 return ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));2557 return ir_build_const_void(irb, child_scope, block_node);
3533 }2558 }
35342559
3535 if (block_node->data.block.name != nullptr) {2560 if (block_node->data.block.name != nullptr) {
3536 scope_block->incoming_blocks = &incoming_blocks;2561 scope_block->incoming_blocks = &incoming_blocks;
3537 scope_block->incoming_values = &incoming_values;2562 scope_block->incoming_values = &incoming_values;
3538 scope_block->end_block = ir_build_basic_block(irb, parent_scope, "BlockEnd");2563 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
3539 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope));2564 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope));
3540 }2565 }
35412566
...@@ -3558,7 +2583,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3558,7 +2583,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3558 // variable declarations start a new scope2583 // variable declarations start a new scope
3559 IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;2584 IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;
3560 child_scope = decl_var_instruction->var->child_scope;2585 child_scope = decl_var_instruction->var->child_scope;
3561 } else if (statement_value != irb->codegen->invalid_instruction) {2586 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {
3562 // this statement's value must be void2587 // this statement's value must be void
3563 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, statement_node, statement_value));2588 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, statement_node, statement_value));
3564 }2589 }
...@@ -3577,7 +2602,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3577,7 +2602,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3577 if (block_node->data.block.name != nullptr) {2602 if (block_node->data.block.name != nullptr) {
3578 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);2603 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
3579 ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));2604 ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));
3580 ir_set_cursor_at_end(irb, scope_block->end_block);2605 ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);
3581 return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);2606 return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
3582 } else {2607 } else {
3583 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);2608 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
...@@ -3635,13 +2660,13 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node...@@ -3635,13 +2660,13 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node
3635 }2660 }
36362661
3637 // block for when val1 == false2662 // block for when val1 == false
3638 IrBasicBlock *false_block = ir_build_basic_block(irb, scope, "BoolOrFalse");2663 IrBasicBlock *false_block = ir_create_basic_block(irb, scope, "BoolOrFalse");
3639 // block for when val1 == true (don't even evaluate the second part)2664 // block for when val1 == true (don't even evaluate the second part)
3640 IrBasicBlock *true_block = ir_build_basic_block(irb, scope, "BoolOrTrue");2665 IrBasicBlock *true_block = ir_create_basic_block(irb, scope, "BoolOrTrue");
36412666
3642 ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime);2667 ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime);
36432668
3644 ir_set_cursor_at_end(irb, false_block);2669 ir_set_cursor_at_end_and_append_block(irb, false_block);
3645 IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);2670 IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
3646 if (val2 == irb->codegen->invalid_instruction)2671 if (val2 == irb->codegen->invalid_instruction)
3647 return irb->codegen->invalid_instruction;2672 return irb->codegen->invalid_instruction;
...@@ -3649,7 +2674,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node...@@ -3649,7 +2674,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node
36492674
3650 ir_build_br(irb, scope, node, true_block, is_comptime);2675 ir_build_br(irb, scope, node, true_block, is_comptime);
36512676
3652 ir_set_cursor_at_end(irb, true_block);2677 ir_set_cursor_at_end_and_append_block(irb, true_block);
36532678
3654 IrInstruction **incoming_values = allocate<IrInstruction *>(2);2679 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
3655 incoming_values[0] = val1;2680 incoming_values[0] = val1;
...@@ -3677,13 +2702,13 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3677,13 +2702,13 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
3677 }2702 }
36782703
3679 // block for when val1 == true2704 // block for when val1 == true
3680 IrBasicBlock *true_block = ir_build_basic_block(irb, scope, "BoolAndTrue");2705 IrBasicBlock *true_block = ir_create_basic_block(irb, scope, "BoolAndTrue");
3681 // block for when val1 == false (don't even evaluate the second part)2706 // block for when val1 == false (don't even evaluate the second part)
3682 IrBasicBlock *false_block = ir_build_basic_block(irb, scope, "BoolAndFalse");2707 IrBasicBlock *false_block = ir_create_basic_block(irb, scope, "BoolAndFalse");
36832708
3684 ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime);2709 ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime);
36852710
3686 ir_set_cursor_at_end(irb, true_block);2711 ir_set_cursor_at_end_and_append_block(irb, true_block);
3687 IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);2712 IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
3688 if (val2 == irb->codegen->invalid_instruction)2713 if (val2 == irb->codegen->invalid_instruction)
3689 return irb->codegen->invalid_instruction;2714 return irb->codegen->invalid_instruction;
...@@ -3691,7 +2716,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3691,7 +2716,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
36912716
3692 ir_build_br(irb, scope, node, false_block, is_comptime);2717 ir_build_br(irb, scope, node, false_block, is_comptime);
36932718
3694 ir_set_cursor_at_end(irb, false_block);2719 ir_set_cursor_at_end_and_append_block(irb, false_block);
36952720
3696 IrInstruction **incoming_values = allocate<IrInstruction *>(2);2721 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
3697 incoming_values[0] = val1;2722 incoming_values[0] = val1;
...@@ -3723,12 +2748,12 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As...@@ -3723,12 +2748,12 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
3723 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null);2748 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null);
3724 }2749 }
37252750
3726 IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "MaybeNonNull");2751 IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "MaybeNonNull");
3727 IrBasicBlock *null_block = ir_build_basic_block(irb, parent_scope, "MaybeNull");2752 IrBasicBlock *null_block = ir_create_basic_block(irb, parent_scope, "MaybeNull");
3728 IrBasicBlock *end_block = ir_build_basic_block(irb, parent_scope, "MaybeEnd");2753 IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "MaybeEnd");
3729 ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);2754 ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);
37302755
3731 ir_set_cursor_at_end(irb, null_block);2756 ir_set_cursor_at_end_and_append_block(irb, null_block);
3732 IrInstruction *null_result = ir_gen_node(irb, op2_node, parent_scope);2757 IrInstruction *null_result = ir_gen_node(irb, op2_node, parent_scope);
3733 if (null_result == irb->codegen->invalid_instruction)2758 if (null_result == irb->codegen->invalid_instruction)
3734 return irb->codegen->invalid_instruction;2759 return irb->codegen->invalid_instruction;
...@@ -3736,13 +2761,13 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As...@@ -3736,13 +2761,13 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
3736 if (!instr_is_unreachable(null_result))2761 if (!instr_is_unreachable(null_result))
3737 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));2762 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
37382763
3739 ir_set_cursor_at_end(irb, ok_block);2764 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3740 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);2765 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);
3741 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);2766 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
3742 IrBasicBlock *after_ok_block = irb->current_basic_block;2767 IrBasicBlock *after_ok_block = irb->current_basic_block;
3743 ir_build_br(irb, parent_scope, node, end_block, is_comptime);2768 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
37442769
3745 ir_set_cursor_at_end(irb, end_block);2770 ir_set_cursor_at_end_and_append_block(irb, end_block);
3746 IrInstruction **incoming_values = allocate<IrInstruction *>(2);2771 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
3747 incoming_values[0] = null_result;2772 incoming_values[0] = null_result;
3748 incoming_values[1] = unwrapped_payload;2773 incoming_values[1] = unwrapped_payload;
...@@ -4748,13 +3773,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4748,13 +3773,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4748 AstNode *then_node = node->data.if_bool_expr.then_block;3773 AstNode *then_node = node->data.if_bool_expr.then_block;
4749 AstNode *else_node = node->data.if_bool_expr.else_node;3774 AstNode *else_node = node->data.if_bool_expr.else_node;
47503775
4751 IrBasicBlock *then_block = ir_build_basic_block(irb, scope, "Then");3776 IrBasicBlock *then_block = ir_create_basic_block(irb, scope, "Then");
4752 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "Else");3777 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "Else");
4753 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "EndIf");3778 IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "EndIf");
47543779
4755 ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_comptime);3780 ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_comptime);
47563781
4757 ir_set_cursor_at_end(irb, then_block);3782 ir_set_cursor_at_end_and_append_block(irb, then_block);
3783
4758 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, scope);3784 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, scope);
4759 if (then_expr_result == irb->codegen->invalid_instruction)3785 if (then_expr_result == irb->codegen->invalid_instruction)
4760 return then_expr_result;3786 return then_expr_result;
...@@ -4762,7 +3788,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4762,7 +3788,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4762 if (!instr_is_unreachable(then_expr_result))3788 if (!instr_is_unreachable(then_expr_result))
4763 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));3789 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
47643790
4765 ir_set_cursor_at_end(irb, else_block);3791 ir_set_cursor_at_end_and_append_block(irb, else_block);
4766 IrInstruction *else_expr_result;3792 IrInstruction *else_expr_result;
4767 if (else_node) {3793 if (else_node) {
4768 else_expr_result = ir_gen_node(irb, else_node, scope);3794 else_expr_result = ir_gen_node(irb, else_node, scope);
...@@ -4775,7 +3801,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4775,7 +3801,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4775 if (!instr_is_unreachable(else_expr_result))3801 if (!instr_is_unreachable(else_expr_result))
4776 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));3802 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
47773803
4778 ir_set_cursor_at_end(irb, endif_block);3804 ir_set_cursor_at_end_and_append_block(irb, endif_block);
4779 IrInstruction **incoming_values = allocate<IrInstruction *>(2);3805 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
4780 incoming_values[0] = then_expr_result;3806 incoming_values[0] = then_expr_result;
4781 incoming_values[1] = else_expr_result;3807 incoming_values[1] = else_expr_result;
...@@ -5044,13 +4070,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5044,13 +4070,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5044 AstNode *continue_expr_node = node->data.while_expr.continue_expr;4070 AstNode *continue_expr_node = node->data.while_expr.continue_expr;
5045 AstNode *else_node = node->data.while_expr.else_node;4071 AstNode *else_node = node->data.while_expr.else_node;
50464072
5047 IrBasicBlock *cond_block = ir_build_basic_block(irb, scope, "WhileCond");4073 IrBasicBlock *cond_block = ir_create_basic_block(irb, scope, "WhileCond");
5048 IrBasicBlock *body_block = ir_build_basic_block(irb, scope, "WhileBody");4074 IrBasicBlock *body_block = ir_create_basic_block(irb, scope, "WhileBody");
5049 IrBasicBlock *continue_block = continue_expr_node ?4075 IrBasicBlock *continue_block = continue_expr_node ?
5050 ir_build_basic_block(irb, scope, "WhileContinue") : cond_block;4076 ir_create_basic_block(irb, scope, "WhileContinue") : cond_block;
5051 IrBasicBlock *end_block = ir_build_basic_block(irb, scope, "WhileEnd");4077 IrBasicBlock *end_block = ir_create_basic_block(irb, scope, "WhileEnd");
5052 IrBasicBlock *else_block = else_node ?4078 IrBasicBlock *else_block = else_node ?
5053 ir_build_basic_block(irb, scope, "WhileElse") : end_block;4079 ir_create_basic_block(irb, scope, "WhileElse") : end_block;
50544080
5055 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,4081 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
5056 ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline);4082 ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline);
...@@ -5059,7 +4085,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5059,7 +4085,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5059 Buf *var_symbol = node->data.while_expr.var_symbol;4085 Buf *var_symbol = node->data.while_expr.var_symbol;
5060 Buf *err_symbol = node->data.while_expr.err_symbol;4086 Buf *err_symbol = node->data.while_expr.err_symbol;
5061 if (err_symbol != nullptr) {4087 if (err_symbol != nullptr) {
5062 ir_set_cursor_at_end(irb, cond_block);4088 ir_set_cursor_at_end_and_append_block(irb, cond_block);
50634089
5064 Scope *payload_scope;4090 Scope *payload_scope;
5065 AstNode *symbol_node = node; // TODO make more accurate4091 AstNode *symbol_node = node; // TODO make more accurate
...@@ -5084,7 +4110,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5084,7 +4110,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5084 else_block, body_block, is_comptime));4110 else_block, body_block, is_comptime));
5085 }4111 }
50864112
5087 ir_set_cursor_at_end(irb, body_block);4113 ir_set_cursor_at_end_and_append_block(irb, body_block);
5088 if (var_symbol) {4114 if (var_symbol) {
5089 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,4115 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,
5090 err_val_ptr, false);4116 err_val_ptr, false);
...@@ -5111,7 +4137,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5111,7 +4137,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5111 ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime));4137 ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime));
51124138
5113 if (continue_expr_node) {4139 if (continue_expr_node) {
5114 ir_set_cursor_at_end(irb, continue_block);4140 ir_set_cursor_at_end_and_append_block(irb, continue_block);
5115 IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, payload_scope);4141 IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, payload_scope);
5116 if (expr_result == irb->codegen->invalid_instruction)4142 if (expr_result == irb->codegen->invalid_instruction)
5117 return expr_result;4143 return expr_result;
...@@ -5121,7 +4147,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5121,7 +4147,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
51214147
5122 IrInstruction *else_result = nullptr;4148 IrInstruction *else_result = nullptr;
5123 if (else_node) {4149 if (else_node) {
5124 ir_set_cursor_at_end(irb, else_block);4150 ir_set_cursor_at_end_and_append_block(irb, else_block);
51254151
5126 // TODO make it an error to write to error variable4152 // TODO make it an error to write to error variable
5127 AstNode *err_symbol_node = else_node; // TODO make more accurate4153 AstNode *err_symbol_node = else_node; // TODO make more accurate
...@@ -5138,7 +4164,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5138,7 +4164,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5138 ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime));4164 ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime));
5139 }4165 }
5140 IrBasicBlock *after_else_block = irb->current_basic_block;4166 IrBasicBlock *after_else_block = irb->current_basic_block;
5141 ir_set_cursor_at_end(irb, end_block);4167 ir_set_cursor_at_end_and_append_block(irb, end_block);
5142 if (else_result) {4168 if (else_result) {
5143 incoming_blocks.append(after_else_block);4169 incoming_blocks.append(after_else_block);
5144 incoming_values.append(else_result);4170 incoming_values.append(else_result);
...@@ -5149,7 +4175,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5149,7 +4175,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
51494175
5150 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);4176 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
5151 } else if (var_symbol != nullptr) {4177 } else if (var_symbol != nullptr) {
5152 ir_set_cursor_at_end(irb, cond_block);4178 ir_set_cursor_at_end_and_append_block(irb, cond_block);
5153 // TODO make it an error to write to payload variable4179 // TODO make it an error to write to payload variable
5154 AstNode *symbol_node = node; // TODO make more accurate4180 AstNode *symbol_node = node; // TODO make more accurate
5155 VariableTableEntry *payload_var = ir_create_var(irb, symbol_node, scope, var_symbol,4181 VariableTableEntry *payload_var = ir_create_var(irb, symbol_node, scope, var_symbol,
...@@ -5167,7 +4193,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5167,7 +4193,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5167 body_block, else_block, is_comptime));4193 body_block, else_block, is_comptime));
5168 }4194 }
51694195
5170 ir_set_cursor_at_end(irb, body_block);4196 ir_set_cursor_at_end_and_append_block(irb, body_block);
5171 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false);4197 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false);
5172 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?4198 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
5173 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);4199 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
...@@ -5191,7 +4217,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5191,7 +4217,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5191 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));4217 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));
51924218
5193 if (continue_expr_node) {4219 if (continue_expr_node) {
5194 ir_set_cursor_at_end(irb, continue_block);4220 ir_set_cursor_at_end_and_append_block(irb, continue_block);
5195 IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, child_scope);4221 IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, child_scope);
5196 if (expr_result == irb->codegen->invalid_instruction)4222 if (expr_result == irb->codegen->invalid_instruction)
5197 return expr_result;4223 return expr_result;
...@@ -5201,7 +4227,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5201,7 +4227,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
52014227
5202 IrInstruction *else_result = nullptr;4228 IrInstruction *else_result = nullptr;
5203 if (else_node) {4229 if (else_node) {
5204 ir_set_cursor_at_end(irb, else_block);4230 ir_set_cursor_at_end_and_append_block(irb, else_block);
52054231
5206 else_result = ir_gen_node(irb, else_node, scope);4232 else_result = ir_gen_node(irb, else_node, scope);
5207 if (else_result == irb->codegen->invalid_instruction)4233 if (else_result == irb->codegen->invalid_instruction)
...@@ -5210,7 +4236,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5210,7 +4236,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5210 ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime));4236 ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime));
5211 }4237 }
5212 IrBasicBlock *after_else_block = irb->current_basic_block;4238 IrBasicBlock *after_else_block = irb->current_basic_block;
5213 ir_set_cursor_at_end(irb, end_block);4239 ir_set_cursor_at_end_and_append_block(irb, end_block);
5214 if (else_result) {4240 if (else_result) {
5215 incoming_blocks.append(after_else_block);4241 incoming_blocks.append(after_else_block);
5216 incoming_values.append(else_result);4242 incoming_values.append(else_result);
...@@ -5221,16 +4247,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5221,16 +4247,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
52214247
5222 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);4248 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
5223 } else {4249 } else {
5224 if (continue_expr_node) {4250 ir_set_cursor_at_end_and_append_block(irb, cond_block);
5225 ir_set_cursor_at_end(irb, continue_block);
5226 IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, scope);
5227 if (expr_result == irb->codegen->invalid_instruction)
5228 return expr_result;
5229 if (!instr_is_unreachable(expr_result))
5230 ir_mark_gen(ir_build_br(irb, scope, node, cond_block, is_comptime));
5231 }
5232
5233 ir_set_cursor_at_end(irb, cond_block);
5234 IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope);4251 IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope);
5235 if (cond_val == irb->codegen->invalid_instruction)4252 if (cond_val == irb->codegen->invalid_instruction)
5236 return cond_val;4253 return cond_val;
...@@ -5241,7 +4258,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5241,7 +4258,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5241 body_block, else_block, is_comptime));4258 body_block, else_block, is_comptime));
5242 }4259 }
52434260
5244 ir_set_cursor_at_end(irb, body_block);4261 ir_set_cursor_at_end_and_append_block(irb, body_block);
52454262
5246 ZigList<IrInstruction *> incoming_values = {0};4263 ZigList<IrInstruction *> incoming_values = {0};
5247 ZigList<IrBasicBlock *> incoming_blocks = {0};4264 ZigList<IrBasicBlock *> incoming_blocks = {0};
...@@ -5260,9 +4277,18 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5260,9 +4277,18 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5260 if (!instr_is_unreachable(body_result))4277 if (!instr_is_unreachable(body_result))
5261 ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime));4278 ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime));
52624279
4280 if (continue_expr_node) {
4281 ir_set_cursor_at_end_and_append_block(irb, continue_block);
4282 IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, scope);
4283 if (expr_result == irb->codegen->invalid_instruction)
4284 return expr_result;
4285 if (!instr_is_unreachable(expr_result))
4286 ir_mark_gen(ir_build_br(irb, scope, node, cond_block, is_comptime));
4287 }
4288
5263 IrInstruction *else_result = nullptr;4289 IrInstruction *else_result = nullptr;
5264 if (else_node) {4290 if (else_node) {
5265 ir_set_cursor_at_end(irb, else_block);4291 ir_set_cursor_at_end_and_append_block(irb, else_block);
52664292
5267 else_result = ir_gen_node(irb, else_node, scope);4293 else_result = ir_gen_node(irb, else_node, scope);
5268 if (else_result == irb->codegen->invalid_instruction)4294 if (else_result == irb->codegen->invalid_instruction)
...@@ -5271,7 +4297,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5271,7 +4297,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5271 ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime));4297 ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime));
5272 }4298 }
5273 IrBasicBlock *after_else_block = irb->current_basic_block;4299 IrBasicBlock *after_else_block = irb->current_basic_block;
5274 ir_set_cursor_at_end(irb, end_block);4300 ir_set_cursor_at_end_and_append_block(irb, end_block);
5275 if (else_result) {4301 if (else_result) {
5276 incoming_blocks.append(after_else_block);4302 incoming_blocks.append(after_else_block);
5277 incoming_values.append(else_result);4303 incoming_values.append(else_result);
...@@ -5344,23 +4370,23 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5344,23 +4370,23 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5344 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var, false, false);4370 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var, false, false);
53454371
53464372
5347 IrBasicBlock *cond_block = ir_build_basic_block(irb, child_scope, "ForCond");4373 IrBasicBlock *cond_block = ir_create_basic_block(irb, child_scope, "ForCond");
5348 IrBasicBlock *body_block = ir_build_basic_block(irb, child_scope, "ForBody");4374 IrBasicBlock *body_block = ir_create_basic_block(irb, child_scope, "ForBody");
5349 IrBasicBlock *end_block = ir_build_basic_block(irb, child_scope, "ForEnd");4375 IrBasicBlock *end_block = ir_create_basic_block(irb, child_scope, "ForEnd");
5350 IrBasicBlock *else_block = else_node ? ir_build_basic_block(irb, child_scope, "ForElse") : end_block;4376 IrBasicBlock *else_block = else_node ? ir_create_basic_block(irb, child_scope, "ForElse") : end_block;
5351 IrBasicBlock *continue_block = ir_build_basic_block(irb, child_scope, "ForContinue");4377 IrBasicBlock *continue_block = ir_create_basic_block(irb, child_scope, "ForContinue");
53524378
5353 IrInstruction *len_val = ir_build_array_len(irb, child_scope, node, array_val);4379 IrInstruction *len_val = ir_build_array_len(irb, child_scope, node, array_val);
5354 ir_build_br(irb, child_scope, node, cond_block, is_comptime);4380 ir_build_br(irb, child_scope, node, cond_block, is_comptime);
53554381
5356 ir_set_cursor_at_end(irb, cond_block);4382 ir_set_cursor_at_end_and_append_block(irb, cond_block);
5357 IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);4383 IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);
5358 IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);4384 IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
5359 IrBasicBlock *after_cond_block = irb->current_basic_block;4385 IrBasicBlock *after_cond_block = irb->current_basic_block;
5360 IrInstruction *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node));4386 IrInstruction *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node));
5361 ir_mark_gen(ir_build_cond_br(irb, child_scope, node, cond, body_block, else_block, is_comptime));4387 ir_mark_gen(ir_build_cond_br(irb, child_scope, node, cond, body_block, else_block, is_comptime));
53624388
5363 ir_set_cursor_at_end(irb, body_block);4389 ir_set_cursor_at_end_and_append_block(irb, body_block);
5364 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false);4390 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false);
5365 IrInstruction *elem_val;4391 IrInstruction *elem_val;
5366 if (node->data.for_expr.elem_is_ptr) {4392 if (node->data.for_expr.elem_is_ptr) {
...@@ -5384,14 +4410,14 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5384,14 +4410,14 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5384 if (!instr_is_unreachable(body_result))4410 if (!instr_is_unreachable(body_result))
5385 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));4411 ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime));
53864412
5387 ir_set_cursor_at_end(irb, continue_block);4413 ir_set_cursor_at_end_and_append_block(irb, continue_block);
5388 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);4414 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);
5389 ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val));4415 ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val));
5390 ir_build_br(irb, child_scope, node, cond_block, is_comptime);4416 ir_build_br(irb, child_scope, node, cond_block, is_comptime);
53914417
5392 IrInstruction *else_result = nullptr;4418 IrInstruction *else_result = nullptr;
5393 if (else_node) {4419 if (else_node) {
5394 ir_set_cursor_at_end(irb, else_block);4420 ir_set_cursor_at_end_and_append_block(irb, else_block);
53954421
5396 else_result = ir_gen_node(irb, else_node, parent_scope);4422 else_result = ir_gen_node(irb, else_node, parent_scope);
5397 if (else_result == irb->codegen->invalid_instruction)4423 if (else_result == irb->codegen->invalid_instruction)
...@@ -5400,7 +4426,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5400,7 +4426,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5400 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));4426 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
5401 }4427 }
5402 IrBasicBlock *after_else_block = irb->current_basic_block;4428 IrBasicBlock *after_else_block = irb->current_basic_block;
5403 ir_set_cursor_at_end(irb, end_block);4429 ir_set_cursor_at_end_and_append_block(irb, end_block);
54044430
5405 if (else_result) {4431 if (else_result) {
5406 incoming_blocks.append(after_else_block);4432 incoming_blocks.append(after_else_block);
...@@ -5577,9 +4603,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no...@@ -5577,9 +4603,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
5577 IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr);4603 IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr);
5578 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_val);4604 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_val);
55794605
5580 IrBasicBlock *then_block = ir_build_basic_block(irb, scope, "MaybeThen");4606 IrBasicBlock *then_block = ir_create_basic_block(irb, scope, "MaybeThen");
5581 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "MaybeElse");4607 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "MaybeElse");
5582 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf");4608 IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "MaybeEndIf");
55834609
5584 IrInstruction *is_comptime;4610 IrInstruction *is_comptime;
5585 if (ir_should_inline(irb->exec, scope)) {4611 if (ir_should_inline(irb->exec, scope)) {
...@@ -5589,7 +4615,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no...@@ -5589,7 +4615,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
5589 }4615 }
5590 ir_build_cond_br(irb, scope, node, is_non_null, then_block, else_block, is_comptime);4616 ir_build_cond_br(irb, scope, node, is_non_null, then_block, else_block, is_comptime);
55914617
5592 ir_set_cursor_at_end(irb, then_block);4618 ir_set_cursor_at_end_and_append_block(irb, then_block);
55934619
5594 Scope *var_scope;4620 Scope *var_scope;
5595 if (var_symbol) {4621 if (var_symbol) {
...@@ -5613,7 +4639,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no...@@ -5613,7 +4639,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
5613 if (!instr_is_unreachable(then_expr_result))4639 if (!instr_is_unreachable(then_expr_result))
5614 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));4640 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
56154641
5616 ir_set_cursor_at_end(irb, else_block);4642 ir_set_cursor_at_end_and_append_block(irb, else_block);
5617 IrInstruction *else_expr_result;4643 IrInstruction *else_expr_result;
5618 if (else_node) {4644 if (else_node) {
5619 else_expr_result = ir_gen_node(irb, else_node, scope);4645 else_expr_result = ir_gen_node(irb, else_node, scope);
...@@ -5626,7 +4652,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no...@@ -5626,7 +4652,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
5626 if (!instr_is_unreachable(else_expr_result))4652 if (!instr_is_unreachable(else_expr_result))
5627 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));4653 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
56284654
5629 ir_set_cursor_at_end(irb, endif_block);4655 ir_set_cursor_at_end_and_append_block(irb, endif_block);
5630 IrInstruction **incoming_values = allocate<IrInstruction *>(2);4656 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
5631 incoming_values[0] = then_expr_result;4657 incoming_values[0] = then_expr_result;
5632 incoming_values[1] = else_expr_result;4658 incoming_values[1] = else_expr_result;
...@@ -5655,9 +4681,9 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5655,9 +4681,9 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod
5655 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);4681 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
5656 IrInstruction *is_err = ir_build_test_err(irb, scope, node, err_val);4682 IrInstruction *is_err = ir_build_test_err(irb, scope, node, err_val);
56574683
5658 IrBasicBlock *ok_block = ir_build_basic_block(irb, scope, "TryOk");4684 IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");
5659 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "TryElse");4685 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");
5660 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "TryEnd");4686 IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "TryEnd");
56614687
5662 IrInstruction *is_comptime;4688 IrInstruction *is_comptime;
5663 if (ir_should_inline(irb->exec, scope)) {4689 if (ir_should_inline(irb->exec, scope)) {
...@@ -5667,7 +4693,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5667,7 +4693,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod
5667 }4693 }
5668 ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);4694 ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);
56694695
5670 ir_set_cursor_at_end(irb, ok_block);4696 ir_set_cursor_at_end_and_append_block(irb, ok_block);
56714697
5672 Scope *var_scope;4698 Scope *var_scope;
5673 if (var_symbol) {4699 if (var_symbol) {
...@@ -5690,7 +4716,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5690,7 +4716,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod
5690 if (!instr_is_unreachable(then_expr_result))4716 if (!instr_is_unreachable(then_expr_result))
5691 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));4717 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
56924718
5693 ir_set_cursor_at_end(irb, else_block);4719 ir_set_cursor_at_end_and_append_block(irb, else_block);
56944720
5695 IrInstruction *else_expr_result;4721 IrInstruction *else_expr_result;
5696 if (else_node) {4722 if (else_node) {
...@@ -5718,7 +4744,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5718,7 +4744,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod
5718 if (!instr_is_unreachable(else_expr_result))4744 if (!instr_is_unreachable(else_expr_result))
5719 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));4745 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
57204746
5721 ir_set_cursor_at_end(irb, endif_block);4747 ir_set_cursor_at_end_and_append_block(irb, endif_block);
5722 IrInstruction **incoming_values = allocate<IrInstruction *>(2);4748 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
5723 incoming_values[0] = then_expr_result;4749 incoming_values[0] = then_expr_result;
5724 incoming_values[1] = else_expr_result;4750 incoming_values[1] = else_expr_result;
...@@ -5781,8 +4807,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5781,8 +4807,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
5781 return target_value_ptr;4807 return target_value_ptr;
5782 IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr);4808 IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr);
57834809
5784 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "SwitchElse");4810 IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "SwitchElse");
5785 IrBasicBlock *end_block = ir_build_basic_block(irb, scope, "SwitchEnd");4811 IrBasicBlock *end_block = ir_create_basic_block(irb, scope, "SwitchEnd");
57864812
5787 size_t prong_count = node->data.switch_expr.prongs.length;4813 size_t prong_count = node->data.switch_expr.prongs.length;
5788 ZigList<IrInstructionSwitchBrCase> cases = {0};4814 ZigList<IrInstructionSwitchBrCase> cases = {0};
...@@ -5798,6 +4824,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5798,6 +4824,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
5798 ZigList<IrBasicBlock *> incoming_blocks = {0};4824 ZigList<IrBasicBlock *> incoming_blocks = {0};
5799 ZigList<IrInstructionCheckSwitchProngsRange> check_ranges = {0};4825 ZigList<IrInstructionCheckSwitchProngsRange> check_ranges = {0};
58004826
4827 // First do the else and the ranges
5801 Scope *comptime_scope = create_comptime_scope(node, scope);4828 Scope *comptime_scope = create_comptime_scope(node, scope);
5802 AstNode *else_prong = nullptr;4829 AstNode *else_prong = nullptr;
5803 for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {4830 for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
...@@ -5814,90 +4841,47 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5814,90 +4841,47 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
5814 else_prong = prong_node;4841 else_prong = prong_node;
58154842
5816 IrBasicBlock *prev_block = irb->current_basic_block;4843 IrBasicBlock *prev_block = irb->current_basic_block;
5817 ir_set_cursor_at_end(irb, else_block);4844 ir_set_cursor_at_end_and_append_block(irb, else_block);
5818 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,4845 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
5819 is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))4846 is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
5820 {4847 {
5821 return irb->codegen->invalid_instruction;4848 return irb->codegen->invalid_instruction;
5822 }4849 }
5823 ir_set_cursor_at_end(irb, prev_block);4850 ir_set_cursor_at_end(irb, prev_block);
5824 } else {4851 } else if (prong_node->data.switch_prong.any_items_are_range) {
5825 if (prong_node->data.switch_prong.any_items_are_range) {4852 IrInstruction *ok_bit = nullptr;
5826 IrInstruction *ok_bit = nullptr;4853 AstNode *last_item_node = nullptr;
5827 AstNode *last_item_node = nullptr;4854 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
5828 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {4855 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
5829 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);4856 last_item_node = item_node;
5830 last_item_node = item_node;4857 if (item_node->type == NodeTypeSwitchRange) {
5831 if (item_node->type == NodeTypeSwitchRange) {4858 AstNode *start_node = item_node->data.switch_range.start;
5832 AstNode *start_node = item_node->data.switch_range.start;4859 AstNode *end_node = item_node->data.switch_range.end;
5833 AstNode *end_node = item_node->data.switch_range.end;4860
58344861 IrInstruction *start_value = ir_gen_node(irb, start_node, comptime_scope);
5835 IrInstruction *start_value = ir_gen_node(irb, start_node, comptime_scope);4862 if (start_value == irb->codegen->invalid_instruction)
5836 if (start_value == irb->codegen->invalid_instruction)4863 return irb->codegen->invalid_instruction;
5837 return irb->codegen->invalid_instruction;
5838
5839 IrInstruction *end_value = ir_gen_node(irb, end_node, comptime_scope);
5840 if (end_value == irb->codegen->invalid_instruction)
5841 return irb->codegen->invalid_instruction;
5842
5843 IrInstructionCheckSwitchProngsRange *check_range = check_ranges.add_one();
5844 check_range->start = start_value;
5845 check_range->end = end_value;
5846
5847 IrInstruction *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq,
5848 target_value, start_value, false);
5849 IrInstruction *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq,
5850 target_value, end_value, false);
5851 IrInstruction *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd,
5852 lower_range_ok, upper_range_ok, false);
5853 if (ok_bit) {
5854 ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false);
5855 } else {
5856 ok_bit = both_ok;
5857 }
5858 } else {
5859 IrInstruction *item_value = ir_gen_node(irb, item_node, comptime_scope);
5860 if (item_value == irb->codegen->invalid_instruction)
5861 return irb->codegen->invalid_instruction;
5862
5863 IrInstructionCheckSwitchProngsRange *check_range = check_ranges.add_one();
5864 check_range->start = item_value;
5865 check_range->end = item_value;
5866
5867 IrInstruction *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq,
5868 item_value, target_value, false);
5869 if (ok_bit) {
5870 ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false);
5871 } else {
5872 ok_bit = cmp_ok;
5873 }
5874 }
5875 }
5876
5877 IrBasicBlock *range_block_yes = ir_build_basic_block(irb, scope, "SwitchRangeYes");
5878 IrBasicBlock *range_block_no = ir_build_basic_block(irb, scope, "SwitchRangeNo");
5879
5880 assert(ok_bit);
5881 assert(last_item_node);
5882 ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes,
5883 range_block_no, is_comptime));
5884
5885 ir_set_cursor_at_end(irb, range_block_yes);
5886 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
5887 is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
5888 {
5889 return irb->codegen->invalid_instruction;
5890 }
5891
5892 ir_set_cursor_at_end(irb, range_block_no);
5893 } else {
5894 IrBasicBlock *prong_block = ir_build_basic_block(irb, scope, "SwitchProng");
5895 IrInstruction *last_item_value = nullptr;
58964864
5897 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {4865 IrInstruction *end_value = ir_gen_node(irb, end_node, comptime_scope);
5898 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);4866 if (end_value == irb->codegen->invalid_instruction)
5899 assert(item_node->type != NodeTypeSwitchRange);4867 return irb->codegen->invalid_instruction;
59004868
4869 IrInstructionCheckSwitchProngsRange *check_range = check_ranges.add_one();
4870 check_range->start = start_value;
4871 check_range->end = end_value;
4872
4873 IrInstruction *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq,
4874 target_value, start_value, false);
4875 IrInstruction *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq,
4876 target_value, end_value, false);
4877 IrInstruction *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd,
4878 lower_range_ok, upper_range_ok, false);
4879 if (ok_bit) {
4880 ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false);
4881 } else {
4882 ok_bit = both_ok;
4883 }
4884 } else {
5901 IrInstruction *item_value = ir_gen_node(irb, item_node, comptime_scope);4885 IrInstruction *item_value = ir_gen_node(irb, item_node, comptime_scope);
5902 if (item_value == irb->codegen->invalid_instruction)4886 if (item_value == irb->codegen->invalid_instruction)
5903 return irb->codegen->invalid_instruction;4887 return irb->codegen->invalid_instruction;
...@@ -5906,26 +4890,77 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5906,26 +4890,77 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
5906 check_range->start = item_value;4890 check_range->start = item_value;
5907 check_range->end = item_value;4891 check_range->end = item_value;
59084892
5909 IrInstructionSwitchBrCase *this_case = cases.add_one();4893 IrInstruction *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq,
5910 this_case->value = item_value;4894 item_value, target_value, false);
5911 this_case->block = prong_block;4895 if (ok_bit) {
59124896 ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false);
5913 last_item_value = item_value;4897 } else {
4898 ok_bit = cmp_ok;
4899 }
5914 }4900 }
5915 IrInstruction *only_item_value = (prong_item_count == 1) ? last_item_value : nullptr;4901 }
59164902
5917 IrBasicBlock *prev_block = irb->current_basic_block;4903 IrBasicBlock *range_block_yes = ir_create_basic_block(irb, scope, "SwitchRangeYes");
5918 ir_set_cursor_at_end(irb, prong_block);4904 IrBasicBlock *range_block_no = ir_create_basic_block(irb, scope, "SwitchRangeNo");
5919 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
5920 is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values))
5921 {
5922 return irb->codegen->invalid_instruction;
5923 }
59244905
5925 ir_set_cursor_at_end(irb, prev_block);4906 assert(ok_bit);
4907 assert(last_item_node);
4908 ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes,
4909 range_block_no, is_comptime));
59264910
4911 ir_set_cursor_at_end_and_append_block(irb, range_block_yes);
4912 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
4913 is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
4914 {
4915 return irb->codegen->invalid_instruction;
5927 }4916 }
4917
4918 ir_set_cursor_at_end_and_append_block(irb, range_block_no);
4919 }
4920 }
4921
4922 // next do the non-else non-ranges
4923 for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
4924 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
4925 size_t prong_item_count = prong_node->data.switch_prong.items.length;
4926 if (prong_item_count == 0)
4927 continue;
4928 if (prong_node->data.switch_prong.any_items_are_range)
4929 continue;
4930
4931 IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng");
4932 IrInstruction *last_item_value = nullptr;
4933
4934 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
4935 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
4936 assert(item_node->type != NodeTypeSwitchRange);
4937
4938 IrInstruction *item_value = ir_gen_node(irb, item_node, comptime_scope);
4939 if (item_value == irb->codegen->invalid_instruction)
4940 return irb->codegen->invalid_instruction;
4941
4942 IrInstructionCheckSwitchProngsRange *check_range = check_ranges.add_one();
4943 check_range->start = item_value;
4944 check_range->end = item_value;
4945
4946 IrInstructionSwitchBrCase *this_case = cases.add_one();
4947 this_case->value = item_value;
4948 this_case->block = prong_block;
4949
4950 last_item_value = item_value;
4951 }
4952 IrInstruction *only_item_value = (prong_item_count == 1) ? last_item_value : nullptr;
4953
4954 IrBasicBlock *prev_block = irb->current_basic_block;
4955 ir_set_cursor_at_end_and_append_block(irb, prong_block);
4956 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
4957 is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values))
4958 {
4959 return irb->codegen->invalid_instruction;
5928 }4960 }
4961
4962 ir_set_cursor_at_end(irb, prev_block);
4963
5929 }4964 }
59304965
5931 ir_build_check_switch_prongs(irb, scope, node, target_value, check_ranges.items, check_ranges.length,4966 ir_build_check_switch_prongs(irb, scope, node, target_value, check_ranges.items, check_ranges.length,
...@@ -5938,11 +4973,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5938,11 +4973,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
5938 }4973 }
59394974
5940 if (!else_prong) {4975 if (!else_prong) {
5941 ir_set_cursor_at_end(irb, else_block);4976 ir_set_cursor_at_end_and_append_block(irb, else_block);
5942 ir_build_unreachable(irb, scope, node);4977 ir_build_unreachable(irb, scope, node);
5943 }4978 }
59444979
5945 ir_set_cursor_at_end(irb, end_block);4980 ir_set_cursor_at_end_and_append_block(irb, end_block);
5946 assert(incoming_blocks.length == incoming_values.length);4981 assert(incoming_blocks.length == incoming_values.length);
5947 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);4982 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
5948}4983}
...@@ -6158,12 +5193,12 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -6158,12 +5193,12 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
6158 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err);5193 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err);
6159 }5194 }
61605195
6161 IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrOk");5196 IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk");
6162 IrBasicBlock *err_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrError");5197 IrBasicBlock *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError");
6163 IrBasicBlock *end_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrEnd");5198 IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd");
6164 ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime);5199 ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime);
61655200
6166 ir_set_cursor_at_end(irb, err_block);5201 ir_set_cursor_at_end_and_append_block(irb, err_block);
6167 Scope *err_scope;5202 Scope *err_scope;
6168 if (var_node) {5203 if (var_node) {
6169 assert(var_node->type == NodeTypeSymbol);5204 assert(var_node->type == NodeTypeSymbol);
...@@ -6187,13 +5222,13 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -6187,13 +5222,13 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
6187 if (!instr_is_unreachable(err_result))5222 if (!instr_is_unreachable(err_result))
6188 ir_mark_gen(ir_build_br(irb, err_scope, node, end_block, is_comptime));5223 ir_mark_gen(ir_build_br(irb, err_scope, node, end_block, is_comptime));
61895224
6190 ir_set_cursor_at_end(irb, ok_block);5225 ir_set_cursor_at_end_and_append_block(irb, ok_block);
6191 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false);5226 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false);
6192 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);5227 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
6193 IrBasicBlock *after_ok_block = irb->current_basic_block;5228 IrBasicBlock *after_ok_block = irb->current_basic_block;
6194 ir_build_br(irb, parent_scope, node, end_block, is_comptime);5229 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
61955230
6196 ir_set_cursor_at_end(irb, end_block);5231 ir_set_cursor_at_end_and_append_block(irb, end_block);
6197 IrInstruction **incoming_values = allocate<IrInstruction *>(2);5232 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
6198 incoming_values[0] = err_result;5233 incoming_values[0] = err_result;
6199 incoming_values[1] = unwrapped_payload;5234 incoming_values[1] = unwrapped_payload;
...@@ -6437,7 +5472,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6437,7 +5472,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6437 irb->codegen = codegen;5472 irb->codegen = codegen;
6438 irb->exec = ir_executable;5473 irb->exec = ir_executable;
64395474
6440 irb->current_basic_block = ir_build_basic_block(irb, scope, "Entry");5475 IrBasicBlock *entry_block = ir_create_basic_block(irb, scope, "Entry");
5476 ir_set_cursor_at_end_and_append_block(irb, entry_block);
6441 // Entry block gets a reference because we enter it to begin.5477 // Entry block gets a reference because we enter it to begin.
6442 ir_ref_bb(irb->current_basic_block);5478 ir_ref_bb(irb->current_basic_block);
64435479
...@@ -7332,6 +6368,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,...@@ -7332,6 +6368,7 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
7332 }6368 }
7333 }6369 }
73346370
6371
7335 // implicit number literal to typed number6372 // implicit number literal to typed number
7336 // implicit number literal to &const integer6373 // implicit number literal to &const integer
7337 if (actual_type->id == TypeTableEntryIdNumLitFloat ||6374 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
...@@ -7786,32 +6823,14 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstr...@@ -7786,32 +6823,14 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstr
7786 assert(old_bb);6823 assert(old_bb);
77876824
7788 if (old_bb->other) {6825 if (old_bb->other) {
7789 if (ref_old_instruction == nullptr || old_bb->other->ref_instruction != ref_old_instruction)6826 if (ref_old_instruction == nullptr || old_bb->other->ref_instruction != ref_old_instruction) {
7790 return old_bb->other;6827 return old_bb->other;
6828 }
7791 }6829 }
77926830
7793 IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb);6831 IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb);
7794 new_bb->ref_instruction = ref_old_instruction;6832 new_bb->ref_instruction = ref_old_instruction;
77956833
7796 // We are about to enqueue old_bb for analysis. Before we do so, look over old_bb's
7797 // instructions and make sure we have enqueued first the blocks which contain
7798 // instructions old_bb depends on.
7799 for (size_t instr_i = 0; instr_i < old_bb->instruction_list.length; instr_i += 1) {
7800 IrInstruction *instruction = old_bb->instruction_list.at(instr_i);
7801
7802 for (size_t dep_i = 0; ; dep_i += 1) {
7803 IrInstruction *dep_instruction = ir_instruction_get_dep(instruction, dep_i);
7804 if (dep_instruction == nullptr)
7805 break;
7806 if (dep_instruction->other)
7807 continue;
7808 if (dep_instruction->owner_bb == old_bb)
7809 continue;
7810 ir_get_new_bb(ira, dep_instruction->owner_bb, nullptr);
7811 }
7812 }
7813 ira->old_bb_queue.append(old_bb);
7814
7815 return new_bb;6834 return new_bb;
7816}6835}
78176836
...@@ -7819,12 +6838,10 @@ static void ir_start_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrBasicBlock *cons...@@ -7819,12 +6838,10 @@ static void ir_start_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrBasicBlock *cons
7819 ira->instruction_index = 0;6838 ira->instruction_index = 0;
7820 ira->old_irb.current_basic_block = old_bb;6839 ira->old_irb.current_basic_block = old_bb;
7821 ira->const_predecessor_bb = const_predecessor_bb;6840 ira->const_predecessor_bb = const_predecessor_bb;
7822
7823 if (!const_predecessor_bb && old_bb->other)
7824 ira->new_irb.exec->basic_block_list.append(old_bb->other);
7825}6841}
78266842
7827static void ir_finish_bb(IrAnalyze *ira) {6843static void ir_finish_bb(IrAnalyze *ira) {
6844 ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
7828 ira->instruction_index += 1;6845 ira->instruction_index += 1;
7829 while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {6846 while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) {
7830 IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);6847 IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
...@@ -7835,19 +6852,35 @@ static void ir_finish_bb(IrAnalyze *ira) {...@@ -7835,19 +6852,35 @@ static void ir_finish_bb(IrAnalyze *ira) {
7835 ira->instruction_index += 1;6852 ira->instruction_index += 1;
7836 }6853 }
78376854
7838 ira->block_queue_index += 1;6855 ira->old_bb_index += 1;
78396856
7840 if (ira->block_queue_index < ira->old_bb_queue.length) {6857 bool need_repeat = true;
7841 IrBasicBlock *old_bb = ira->old_bb_queue.at(ira->block_queue_index);6858 for (;;) {
7842 assert(old_bb->other);6859 while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) {
7843 ira->new_irb.current_basic_block = old_bb->other;6860 IrBasicBlock *old_bb = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index);
6861 if (old_bb->other == nullptr) {
6862 ira->old_bb_index += 1;
6863 continue;
6864 }
6865 if (old_bb->other->instruction_list.length != 0) {
6866 ira->old_bb_index += 1;
6867 continue;
6868 }
6869 ira->new_irb.current_basic_block = old_bb->other;
78446870
7845 ir_start_bb(ira, old_bb, nullptr);6871 ir_start_bb(ira, old_bb, nullptr);
6872 return;
6873 }
6874 if (!need_repeat)
6875 return;
6876 need_repeat = false;
6877 ira->old_bb_index = 0;
6878 continue;
7846 }6879 }
7847}6880}
78486881
7849static TypeTableEntry *ir_unreach_error(IrAnalyze *ira) {6882static TypeTableEntry *ir_unreach_error(IrAnalyze *ira) {
7850 ira->block_queue_index = SIZE_MAX;6883 ira->old_bb_index = SIZE_MAX;
7851 ira->new_irb.exec->invalid = true;6884 ira->new_irb.exec->invalid = true;
7852 return ira->codegen->builtin_types.entry_unreachable;6885 return ira->codegen->builtin_types.entry_unreachable;
7853}6886}
...@@ -10639,6 +9672,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -10639,6 +9672,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
10639static VariableTableEntry *get_fn_var_by_index(FnTableEntry *fn_entry, size_t index) {9672static VariableTableEntry *get_fn_var_by_index(FnTableEntry *fn_entry, size_t index) {
10640 size_t next_var_i = 0;9673 size_t next_var_i = 0;
10641 FnGenParamInfo *gen_param_info = fn_entry->type_entry->data.fn.gen_param_info;9674 FnGenParamInfo *gen_param_info = fn_entry->type_entry->data.fn.gen_param_info;
9675 assert(gen_param_info != nullptr);
10642 for (size_t param_i = 0; param_i < index; param_i += 1) {9676 for (size_t param_i = 0; param_i < index; param_i += 1) {
10643 FnGenParamInfo *info = &gen_param_info[param_i];9677 FnGenParamInfo *info = &gen_param_info[param_i];
10644 if (info->gen_index == SIZE_MAX)9678 if (info->gen_index == SIZE_MAX)
...@@ -11442,7 +10476,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -11442,7 +10476,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
11442 IrInstruction *old_value = phi_instruction->incoming_values[i];10476 IrInstruction *old_value = phi_instruction->incoming_values[i];
11443 assert(old_value);10477 assert(old_value);
11444 IrInstruction *new_value = old_value->other;10478 IrInstruction *new_value = old_value->other;
11445 if (!new_value || new_value->value.type->id == TypeTableEntryIdUnreachable)10479 if (!new_value || new_value->value.type->id == TypeTableEntryIdUnreachable || predecessor->other == nullptr)
11446 continue;10480 continue;
1144710481
11448 if (type_is_invalid(new_value->value.type))10482 if (type_is_invalid(new_value->value.type))
...@@ -16312,11 +15346,11 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl...@@ -16312,11 +15346,11 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
16312 IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr);15346 IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr);
16313 ir_ref_bb(new_entry_bb);15347 ir_ref_bb(new_entry_bb);
16314 ira->new_irb.current_basic_block = new_entry_bb;15348 ira->new_irb.current_basic_block = new_entry_bb;
16315 ira->block_queue_index = 0;15349 ira->old_bb_index = 0;
1631615350
16317 ir_start_bb(ira, old_entry_bb, nullptr);15351 ir_start_bb(ira, old_entry_bb, nullptr);
1631815352
16319 while (ira->block_queue_index < ira->old_bb_queue.length) {15353 while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) {
16320 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);15354 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
1632115355
16322 if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) {15356 if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) {
...@@ -16326,7 +15360,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl...@@ -16326,7 +15360,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
1632615360
16327 TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction);15361 TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction);
16328 if (type_is_invalid(return_type) && ir_should_inline(new_exec, old_instruction->scope)) {15362 if (type_is_invalid(return_type) && ir_should_inline(new_exec, old_instruction->scope)) {
16329 break;15363 return ira->codegen->builtin_types.entry_invalid;
16330 }15364 }
1633115365
16332 // unreachable instructions do their own control flow.15366 // unreachable instructions do their own control flow.
std/fmt/index.zig+102-1
...@@ -14,6 +14,8 @@ const State = enum { // TODO put inside format function and make sure the name a...@@ -14,6 +14,8 @@ const State = enum { // TODO put inside format function and make sure the name a
14 CloseBrace,14 CloseBrace,
15 Integer,15 Integer,
16 IntegerWidth,16 IntegerWidth,
17 Float,
18 FloatWidth,
17 Character,19 Character,
18 Buf,20 Buf,
19 BufWidth,21 BufWidth,
...@@ -37,7 +39,6 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void,...@@ -37,7 +39,6 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void,
37 switch (state) {39 switch (state) {
38 State.Start => switch (c) {40 State.Start => switch (c) {
39 '{' => {41 '{' => {
40 // TODO if you make this an if statement with `and` then it breaks
41 if (start_index < i) {42 if (start_index < i) {
42 %return output(context, fmt[start_index..i]);43 %return output(context, fmt[start_index..i]);
43 }44 }
...@@ -85,6 +86,8 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void,...@@ -85,6 +86,8 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void,
85 },86 },
86 's' => {87 's' => {
87 state = State.Buf;88 state = State.Buf;
89 },'.' => {
90 state = State.Float;
88 },91 },
89 else => @compileError("Unknown format character: " ++ []u8{c}),92 else => @compileError("Unknown format character: " ++ []u8{c}),
90 },93 },
...@@ -129,6 +132,30 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void,...@@ -129,6 +132,30 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void,
129 '0' ... '9' => {},132 '0' ... '9' => {},
130 else => @compileError("Unexpected character in format string: " ++ []u8{c}),133 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
131 },134 },
135 State.Float => switch (c) {
136 '}' => {
137 %return formatFloatDecimal(args[next_arg], 0, context, output);
138 next_arg += 1;
139 state = State.Start;
140 start_index = i + 1;
141 },
142 '0' ... '9' => {
143 width_start = i;
144 state = State.FloatWidth;
145 },
146 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
147 },
148 State.FloatWidth => switch (c) {
149 '}' => {
150 width = comptime %%parseUnsigned(usize, fmt[width_start..i], 10);
151 %return formatFloatDecimal(args[next_arg], width, context, output);
152 next_arg += 1;
153 state = State.Start;
154 start_index = i + 1;
155 },
156 '0' ... '9' => {},
157 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
158 },
132 State.BufWidth => switch (c) {159 State.BufWidth => switch (c) {
133 '}' => {160 '}' => {
134 width = comptime %%parseUnsigned(usize, fmt[width_start..i], 10);161 width = comptime %%parseUnsigned(usize, fmt[width_start..i], 10);
...@@ -267,6 +294,47 @@ pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []cons...@@ -267,6 +294,47 @@ pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []cons
267 }294 }
268}295}
269296
297pub fn formatFloatDecimal(value: var, precision: usize, context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void {
298 var x = f64(value);
299
300 // Errol doesn't handle these special cases.
301 if (math.isNan(x)) {
302 return output(context, "NaN");
303 }
304 if (math.signbit(x)) {
305 %return output(context, "-");
306 x = -x;
307 }
308 if (math.isPositiveInf(x)) {
309 return output(context, "Infinity");
310 }
311 if (x == 0.0) {
312 return output(context, "0.0");
313 }
314
315 var buffer: [32]u8 = undefined;
316 const float_decimal = errol3(x, buffer[0..]);
317
318 const num_left_digits = if (float_decimal.exp > 0) usize(float_decimal.exp) else 1;
319
320 %return output(context, float_decimal.digits[0 .. num_left_digits]);
321 %return output(context, ".");
322 if (float_decimal.digits.len > 1) {
323 const num_valid_digtis = if (@typeOf(value) == f32) math.min(usize(7), float_decimal.digits.len)
324 else
325 float_decimal.digits.len;
326
327 const num_right_digits = if (precision != 0)
328 math.min(precision, (num_valid_digtis-num_left_digits))
329 else
330 num_valid_digtis - num_left_digits;
331 %return output(context, float_decimal.digits[num_left_digits .. (num_left_digits + num_right_digits)]);
332 } else {
333 %return output(context, "0");
334 }
335}
336
337
270pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,338pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
271 context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void339 context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void
272{340{
...@@ -540,6 +608,39 @@ test "fmt.format" {...@@ -540,6 +608,39 @@ test "fmt.format" {
540 const result = %%bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64);608 const result = %%bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64);
541 assert(mem.eql(u8, result, "f64: -Infinity\n"));609 assert(mem.eql(u8, result, "f64: -Infinity\n"));
542 }610 }
611 {
612 var buf1: [32]u8 = undefined;
613 const value: f32 = 1.1234;
614 const result = %%bufPrint(buf1[0..], "f32: {.1}\n", value);
615 assert(mem.eql(u8, result, "f32: 1.1\n"));
616 }
617 {
618 var buf1: [32]u8 = undefined;
619 const value: f32 = 1234.567;
620 const result = %%bufPrint(buf1[0..], "f32: {.2}\n", value);
621 assert(mem.eql(u8, result, "f32: 1234.56\n"));
622 }
623 {
624 var buf1: [32]u8 = undefined;
625 const value: f32 = -11.1234;
626 const result = %%bufPrint(buf1[0..], "f32: {.4}\n", value);
627 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
628 // -11.12339... is truncated to -11.1233
629 assert(mem.eql(u8, result, "f32: -11.1233\n"));
630 }
631 {
632 var buf1: [32]u8 = undefined;
633 const value: f32 = 91.12345;
634 const result = %%bufPrint(buf1[0..], "f32: {.}\n", value);
635 assert(mem.eql(u8, result, "f32: 91.12345\n"));
636 }
637 {
638 var buf1: [32]u8 = undefined;
639 const value: f64 = 91.12345678901235;
640 const result = %%bufPrint(buf1[0..], "f64: {.10}\n", value);
641 assert(mem.eql(u8, result, "f64: 91.1234567890\n"));
642 }
643
543 }644 }
544}645}
545646
std/index.zig+2
...@@ -25,6 +25,7 @@ pub const net = @import("net.zig");...@@ -25,6 +25,7 @@ pub const net = @import("net.zig");
25pub const os = @import("os/index.zig");25pub const os = @import("os/index.zig");
26pub const rand = @import("rand.zig");26pub const rand = @import("rand.zig");
27pub const sort = @import("sort.zig");27pub const sort = @import("sort.zig");
28pub const unicode = @import("unicode.zig");
2829
29test "std" {30test "std" {
30 // run tests from these31 // run tests from these
...@@ -53,4 +54,5 @@ test "std" {...@@ -53,4 +54,5 @@ test "std" {
53 _ = @import("os/index.zig");54 _ = @import("os/index.zig");
54 _ = @import("rand.zig");55 _ = @import("rand.zig");
55 _ = @import("sort.zig");56 _ = @import("sort.zig");
57 _ = @import("unicode.zig");
56}58}
std/io.zig+6-1
...@@ -500,11 +500,16 @@ pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator)...@@ -500,11 +500,16 @@ pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator)
500500
501/// On success, caller owns returned buffer.501/// On success, caller owns returned buffer.
502pub fn readFileAlloc(path: []const u8, allocator: &mem.Allocator) -> %[]u8 {502pub fn readFileAlloc(path: []const u8, allocator: &mem.Allocator) -> %[]u8 {
503 return readFileAllocExtra(path, allocator, 0);
504}
505/// On success, caller owns returned buffer.
506/// Allocates extra_len extra bytes at the end of the file buffer, which are uninitialized.
507pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len: usize) -> %[]u8 {
503 var file = %return File.openRead(path, allocator);508 var file = %return File.openRead(path, allocator);
504 defer file.close();509 defer file.close();
505510
506 const size = %return file.getEndPos();511 const size = %return file.getEndPos();
507 const buf = %return allocator.alloc(u8, size);512 const buf = %return allocator.alloc(u8, size + extra_len);
508 %defer allocator.free(buf);513 %defer allocator.free(buf);
509514
510 var adapter = FileInStream.init(&file);515 var adapter = FileInStream.init(&file);
std/math/acos.zig+1-1
...@@ -39,7 +39,7 @@ fn acos32(x: f32) -> f32 {...@@ -39,7 +39,7 @@ fn acos32(x: f32) -> f32 {
39 if (hx >> 31 != 0) {39 if (hx >> 31 != 0) {
40 return 2.0 * pio2_hi + 0x1.0p-120;40 return 2.0 * pio2_hi + 0x1.0p-120;
41 } else {41 } else {
42 return 0;42 return 0.0;
43 }43 }
44 } else {44 } else {
45 return math.nan(f32);45 return math.nan(f32);
std/unicode.zig created+169
...@@ -0,0 +1,169 @@
1const std = @import("./index.zig");
2
3error Utf8InvalidStartByte;
4
5/// Given the first byte of a UTF-8 codepoint,
6/// returns a number 1-4 indicating the total length of the codepoint in bytes.
7/// If this byte does not match the form of a UTF-8 start byte, returns Utf8InvalidStartByte.
8pub fn utf8ByteSequenceLength(first_byte: u8) -> %u3 {
9 if (first_byte < 0b10000000) return u3(1);
10 if (first_byte & 0b11100000 == 0b11000000) return u3(2);
11 if (first_byte & 0b11110000 == 0b11100000) return u3(3);
12 if (first_byte & 0b11111000 == 0b11110000) return u3(4);
13 return error.Utf8InvalidStartByte;
14}
15
16error Utf8OverlongEncoding;
17error Utf8ExpectedContinuation;
18error Utf8EncodesSurrogateHalf;
19error Utf8CodepointTooLarge;
20
21/// Decodes the UTF-8 codepoint encoded in the given slice of bytes.
22/// bytes.len must be equal to %%utf8ByteSequenceLength(bytes[0]).
23/// If you already know the length at comptime, you can call one of
24/// utf8Decode2,utf8Decode3,utf8Decode4 directly instead of this function.
25pub fn utf8Decode(bytes: []const u8) -> %u32 {
26 return switch (bytes.len) {
27 1 => u32(bytes[0]),
28 2 => utf8Decode2(bytes),
29 3 => utf8Decode3(bytes),
30 4 => utf8Decode4(bytes),
31 else => unreachable,
32 };
33}
34pub fn utf8Decode2(bytes: []const u8) -> %u32 {
35 std.debug.assert(bytes.len == 2);
36 std.debug.assert(bytes[0] & 0b11100000 == 0b11000000);
37 var value: u32 = bytes[0] & 0b00011111;
38
39 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
40 value <<= 6;
41 value |= bytes[1] & 0b00111111;
42
43 if (value < 0x80) return error.Utf8OverlongEncoding;
44
45 return value;
46}
47pub fn utf8Decode3(bytes: []const u8) -> %u32 {
48 std.debug.assert(bytes.len == 3);
49 std.debug.assert(bytes[0] & 0b11110000 == 0b11100000);
50 var value: u32 = bytes[0] & 0b00001111;
51
52 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
53 value <<= 6;
54 value |= bytes[1] & 0b00111111;
55
56 if (bytes[2] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
57 value <<= 6;
58 value |= bytes[2] & 0b00111111;
59
60 if (value < 0x800) return error.Utf8OverlongEncoding;
61 if (0xd800 <= value and value <= 0xdfff) return error.Utf8EncodesSurrogateHalf;
62
63 return value;
64}
65pub fn utf8Decode4(bytes: []const u8) -> %u32 {
66 std.debug.assert(bytes.len == 4);
67 std.debug.assert(bytes[0] & 0b11111000 == 0b11110000);
68 var value: u32 = bytes[0] & 0b00000111;
69
70 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
71 value <<= 6;
72 value |= bytes[1] & 0b00111111;
73
74 if (bytes[2] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
75 value <<= 6;
76 value |= bytes[2] & 0b00111111;
77
78 if (bytes[3] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
79 value <<= 6;
80 value |= bytes[3] & 0b00111111;
81
82 if (value < 0x10000) return error.Utf8OverlongEncoding;
83 if (value > 0x10FFFF) return error.Utf8CodepointTooLarge;
84
85 return value;
86}
87
88error UnexpectedEof;
89test "valid utf8" {
90 testValid("\x00", 0x0);
91 testValid("\x20", 0x20);
92 testValid("\x7f", 0x7f);
93 testValid("\xc2\x80", 0x80);
94 testValid("\xdf\xbf", 0x7ff);
95 testValid("\xe0\xa0\x80", 0x800);
96 testValid("\xe1\x80\x80", 0x1000);
97 testValid("\xef\xbf\xbf", 0xffff);
98 testValid("\xf0\x90\x80\x80", 0x10000);
99 testValid("\xf1\x80\x80\x80", 0x40000);
100 testValid("\xf3\xbf\xbf\xbf", 0xfffff);
101 testValid("\xf4\x8f\xbf\xbf", 0x10ffff);
102}
103
104test "invalid utf8 continuation bytes" {
105 // unexpected continuation
106 testError("\x80", error.Utf8InvalidStartByte);
107 testError("\xbf", error.Utf8InvalidStartByte);
108 // too many leading 1's
109 testError("\xf8", error.Utf8InvalidStartByte);
110 testError("\xff", error.Utf8InvalidStartByte);
111 // expected continuation for 2 byte sequences
112 testError("\xc2", error.UnexpectedEof);
113 testError("\xc2\x00", error.Utf8ExpectedContinuation);
114 testError("\xc2\xc0", error.Utf8ExpectedContinuation);
115 // expected continuation for 3 byte sequences
116 testError("\xe0", error.UnexpectedEof);
117 testError("\xe0\x00", error.UnexpectedEof);
118 testError("\xe0\xc0", error.UnexpectedEof);
119 testError("\xe0\xa0", error.UnexpectedEof);
120 testError("\xe0\xa0\x00", error.Utf8ExpectedContinuation);
121 testError("\xe0\xa0\xc0", error.Utf8ExpectedContinuation);
122 // expected continuation for 4 byte sequences
123 testError("\xf0", error.UnexpectedEof);
124 testError("\xf0\x00", error.UnexpectedEof);
125 testError("\xf0\xc0", error.UnexpectedEof);
126 testError("\xf0\x90\x00", error.UnexpectedEof);
127 testError("\xf0\x90\xc0", error.UnexpectedEof);
128 testError("\xf0\x90\x80\x00", error.Utf8ExpectedContinuation);
129 testError("\xf0\x90\x80\xc0", error.Utf8ExpectedContinuation);
130}
131
132test "overlong utf8 codepoint" {
133 testError("\xc0\x80", error.Utf8OverlongEncoding);
134 testError("\xc1\xbf", error.Utf8OverlongEncoding);
135 testError("\xe0\x80\x80", error.Utf8OverlongEncoding);
136 testError("\xe0\x9f\xbf", error.Utf8OverlongEncoding);
137 testError("\xf0\x80\x80\x80", error.Utf8OverlongEncoding);
138 testError("\xf0\x8f\xbf\xbf", error.Utf8OverlongEncoding);
139}
140
141test "misc invalid utf8" {
142 // codepoint out of bounds
143 testError("\xf4\x90\x80\x80", error.Utf8CodepointTooLarge);
144 testError("\xf7\xbf\xbf\xbf", error.Utf8CodepointTooLarge);
145 // surrogate halves
146 testValid("\xed\x9f\xbf", 0xd7ff);
147 testError("\xed\xa0\x80", error.Utf8EncodesSurrogateHalf);
148 testError("\xed\xbf\xbf", error.Utf8EncodesSurrogateHalf);
149 testValid("\xee\x80\x80", 0xe000);
150}
151
152fn testError(bytes: []const u8, expected_err: error) {
153 if (testDecode(bytes)) |_| {
154 unreachable;
155 } else |err| {
156 std.debug.assert(err == expected_err);
157 }
158}
159
160fn testValid(bytes: []const u8, expected_codepoint: u32) {
161 std.debug.assert(%%testDecode(bytes) == expected_codepoint);
162}
163
164fn testDecode(bytes: []const u8) -> %u32 {
165 const length = %return utf8ByteSequenceLength(bytes[0]);
166 if (bytes.len < length) return error.UnexpectedEof;
167 std.debug.assert(bytes.len == length);
168 return utf8Decode(bytes);
169}
test/cases/cast.zig+9-8
...@@ -230,20 +230,21 @@ fn foo(args: ...) {...@@ -230,20 +230,21 @@ fn foo(args: ...) {
230230
231231
232test "peer type resolution: error and [N]T" {232test "peer type resolution: error and [N]T" {
233 assert(mem.eql(u8, %%testPeerErrorAndArray(0), "OK"));233 // TODO: implicit %T to %U where T can implicitly cast to U
234 comptime assert(mem.eql(u8, %%testPeerErrorAndArray(0), "OK"));234 //assert(mem.eql(u8, %%testPeerErrorAndArray(0), "OK"));
235 //comptime assert(mem.eql(u8, %%testPeerErrorAndArray(0), "OK"));
235236
236 assert(mem.eql(u8, %%testPeerErrorAndArray2(1), "OKK"));237 assert(mem.eql(u8, %%testPeerErrorAndArray2(1), "OKK"));
237 comptime assert(mem.eql(u8, %%testPeerErrorAndArray2(1), "OKK"));238 comptime assert(mem.eql(u8, %%testPeerErrorAndArray2(1), "OKK"));
238}239}
239240
240error BadValue;241error BadValue;
241fn testPeerErrorAndArray(x: u8) -> %[]const u8 {242//fn testPeerErrorAndArray(x: u8) -> %[]const u8 {
242 return switch (x) {243// return switch (x) {
243 0x00 => "OK",244// 0x00 => "OK",
244 else => error.BadValue,245// else => error.BadValue,
245 };246// };
246}247//}
247fn testPeerErrorAndArray2(x: u8) -> %[]const u8 {248fn testPeerErrorAndArray2(x: u8) -> %[]const u8 {
248 return switch (x) {249 return switch (x) {
249 0x00 => "OK",250 0x00 => "OK",
test/cases/misc.zig+11
...@@ -560,3 +560,14 @@ fn hereIsAnOpaqueType(ptr: &OpaqueA) -> &OpaqueA {...@@ -560,3 +560,14 @@ fn hereIsAnOpaqueType(ptr: &OpaqueA) -> &OpaqueA {
560 var a = ptr;560 var a = ptr;
561 return a;561 return a;
562}562}
563
564test "comptime if inside runtime while which unconditionally breaks" {
565 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
566 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
567}
568fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) {
569 while (cond) {
570 if (false) { }
571 break;
572 }
573}