authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-23 04:45:35-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-23 04:45:35-05:00
log7597735badd1f6aa6750f354a7e9c85fec705c55
tree69e5e1b3795afcf065b0a40203ba4f678a4532d7
parent6b623b5ea2a811b54a2391f17081a8981fa733a5
signaturelock-open Commit is signed but in an unrecognized format.

update the stage1 implementation to the new proposal

See #3731

21 files changed, 614 insertions(+), 443 deletions(-)

lib/std/builtin.zig+12-2
...@@ -144,7 +144,12 @@ pub const TypeInfo = union(enum) {...@@ -144,7 +144,12 @@ pub const TypeInfo = union(enum) {
144 alignment: comptime_int,144 alignment: comptime_int,
145 child: type,145 child: type,
146 is_allowzero: bool,146 is_allowzero: bool,
147 is_null_terminated: bool,147 /// The type of the sentinel is the element type of the pointer, which is
148 /// the value of the `child` field in this struct. However there is no way
149 /// to refer to that type here, so this is a pointer to an opaque value.
150 /// It will be known at compile-time to be the correct type. Dereferencing
151 /// this pointer will work at compile-time.
152 sentinel: ?*const c_void,
148153
149 /// This data structure is used by the Zig language code generation and154 /// This data structure is used by the Zig language code generation and
150 /// therefore must be kept in sync with the compiler implementation.155 /// therefore must be kept in sync with the compiler implementation.
...@@ -161,7 +166,12 @@ pub const TypeInfo = union(enum) {...@@ -161,7 +166,12 @@ pub const TypeInfo = union(enum) {
161 pub const Array = struct {166 pub const Array = struct {
162 len: comptime_int,167 len: comptime_int,
163 child: type,168 child: type,
164 is_null_terminated: bool,169 /// The type of the sentinel is the element type of the array, which is
170 /// the value of the `child` field in this struct. However there is no way
171 /// to refer to that type here, so this is a pointer to an opaque value.
172 /// It will be known at compile-time to be the correct type. Dereferencing
173 /// this pointer will work at compile-time.
174 sentinel: ?*const c_void,
165 };175 };
166176
167 /// This data structure is used by the Zig language code generation and177 /// This data structure is used by the Zig language code generation and
lib/std/c.zig+1-1
...@@ -63,7 +63,7 @@ pub extern "c" fn fclose(stream: *FILE) c_int;...@@ -63,7 +63,7 @@ pub extern "c" fn fclose(stream: *FILE) c_int;
63pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;63pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
64pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;64pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
6565
66pub extern "c" fn printf(format: [*]null const u8, ...) c_int;66pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
67pub extern "c" fn abort() noreturn;67pub extern "c" fn abort() noreturn;
68pub extern "c" fn exit(code: c_int) noreturn;68pub extern "c" fn exit(code: c_int) noreturn;
69pub extern "c" fn isatty(fd: fd_t) c_int;69pub extern "c" fn isatty(fd: fd_t) c_int;
lib/std/mem.zig+1-1
...@@ -1409,7 +1409,7 @@ fn BytesAsValueReturnType(comptime T: type, comptime B: type) type {...@@ -1409,7 +1409,7 @@ fn BytesAsValueReturnType(comptime T: type, comptime B: type) type {
1409 const size = @as(usize, @sizeOf(T));1409 const size = @as(usize, @sizeOf(T));
14101410
1411 if (comptime !trait.is(builtin.TypeId.Pointer)(B) or1411 if (comptime !trait.is(builtin.TypeId.Pointer)(B) or
1412 (meta.Child(B) != [size]u8 and meta.Child(B) != [size]null u8))1412 (meta.Child(B) != [size]u8 and meta.Child(B) != [size:0]u8))
1413 {1413 {
1414 @compileError("expected *[N]u8 " ++ ", passed " ++ @typeName(B));1414 @compileError("expected *[N]u8 " ++ ", passed " ++ @typeName(B));
1415 }1415 }
lib/std/zig/parser_test.zig+3-3
...@@ -1552,7 +1552,7 @@ test "zig fmt: pointer attributes" {...@@ -1552,7 +1552,7 @@ test "zig fmt: pointer attributes" {
1552 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;1552 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
1553 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;1553 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
1554 \\extern fn f4(s: *align(1) const volatile u8) c_int;1554 \\extern fn f4(s: *align(1) const volatile u8) c_int;
1555 \\extern fn f5(s: [*]null align(1) const volatile u8) c_int;1555 \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
1556 \\1556 \\
1557 );1557 );
1558}1558}
...@@ -1563,7 +1563,7 @@ test "zig fmt: slice attributes" {...@@ -1563,7 +1563,7 @@ test "zig fmt: slice attributes" {
1563 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;1563 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
1564 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;1564 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
1565 \\extern fn f4(s: *align(1) const volatile u8) c_int;1565 \\extern fn f4(s: *align(1) const volatile u8) c_int;
1566 \\extern fn f5(s: [*]null align(1) const volatile u8) c_int;1566 \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
1567 \\1567 \\
1568 );1568 );
1569}1569}
...@@ -1885,7 +1885,7 @@ test "zig fmt: arrays" {...@@ -1885,7 +1885,7 @@ test "zig fmt: arrays" {
1885 \\ 2,1885 \\ 2,
1886 \\ };1886 \\ };
1887 \\ const a: [0]u8 = []u8{};1887 \\ const a: [0]u8 = []u8{};
1888 \\ const x: [4]null u8 = undefined;1888 \\ const x: [4:0]u8 = undefined;
1889 \\}1889 \\}
1890 \\1890 \\
1891 );1891 );
src/all_types.hpp+19-8
...@@ -55,7 +55,6 @@ enum PtrLen {...@@ -55,7 +55,6 @@ enum PtrLen {
55 PtrLenUnknown,55 PtrLenUnknown,
56 PtrLenSingle,56 PtrLenSingle,
57 PtrLenC,57 PtrLenC,
58 PtrLenNull,
59};58};
6059
61// This one corresponds to the builtin.zig enum.60// This one corresponds to the builtin.zig enum.
...@@ -353,19 +352,20 @@ struct LazyValueSliceType {...@@ -353,19 +352,20 @@ struct LazyValueSliceType {
353 LazyValue base;352 LazyValue base;
354353
355 IrAnalyze *ira;354 IrAnalyze *ira;
355 IrInstruction *sentinel; // can be null
356 IrInstruction *elem_type;356 IrInstruction *elem_type;
357 IrInstruction *align_inst; // can be null357 IrInstruction *align_inst; // can be null
358358
359 bool is_const;359 bool is_const;
360 bool is_volatile;360 bool is_volatile;
361 bool is_allowzero;361 bool is_allowzero;
362 bool is_null_terminated;
363};362};
364363
365struct LazyValuePtrType {364struct LazyValuePtrType {
366 LazyValue base;365 LazyValue base;
367366
368 IrAnalyze *ira;367 IrAnalyze *ira;
368 IrInstruction *sentinel; // can be null
369 IrInstruction *elem_type;369 IrInstruction *elem_type;
370 IrInstruction *align_inst; // can be null370 IrInstruction *align_inst; // can be null
371371
...@@ -821,6 +821,7 @@ struct AstNodePrefixOpExpr {...@@ -821,6 +821,7 @@ struct AstNodePrefixOpExpr {
821821
822struct AstNodePointerType {822struct AstNodePointerType {
823 Token *star_token;823 Token *star_token;
824 AstNode *sentinel;
824 AstNode *align_expr;825 AstNode *align_expr;
825 BigInt *bit_offset_start;826 BigInt *bit_offset_start;
826 BigInt *host_int_bytes;827 BigInt *host_int_bytes;
...@@ -828,21 +829,21 @@ struct AstNodePointerType {...@@ -828,21 +829,21 @@ struct AstNodePointerType {
828 Token *allow_zero_token;829 Token *allow_zero_token;
829 bool is_const;830 bool is_const;
830 bool is_volatile;831 bool is_volatile;
831 bool is_null_terminated;
832};832};
833833
834struct AstNodeInferredArrayType {834struct AstNodeInferredArrayType {
835 AstNode *sentinel; // can be null
835 AstNode *child_type;836 AstNode *child_type;
836};837};
837838
838struct AstNodeArrayType {839struct AstNodeArrayType {
839 AstNode *size;840 AstNode *size;
841 AstNode *sentinel;
840 AstNode *child_type;842 AstNode *child_type;
841 AstNode *align_expr;843 AstNode *align_expr;
842 Token *allow_zero_token;844 Token *allow_zero_token;
843 bool is_const;845 bool is_const;
844 bool is_volatile;846 bool is_volatile;
845 bool is_null_terminated;
846};847};
847848
848struct AstNodeUsingNamespace {849struct AstNodeUsingNamespace {
...@@ -1208,6 +1209,11 @@ struct ZigTypePointer {...@@ -1208,6 +1209,11 @@ struct ZigTypePointer {
1208 // struct.1209 // struct.
1209 InferredStructField *inferred_struct_field;1210 InferredStructField *inferred_struct_field;
12101211
1212 // This can be null. If it is non-null, it means the pointer is terminated by this
1213 // sentinel value. This is most commonly used for C-style strings, with a 0 byte
1214 // to specify the length of the memory pointed to.
1215 ConstExprValue *sentinel;
1216
1211 PtrLen ptr_len;1217 PtrLen ptr_len;
1212 uint32_t explicit_alignment; // 0 means use ABI alignment1218 uint32_t explicit_alignment; // 0 means use ABI alignment
12131219
...@@ -1235,7 +1241,7 @@ struct ZigTypeFloat {...@@ -1235,7 +1241,7 @@ struct ZigTypeFloat {
1235struct ZigTypeArray {1241struct ZigTypeArray {
1236 ZigType *child_type;1242 ZigType *child_type;
1237 uint64_t len;1243 uint64_t len;
1238 bool is_null_terminated;1244 ConstExprValue *sentinel;
1239};1245};
12401246
1241struct TypeStructField {1247struct TypeStructField {
...@@ -1761,8 +1767,10 @@ struct TypeId {...@@ -1761,8 +1767,10 @@ struct TypeId {
17611767
1762 union {1768 union {
1763 struct {1769 struct {
1770 CodeGen *codegen;
1764 ZigType *child_type;1771 ZigType *child_type;
1765 InferredStructField *inferred_struct_field;1772 InferredStructField *inferred_struct_field;
1773 ConstExprValue *sentinel;
1766 PtrLen ptr_len;1774 PtrLen ptr_len;
1767 uint32_t alignment;1775 uint32_t alignment;
17681776
...@@ -1775,9 +1783,10 @@ struct TypeId {...@@ -1775,9 +1783,10 @@ struct TypeId {
1775 bool allow_zero;1783 bool allow_zero;
1776 } pointer;1784 } pointer;
1777 struct {1785 struct {
1786 CodeGen *codegen;
1778 ZigType *child_type;1787 ZigType *child_type;
1779 uint64_t size;1788 uint64_t size;
1780 bool is_null_terminated;1789 ConstExprValue *sentinel;
1781 } array;1790 } array;
1782 struct {1791 struct {
1783 bool is_signed;1792 bool is_signed;
...@@ -2033,6 +2042,7 @@ struct CodeGen {...@@ -2033,6 +2042,7 @@ struct CodeGen {
2033 IrInstruction *invalid_instruction;2042 IrInstruction *invalid_instruction;
2034 IrInstruction *unreach_instruction;2043 IrInstruction *unreach_instruction;
20352044
2045 ConstExprValue const_zero_byte;
2036 ConstExprValue const_void_val;2046 ConstExprValue const_void_val;
2037 ConstExprValue panic_msg_vals[PanicMsgIdCount];2047 ConstExprValue panic_msg_vals[PanicMsgIdCount];
20382048
...@@ -2989,13 +2999,14 @@ struct IrInstructionArrayType {...@@ -2989,13 +2999,14 @@ struct IrInstructionArrayType {
2989 IrInstruction base;2999 IrInstruction base;
29903000
2991 IrInstruction *size;3001 IrInstruction *size;
3002 IrInstruction *sentinel;
2992 IrInstruction *child_type;3003 IrInstruction *child_type;
2993 bool is_null_terminated;
2994};3004};
29953005
2996struct IrInstructionPtrType {3006struct IrInstructionPtrType {
2997 IrInstruction base;3007 IrInstruction base;
29983008
3009 IrInstruction *sentinel;
2999 IrInstruction *align_value;3010 IrInstruction *align_value;
3000 IrInstruction *child_type;3011 IrInstruction *child_type;
3001 uint32_t bit_offset_start;3012 uint32_t bit_offset_start;
...@@ -3015,12 +3026,12 @@ struct IrInstructionAnyFrameType {...@@ -3015,12 +3026,12 @@ struct IrInstructionAnyFrameType {
3015struct IrInstructionSliceType {3026struct IrInstructionSliceType {
3016 IrInstruction base;3027 IrInstruction base;
30173028
3029 IrInstruction *sentinel;
3018 IrInstruction *align_value;3030 IrInstruction *align_value;
3019 IrInstruction *child_type;3031 IrInstruction *child_type;
3020 bool is_const;3032 bool is_const;
3021 bool is_volatile;3033 bool is_volatile;
3022 bool is_allow_zero;3034 bool is_allow_zero;
3023 bool is_null_terminated;
3024};3035};
30253036
3026struct IrInstructionGlobalAsm {3037struct IrInstructionGlobalAsm {
src/analyze.cpp+117-104
...@@ -452,20 +452,6 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type) {...@@ -452,20 +452,6 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type) {
452 return entry;452 return entry;
453}453}
454454
455static const char *ptr_len_to_star_str(PtrLen ptr_len) {
456 switch (ptr_len) {
457 case PtrLenSingle:
458 return "*";
459 case PtrLenUnknown:
460 return "[*]";
461 case PtrLenC:
462 return "[*c]";
463 case PtrLenNull:
464 return "[*]null ";
465 }
466 zig_unreachable();
467}
468
469ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {455ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
470 if (fn->frame_type != nullptr) {456 if (fn->frame_type != nullptr) {
471 return fn->frame_type;457 return fn->frame_type;
...@@ -485,10 +471,47 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {...@@ -485,10 +471,47 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
485 return entry;471 return entry;
486}472}
487473
474static void append_ptr_type_attrs(Buf *type_name, ZigType *ptr_type) {
475 const char *const_str = ptr_type->data.pointer.is_const ? "const " : "";
476 const char *volatile_str = ptr_type->data.pointer.is_volatile ? "volatile " : "";
477 const char *allow_zero_str;
478 if (ptr_type->data.pointer.ptr_len == PtrLenC) {
479 assert(ptr_type->data.pointer.allow_zero);
480 allow_zero_str = "";
481 } else {
482 allow_zero_str = ptr_type->data.pointer.allow_zero ? "allowzero " : "";
483 }
484 if (ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.host_int_bytes != 0 ||
485 ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE)
486 {
487 buf_appendf(type_name, "align(");
488 if (ptr_type->data.pointer.explicit_alignment != 0) {
489 buf_appendf(type_name, "%" PRIu32, ptr_type->data.pointer.explicit_alignment);
490 }
491 if (ptr_type->data.pointer.host_int_bytes != 0) {
492 buf_appendf(type_name, ":%" PRIu32 ":%" PRIu32, ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes);
493 }
494 if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
495 buf_appendf(type_name, ":?");
496 } else if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
497 buf_appendf(type_name, ":%" PRIu32, ptr_type->data.pointer.vector_index);
498 }
499 buf_appendf(type_name, ")");
500 }
501 buf_appendf(type_name, "%s%s%s", const_str, volatile_str, allow_zero_str);
502 if (ptr_type->data.pointer.inferred_struct_field != nullptr) {
503 buf_appendf(type_name, " field '%s' of %s)",
504 buf_ptr(ptr_type->data.pointer.inferred_struct_field->field_name),
505 buf_ptr(&ptr_type->data.pointer.inferred_struct_field->inferred_struct_type->name));
506 } else {
507 buf_appendf(type_name, "%s", buf_ptr(&ptr_type->data.pointer.child_type->name));
508 }
509}
510
488ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,511ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,
489 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,512 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
490 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero,513 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero,
491 uint32_t vector_index, InferredStructField *inferred_struct_field)514 uint32_t vector_index, InferredStructField *inferred_struct_field, ConstExprValue *sentinel)
492{515{
493 assert(ptr_len != PtrLenC || allow_zero);516 assert(ptr_len != PtrLenC || allow_zero);
494 assert(!type_is_invalid(child_type));517 assert(!type_is_invalid(child_type));
...@@ -511,9 +534,11 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -511,9 +534,11 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
511 TypeId type_id = {};534 TypeId type_id = {};
512 ZigType **parent_pointer = nullptr;535 ZigType **parent_pointer = nullptr;
513 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||536 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
514 allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr)537 allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr ||
538 sentinel != nullptr)
515 {539 {
516 type_id.id = ZigTypeIdPointer;540 type_id.id = ZigTypeIdPointer;
541 type_id.data.pointer.codegen = g;
517 type_id.data.pointer.child_type = child_type;542 type_id.data.pointer.child_type = child_type;
518 type_id.data.pointer.is_const = is_const;543 type_id.data.pointer.is_const = is_const;
519 type_id.data.pointer.is_volatile = is_volatile;544 type_id.data.pointer.is_volatile = is_volatile;
...@@ -524,6 +549,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -524,6 +549,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
524 type_id.data.pointer.allow_zero = allow_zero;549 type_id.data.pointer.allow_zero = allow_zero;
525 type_id.data.pointer.vector_index = vector_index;550 type_id.data.pointer.vector_index = vector_index;
526 type_id.data.pointer.inferred_struct_field = inferred_struct_field;551 type_id.data.pointer.inferred_struct_field = inferred_struct_field;
552 type_id.data.pointer.sentinel = sentinel;
527553
528 auto existing_entry = g->type_table.maybe_get(type_id);554 auto existing_entry = g->type_table.maybe_get(type_id);
529 if (existing_entry)555 if (existing_entry)
...@@ -539,57 +565,36 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -539,57 +565,36 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
539565
540 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);566 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
541567
542 const char *star_str = ptr_len_to_star_str(ptr_len);
543 const char *const_str = is_const ? "const " : "";
544 const char *volatile_str = is_volatile ? "volatile " : "";
545 const char *allow_zero_str;
546 if (ptr_len == PtrLenC) {
547 assert(allow_zero);
548 allow_zero_str = "";
549 } else {
550 allow_zero_str = allow_zero ? "allowzero " : "";
551 }
552 buf_resize(&entry->name, 0);568 buf_resize(&entry->name, 0);
553 if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) {569 if (inferred_struct_field != nullptr) {
554 if (inferred_struct_field == nullptr) {570 buf_appendf(&entry->name, "(");
555 buf_appendf(&entry->name, "%s%s%s%s%s",571 }
556 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));572 switch (ptr_len) {
557 } else {573 case PtrLenSingle:
558 buf_appendf(&entry->name, "(%s%s%s%s field '%s' of %s)",574 buf_appendf(&entry->name, "*");
559 star_str, const_str, volatile_str, allow_zero_str,575 break;
560 buf_ptr(inferred_struct_field->field_name),576 case PtrLenUnknown:
561 buf_ptr(&inferred_struct_field->inferred_struct_type->name));577 buf_appendf(&entry->name, "[*");
562 }578 break;
563 } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) {579 case PtrLenC:
564 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,580 assert(sentinel == nullptr);
565 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));581 buf_appendf(&entry->name, "[*c]");
566 } else if (byte_alignment == 0) {582 break;
567 assert(vector_index == VECTOR_INDEX_NONE);583 }
568 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s",584 if (sentinel != nullptr) {
569 star_str,585 buf_appendf(&entry->name, ":");
570 bit_offset_in_host, host_int_bytes,586 render_const_value(g, &entry->name, sentinel);
571 const_str, volatile_str, allow_zero_str,587 }
572 buf_ptr(&child_type->name));588 switch (ptr_len) {
573 } else if (vector_index == VECTOR_INDEX_NONE) {589 case PtrLenSingle:
574 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",590 case PtrLenC:
575 star_str, byte_alignment,591 break;
576 bit_offset_in_host, host_int_bytes,592 case PtrLenUnknown:
577 const_str, volatile_str, allow_zero_str,593 buf_appendf(&entry->name, "]");
578 buf_ptr(&child_type->name));594 break;
579 } else if (vector_index == VECTOR_INDEX_RUNTIME) {
580 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":?) %s%s%s%s",
581 star_str, byte_alignment,
582 bit_offset_in_host, host_int_bytes,
583 const_str, volatile_str, allow_zero_str,
584 buf_ptr(&child_type->name));
585 } else {
586 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
587 star_str, byte_alignment,
588 bit_offset_in_host, host_int_bytes, vector_index,
589 const_str, volatile_str, allow_zero_str,
590 buf_ptr(&child_type->name));
591 }595 }
592596
597
593 if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {598 if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
594 if (type_has_bits(child_type)) {599 if (type_has_bits(child_type)) {
595 entry->abi_size = g->builtin_types.entry_usize->abi_size;600 entry->abi_size = g->builtin_types.entry_usize->abi_size;
...@@ -617,6 +622,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -617,6 +622,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
617 entry->data.pointer.allow_zero = allow_zero;622 entry->data.pointer.allow_zero = allow_zero;
618 entry->data.pointer.vector_index = vector_index;623 entry->data.pointer.vector_index = vector_index;
619 entry->data.pointer.inferred_struct_field = inferred_struct_field;624 entry->data.pointer.inferred_struct_field = inferred_struct_field;
625 entry->data.pointer.sentinel = sentinel;
626
627 append_ptr_type_attrs(&entry->name, entry);
620628
621 if (parent_pointer) {629 if (parent_pointer) {
622 *parent_pointer = entry;630 *parent_pointer = entry;
...@@ -631,12 +639,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -631,12 +639,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
631 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)639 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
632{640{
633 return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len,641 return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len,
634 byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr);642 byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr, nullptr);
635}643}
636644
637ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {645ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
638 return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false,646 return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false,
639 VECTOR_INDEX_NONE, nullptr);647 VECTOR_INDEX_NONE, nullptr, nullptr);
640}648}
641649
642ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {650ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
...@@ -752,12 +760,13 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa...@@ -752,12 +760,13 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
752 return entry;760 return entry;
753}761}
754762
755ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bool is_null_terminated) {763ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ConstExprValue *sentinel) {
756 TypeId type_id = {};764 TypeId type_id = {};
757 type_id.id = ZigTypeIdArray;765 type_id.id = ZigTypeIdArray;
766 type_id.data.array.codegen = g;
758 type_id.data.array.child_type = child_type;767 type_id.data.array.child_type = child_type;
759 type_id.data.array.size = array_size;768 type_id.data.array.size = array_size;
760 type_id.data.array.is_null_terminated = is_null_terminated;769 type_id.data.array.sentinel = sentinel;
761 auto existing_entry = g->type_table.maybe_get(type_id);770 auto existing_entry = g->type_table.maybe_get(type_id);
762 if (existing_entry) {771 if (existing_entry) {
763 return existing_entry->value;772 return existing_entry->value;
...@@ -767,16 +776,19 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bo...@@ -767,16 +776,19 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bo
767776
768 ZigType *entry = new_type_table_entry(ZigTypeIdArray);777 ZigType *entry = new_type_table_entry(ZigTypeIdArray);
769778
770 const char *null_str = is_null_terminated ? "null " : "";
771
772 buf_resize(&entry->name, 0);779 buf_resize(&entry->name, 0);
773 buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s%s", array_size, null_str, buf_ptr(&child_type->name));780 buf_appendf(&entry->name, "[%" ZIG_PRI_u64, array_size);
781 if (sentinel != nullptr) {
782 buf_appendf(&entry->name, ":");
783 render_const_value(g, &entry->name, sentinel);
784 }
785 buf_appendf(&entry->name, "]%s", buf_ptr(&child_type->name));
774786
775 size_t full_array_size;787 size_t full_array_size;
776 if (array_size == 0) {788 if (array_size == 0) {
777 full_array_size = 0;789 full_array_size = 0;
778 } else {790 } else {
779 full_array_size = array_size + (is_null_terminated ? 1 : 0);791 full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0);
780 }792 }
781793
782 entry->size_in_bits = child_type->size_in_bits * full_array_size;794 entry->size_in_bits = child_type->size_in_bits * full_array_size;
...@@ -785,7 +797,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bo...@@ -785,7 +797,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bo
785797
786 entry->data.array.child_type = child_type;798 entry->data.array.child_type = child_type;
787 entry->data.array.len = array_size;799 entry->data.array.len = array_size;
788 entry->data.array.is_null_terminated = is_null_terminated;800 entry->data.array.sentinel = sentinel;
789801
790 g->type_table.put(type_id, entry);802 g->type_table.put(type_id, entry);
791 return entry;803 return entry;
...@@ -793,7 +805,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bo...@@ -793,7 +805,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bo
793805
794ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {806ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
795 assert(ptr_type->id == ZigTypeIdPointer);807 assert(ptr_type->id == ZigTypeIdPointer);
796 assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown || ptr_type->data.pointer.ptr_len == PtrLenNull);808 assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown);
797809
798 ZigType **parent_pointer = &ptr_type->data.pointer.slice_parent;810 ZigType **parent_pointer = &ptr_type->data.pointer.slice_parent;
799 if (*parent_pointer) {811 if (*parent_pointer) {
...@@ -802,10 +814,14 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -802,10 +814,14 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
802814
803 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);815 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
804816
805 // replace the & with [] to go from a ptr type name to a slice type name
806 buf_resize(&entry->name, 0);817 buf_resize(&entry->name, 0);
807 size_t name_offset = (ptr_type->data.pointer.ptr_len == PtrLenSingle) ? 1 : 3;818 buf_appendf(&entry->name, "[");
808 buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset);819 if (ptr_type->data.pointer.sentinel != nullptr) {
820 buf_appendf(&entry->name, ":");
821 render_const_value(g, &entry->name, ptr_type->data.pointer.sentinel);
822 }
823 buf_appendf(&entry->name, "]");
824 append_ptr_type_attrs(&entry->name, ptr_type);
809825
810 unsigned element_count = 2;826 unsigned element_count = 2;
811 Buf *ptr_field_name = buf_create_from_str("ptr");827 Buf *ptr_field_name = buf_create_from_str("ptr");
...@@ -5639,14 +5655,14 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -5639,14 +5655,14 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
5639 // first we build the underlying array5655 // first we build the underlying array
5640 ConstExprValue *array_val = create_const_vals(1);5656 ConstExprValue *array_val = create_const_vals(1);
5641 array_val->special = ConstValSpecialStatic;5657 array_val->special = ConstValSpecialStatic;
5642 array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), true);5658 array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), &g->const_zero_byte);
5643 array_val->data.x_array.special = ConstArraySpecialBuf;5659 array_val->data.x_array.special = ConstArraySpecialBuf;
5644 array_val->data.x_array.data.s_buf = str;5660 array_val->data.x_array.data.s_buf = str;
56455661
5646 // then make the pointer point to it5662 // then make the pointer point to it
5647 const_val->special = ConstValSpecialStatic;5663 const_val->special = ConstValSpecialStatic;
5648 const_val->type = get_pointer_to_type_extra2(g, array_val->type, true, false,5664 const_val->type = get_pointer_to_type_extra2(g, array_val->type, true, false,
5649 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr);5665 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, nullptr);
5650 const_val->data.x_ptr.special = ConstPtrSpecialRef;5666 const_val->data.x_ptr.special = ConstPtrSpecialRef;
5651 const_val->data.x_ptr.data.ref.pointee = array_val;5667 const_val->data.x_ptr.data.ref.pointee = array_val;
56525668
...@@ -6079,7 +6095,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -6079,7 +6095,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
60796095
6080 fields.append({"@stack_trace", get_stack_trace_type(g), 0});6096 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
6081 fields.append({"@instruction_addresses",6097 fields.append({"@instruction_addresses",
6082 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, false), 0});6098 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr), 0});
6083 }6099 }
60846100
6085 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),6101 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
...@@ -6287,7 +6303,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -6287,7 +6303,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
6287 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {6303 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {
6288 fields.append({"@stack_trace", get_stack_trace_type(g), 0});6304 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
6289 fields.append({"@instruction_addresses",6305 fields.append({"@instruction_addresses",
6290 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, false), 0});6306 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr), 0});
6291 }6307 }
62926308
6293 for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {6309 for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
...@@ -7050,11 +7066,12 @@ uint32_t type_id_hash(TypeId x) {...@@ -7050,11 +7066,12 @@ uint32_t type_id_hash(TypeId x) {
7050 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +7066 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
7051 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +7067 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
7052 (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +7068 (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +
7053 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);7069 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881) *
7070 (x.data.pointer.sentinel ? hash_const_val(x.data.pointer.sentinel) : (uint32_t)2955491856);
7054 case ZigTypeIdArray:7071 case ZigTypeIdArray:
7055 return hash_ptr(x.data.array.child_type) *7072 return hash_ptr(x.data.array.child_type) *
7056 ((uint32_t)x.data.array.size ^ (uint32_t)2122979968) *7073 ((uint32_t)x.data.array.size ^ (uint32_t)2122979968) *
7057 ((uint32_t)x.data.array.is_null_terminated ^ (uint32_t)2048352596);7074 (x.data.array.sentinel ? hash_const_val(x.data.array.sentinel) : (uint32_t)1927201585);
7058 case ZigTypeIdInt:7075 case ZigTypeIdInt:
7059 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +7076 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
7060 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);7077 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
...@@ -7105,6 +7122,11 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -7105,6 +7122,11 @@ bool type_id_eql(TypeId a, TypeId b) {
7105 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&7122 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
7106 a.data.pointer.vector_index == b.data.pointer.vector_index &&7123 a.data.pointer.vector_index == b.data.pointer.vector_index &&
7107 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes &&7124 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes &&
7125 (
7126 a.data.pointer.sentinel == b.data.pointer.sentinel ||
7127 (a.data.pointer.sentinel != nullptr && b.data.pointer.sentinel != nullptr &&
7128 const_values_equal(a.data.pointer.codegen, a.data.pointer.sentinel, b.data.pointer.sentinel))
7129 ) &&
7108 (7130 (
7109 a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field ||7131 a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field ||
7110 (a.data.pointer.inferred_struct_field != nullptr &&7132 (a.data.pointer.inferred_struct_field != nullptr &&
...@@ -7117,7 +7139,11 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -7117,7 +7139,11 @@ bool type_id_eql(TypeId a, TypeId b) {
7117 case ZigTypeIdArray:7139 case ZigTypeIdArray:
7118 return a.data.array.child_type == b.data.array.child_type &&7140 return a.data.array.child_type == b.data.array.child_type &&
7119 a.data.array.size == b.data.array.size &&7141 a.data.array.size == b.data.array.size &&
7120 a.data.array.is_null_terminated == b.data.array.is_null_terminated;7142 (
7143 a.data.array.sentinel == b.data.array.sentinel ||
7144 (a.data.array.sentinel != nullptr && b.data.array.sentinel != nullptr &&
7145 const_values_equal(a.data.array.codegen, a.data.array.sentinel, b.data.array.sentinel))
7146 );
7121 case ZigTypeIdInt:7147 case ZigTypeIdInt:
7122 return a.data.integer.is_signed == b.data.integer.is_signed &&7148 return a.data.integer.is_signed == b.data.integer.is_signed &&
7123 a.data.integer.bit_count == b.data.integer.bit_count;7149 a.data.integer.bit_count == b.data.integer.bit_count;
...@@ -8303,7 +8329,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -8303,7 +8329,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
8303 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;8329 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
8304 if (padding_bytes > 0) {8330 if (padding_bytes > 0) {
8305 ZigType *u8_type = get_int_type(g, false, 8);8331 ZigType *u8_type = get_int_type(g, false, 8);
8306 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, false);8332 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, nullptr);
8307 LLVMTypeRef union_element_types[] = {8333 LLVMTypeRef union_element_types[] = {
8308 most_aligned_union_member->type_entry->llvm_type,8334 most_aligned_union_member->type_entry->llvm_type,
8309 get_llvm_type(g, padding_array),8335 get_llvm_type(g, padding_array),
...@@ -8337,7 +8363,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -8337,7 +8363,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
8337 union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);8363 union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);
8338 } else {8364 } else {
8339 ZigType *u8_type = get_int_type(g, false, 8);8365 ZigType *u8_type = get_int_type(g, false, 8);
8340 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, false);8366 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, nullptr);
8341 LLVMTypeRef union_element_types[] = {8367 LLVMTypeRef union_element_types[] = {
8342 get_llvm_type(g, most_aligned_union_member->type_entry),8368 get_llvm_type(g, most_aligned_union_member->type_entry),
8343 get_llvm_type(g, padding_array),8369 get_llvm_type(g, padding_array),
...@@ -8418,19 +8444,19 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus...@@ -8418,19 +8444,19 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus
8418 if (type->data.pointer.is_const || type->data.pointer.is_volatile ||8444 if (type->data.pointer.is_const || type->data.pointer.is_volatile ||
8419 type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle ||8445 type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle ||
8420 type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero ||8446 type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero ||
8421 type->data.pointer.vector_index != VECTOR_INDEX_NONE)8447 type->data.pointer.vector_index != VECTOR_INDEX_NONE || type->data.pointer.sentinel != nullptr)
8422 {8448 {
8423 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));8449 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));
8424 ZigType *peer_type;8450 ZigType *peer_type;
8425 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {8451 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {
8426 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,8452 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,
8427 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,8453 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,
8428 VECTOR_INDEX_NONE, nullptr);8454 VECTOR_INDEX_NONE, nullptr, nullptr);
8429 } else {8455 } else {
8430 uint32_t host_vec_len = type->data.pointer.host_int_bytes;8456 uint32_t host_vec_len = type->data.pointer.host_int_bytes;
8431 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);8457 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);
8432 peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false,8458 peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false,
8433 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr);8459 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, nullptr);
8434 }8460 }
8435 type->llvm_type = get_llvm_type(g, peer_type);8461 type->llvm_type = get_llvm_type(g, peer_type);
8436 type->llvm_di_type = get_llvm_di_type(g, peer_type);8462 type->llvm_di_type = get_llvm_di_type(g, peer_type);
...@@ -8659,8 +8685,8 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {...@@ -8659,8 +8685,8 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {
86598685
8660 ZigType *elem_type = type->data.array.child_type;8686 ZigType *elem_type = type->data.array.child_type;
86618687
8662 uint64_t extra_len_from_null = type->data.array.is_null_terminated ? 1 : 0;8688 uint64_t extra_len_from_sentinel = (type->data.array.sentinel != nullptr) ? 1 : 0;
8663 uint64_t full_len = type->data.array.len + extra_len_from_null;8689 uint64_t full_len = type->data.array.len + extra_len_from_sentinel;
8664 // TODO https://github.com/ziglang/zig/issues/14248690 // TODO https://github.com/ziglang/zig/issues/1424
8665 type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)full_len);8691 type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)full_len);
86668692
...@@ -9166,16 +9192,3 @@ void IrExecutable::src() {...@@ -9166,16 +9192,3 @@ void IrExecutable::src() {
9166 it->source_node->src();9192 it->source_node->src();
9167 }9193 }
9168}9194}
9169
9170ConstExprValue *get_null_value(ZigType *ty) {
9171 if (ty->id == ZigTypeIdInt || ty->id == ZigTypeIdComptimeInt) {
9172 return create_const_unsigned_negative(ty, 0, false);
9173 } else if (ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdComptimeFloat) {
9174 return create_const_float(ty, NAN);
9175 } else if (ty->id == ZigTypeIdOptional) {
9176 return create_const_null(ty);
9177 } else {
9178 zig_unreachable();
9179 }
9180}
9181
src/analyze.hpp+3-3
...@@ -24,7 +24,8 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,...@@ -24,7 +24,8 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,
24ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,24ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,
25 bool is_const, bool is_volatile, PtrLen ptr_len,25 bool is_const, bool is_volatile, PtrLen ptr_len,
26 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,26 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,
27 bool allow_zero, uint32_t vector_index, InferredStructField *inferred_struct_field);27 bool allow_zero, uint32_t vector_index, InferredStructField *inferred_struct_field,
28 ConstExprValue *sentinel);
28uint64_t type_size(CodeGen *g, ZigType *type_entry);29uint64_t type_size(CodeGen *g, ZigType *type_entry);
29uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);30uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
30ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);31ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
...@@ -33,7 +34,7 @@ ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);...@@ -33,7 +34,7 @@ ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
33ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);34ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
34ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);35ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
35ZigType *get_optional_type(CodeGen *g, ZigType *child_type);36ZigType *get_optional_type(CodeGen *g, ZigType *child_type);
36ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bool is_null_terminated);37ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ConstExprValue *sentinel);
37ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);38ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
38ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,39ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
39 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);40 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);
...@@ -276,5 +277,4 @@ IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node,...@@ -276,5 +277,4 @@ IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node,
276Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,277Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,
277 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);278 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
278ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);279ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
279ConstExprValue *get_null_value(ZigType *ty);
280#endif280#endif
src/ast_render.cpp+2-2
...@@ -147,9 +147,9 @@ static const char *token_to_ptr_len_str(Token *tok) {...@@ -147,9 +147,9 @@ static const char *token_to_ptr_len_str(Token *tok) {
147 case TokenIdStar:147 case TokenIdStar:
148 case TokenIdStarStar:148 case TokenIdStarStar:
149 return "*";149 return "*";
150 case TokenIdBracketStarBracket:150 case TokenIdLBracket:
151 return "[*]";151 return "[*]";
152 case TokenIdBracketStarCBracket:152 case TokenIdSymbol:
153 return "[*c]";153 return "[*c]";
154 default:154 default:
155 zig_unreachable();155 zig_unreachable();
src/codegen.cpp+16-11
...@@ -3707,8 +3707,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3707,8 +3707,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3707 array_type = array_type->data.pointer.child_type;3707 array_type = array_type->data.pointer.child_type;
3708 }3708 }
3709 if (safety_check_on) {3709 if (safety_check_on) {
3710 uint64_t extra_len_from_null = array_type->data.array.is_null_terminated ? 1 : 0;3710 uint64_t extra_len_from_sentinel = (array_type->data.array.sentinel != nullptr) ? 1 : 0;
3711 uint64_t full_len = array_type->data.array.len + extra_len_from_null;3711 uint64_t full_len = array_type->data.array.len + extra_len_from_sentinel;
3712 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, full_len, false);3712 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, full_len, false);
3713 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);3713 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
3714 }3714 }
...@@ -6636,8 +6636,8 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con...@@ -6636,8 +6636,8 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
6636 ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;6636 ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
6637 assert(array_const_val->type->id == ZigTypeIdArray);6637 assert(array_const_val->type->id == ZigTypeIdArray);
6638 if (!type_has_bits(array_const_val->type)) {6638 if (!type_has_bits(array_const_val->type)) {
6639 if (array_const_val->type->data.array.is_null_terminated) {6639 if (array_const_val->type->data.array.sentinel != nullptr) {
6640 ConstExprValue *pointee = get_null_value(array_const_val->type->data.array.child_type);6640 ConstExprValue *pointee = array_const_val->type->data.array.sentinel;
6641 render_const_val(g, pointee, "");6641 render_const_val(g, pointee, "");
6642 render_const_val_global(g, pointee, "");6642 render_const_val_global(g, pointee, "");
6643 const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global,6643 const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global,
...@@ -6963,8 +6963,8 @@ check: switch (const_val->special) {...@@ -6963,8 +6963,8 @@ check: switch (const_val->special) {
6963 case ConstArraySpecialUndef:6963 case ConstArraySpecialUndef:
6964 return LLVMGetUndef(get_llvm_type(g, type_entry));6964 return LLVMGetUndef(get_llvm_type(g, type_entry));
6965 case ConstArraySpecialNone: {6965 case ConstArraySpecialNone: {
6966 uint64_t extra_len_from_null = type_entry->data.array.is_null_terminated ? 1 : 0;6966 uint64_t extra_len_from_sentinel = (type_entry->data.array.sentinel != nullptr) ? 1 : 0;
6967 uint64_t full_len = len + extra_len_from_null;6967 uint64_t full_len = len + extra_len_from_sentinel;
6968 LLVMValueRef *values = allocate<LLVMValueRef>(full_len);6968 LLVMValueRef *values = allocate<LLVMValueRef>(full_len);
6969 LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);6969 LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);
6970 bool make_unnamed_struct = false;6970 bool make_unnamed_struct = false;
...@@ -6974,8 +6974,8 @@ check: switch (const_val->special) {...@@ -6974,8 +6974,8 @@ check: switch (const_val->special) {
6974 values[i] = val;6974 values[i] = val;
6975 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val);6975 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val);
6976 }6976 }
6977 if (type_entry->data.array.is_null_terminated) {6977 if (type_entry->data.array.sentinel != nullptr) {
6978 values[len] = LLVMConstNull(element_type_ref);6978 values[len] = gen_const_val(g, type_entry->data.array.sentinel, "");
6979 }6979 }
6980 if (make_unnamed_struct) {6980 if (make_unnamed_struct) {
6981 return LLVMConstStruct(values, full_len, true);6981 return LLVMConstStruct(values, full_len, true);
...@@ -6986,7 +6986,7 @@ check: switch (const_val->special) {...@@ -6986,7 +6986,7 @@ check: switch (const_val->special) {
6986 case ConstArraySpecialBuf: {6986 case ConstArraySpecialBuf: {
6987 Buf *buf = const_val->data.x_array.data.s_buf;6987 Buf *buf = const_val->data.x_array.data.s_buf;
6988 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf),6988 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf),
6989 !type_entry->data.array.is_null_terminated);6989 type_entry->data.array.sentinel == nullptr);
6990 }6990 }
6991 }6991 }
6992 zig_unreachable();6992 zig_unreachable();
...@@ -7479,7 +7479,7 @@ static void do_code_gen(CodeGen *g) {...@@ -7479,7 +7479,7 @@ static void do_code_gen(CodeGen *g) {
7479 !is_async && !have_err_ret_trace_arg;7479 !is_async && !have_err_ret_trace_arg;
7480 LLVMValueRef err_ret_array_val = nullptr;7480 LLVMValueRef err_ret_array_val = nullptr;
7481 if (have_err_ret_trace_stack) {7481 if (have_err_ret_trace_stack) {
7482 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, false);7482 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr);
7483 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));7483 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));
74847484
7485 (void)get_llvm_type(g, get_stack_trace_type(g));7485 (void)get_llvm_type(g, get_stack_trace_type(g));
...@@ -8642,6 +8642,11 @@ static void init(CodeGen *g) {...@@ -8642,6 +8642,11 @@ static void init(CodeGen *g) {
8642 g->const_void_val.type = g->builtin_types.entry_void;8642 g->const_void_val.type = g->builtin_types.entry_void;
8643 g->const_void_val.global_refs = allocate<ConstGlobalRefs>(1);8643 g->const_void_val.global_refs = allocate<ConstGlobalRefs>(1);
86448644
8645 g->const_zero_byte.special = ConstValSpecialStatic;
8646 g->const_zero_byte.type = g->builtin_types.entry_u8;
8647 g->const_zero_byte.global_refs = allocate<ConstGlobalRefs>(1);
8648 bigint_init_unsigned(&g->const_zero_byte.data.x_bigint, 0);
8649
8645 {8650 {
8646 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(PanicMsgIdCount);8651 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(PanicMsgIdCount);
8647 for (size_t i = 0; i < PanicMsgIdCount; i += 1) {8652 for (size_t i = 0; i < PanicMsgIdCount; i += 1) {
...@@ -9081,7 +9086,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -9081,7 +9086,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
9081 zig_unreachable();9086 zig_unreachable();
90829087
9083 ConstExprValue *test_fn_array = create_const_vals(1);9088 ConstExprValue *test_fn_array = create_const_vals(1);
9084 test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length, false);9089 test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length, nullptr);
9085 test_fn_array->special = ConstValSpecialStatic;9090 test_fn_array->special = ConstValSpecialStatic;
9086 test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length);9091 test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length);
90879092
src/dump_analysis.cpp-4
...@@ -992,10 +992,6 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {...@@ -992,10 +992,6 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
992 jw_object_field(jw, "len");992 jw_object_field(jw, "len");
993 jw_int(jw, 3);993 jw_int(jw, 3);
994 break;994 break;
995 case PtrLenNull:
996 jw_object_field(jw, "len");
997 jw_int(jw, 4);
998 break;
999 }995 }
1000 anal_dump_pointer_attrs(ctx, ty);996 anal_dump_pointer_attrs(ctx, ty);
1001 break;997 break;
src/ir.cpp+312-142
...@@ -67,9 +67,10 @@ enum ConstCastResultId {...@@ -67,9 +67,10 @@ enum ConstCastResultId {
67 ConstCastResultIdAsyncAllocatorType,67 ConstCastResultIdAsyncAllocatorType,
68 ConstCastResultIdBadAllowsZero,68 ConstCastResultIdBadAllowsZero,
69 ConstCastResultIdArrayChild,69 ConstCastResultIdArrayChild,
70 ConstCastResultIdBadNullTermArrays,70 ConstCastResultIdSentinelArrays,
71 ConstCastResultIdPtrLens,71 ConstCastResultIdPtrLens,
72 ConstCastResultIdCV,72 ConstCastResultIdCV,
73 ConstCastResultIdPtrSentinel,
73};74};
7475
75struct ConstCastOnly;76struct ConstCastOnly;
...@@ -94,8 +95,8 @@ struct ConstCastTypeMismatch;...@@ -94,8 +95,8 @@ struct ConstCastTypeMismatch;
94struct ConstCastArrayMismatch;95struct ConstCastArrayMismatch;
95struct ConstCastBadAllowsZero;96struct ConstCastBadAllowsZero;
96struct ConstCastBadNullTermArrays;97struct ConstCastBadNullTermArrays;
97struct ConstCastBadPtrLens;
98struct ConstCastBadCV;98struct ConstCastBadCV;
99struct ConstCastPtrSentinel;
99100
100struct ConstCastOnly {101struct ConstCastOnly {
101 ConstCastResultId id;102 ConstCastResultId id;
...@@ -113,9 +114,9 @@ struct ConstCastOnly {...@@ -113,9 +114,9 @@ struct ConstCastOnly {
113 ConstCastArg fn_arg;114 ConstCastArg fn_arg;
114 ConstCastArgNoAlias arg_no_alias;115 ConstCastArgNoAlias arg_no_alias;
115 ConstCastBadAllowsZero *bad_allows_zero;116 ConstCastBadAllowsZero *bad_allows_zero;
116 ConstCastBadNullTermArrays *bad_null_term_arrays;117 ConstCastBadNullTermArrays *sentinel_arrays;
117 ConstCastBadPtrLens *bad_ptr_lens;
118 ConstCastBadCV *bad_cv;118 ConstCastBadCV *bad_cv;
119 ConstCastPtrSentinel *bad_ptr_sentinel;
119 } data;120 } data;
120};121};
121122
...@@ -175,14 +176,13 @@ struct ConstCastBadNullTermArrays {...@@ -175,14 +176,13 @@ struct ConstCastBadNullTermArrays {
175 ZigType *actual_type;176 ZigType *actual_type;
176};177};
177178
178struct ConstCastBadPtrLens {179struct ConstCastBadCV {
179 ZigType *wanted_type;180 ZigType *wanted_type;
180 ZigType *actual_type;181 ZigType *actual_type;
181};182};
182183
183struct ConstCastBadCV {184struct ConstCastPtrSentinel {
184 ZigType *wanted_type;185 ZigType *wanted_type;
185 ZigType *actual_type;
186};186};
187187
188static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);188static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
...@@ -264,8 +264,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -264,8 +264,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
264 case ConstPtrSpecialBaseArray: {264 case ConstPtrSpecialBaseArray: {
265 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;265 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
266 if (const_val->data.x_ptr.data.base_array.elem_index == array_val->type->data.array.len) {266 if (const_val->data.x_ptr.data.base_array.elem_index == array_val->type->data.array.len) {
267 assert(array_val->type->data.array.is_null_terminated);267 result = array_val->type->data.array.sentinel;
268 result = get_null_value(array_val->type->data.array.child_type);
269 } else {268 } else {
270 expand_undef_array(g, array_val);269 expand_undef_array(g, array_val);
271 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];270 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
...@@ -317,7 +316,7 @@ static bool slice_is_const(ZigType *type) {...@@ -317,7 +316,7 @@ static bool slice_is_const(ZigType *type) {
317316
318// This function returns true when you can change the type of a ConstExprValue and the317// This function returns true when you can change the type of a ConstExprValue and the
319// value remains meaningful.318// value remains meaningful.
320static bool types_have_same_zig_comptime_repr(ZigType *expected, ZigType *actual) {319static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expected, ZigType *actual) {
321 if (expected == actual)320 if (expected == actual)
322 return true;321 return true;
323322
...@@ -366,7 +365,8 @@ static bool types_have_same_zig_comptime_repr(ZigType *expected, ZigType *actual...@@ -366,7 +365,8 @@ static bool types_have_same_zig_comptime_repr(ZigType *expected, ZigType *actual
366 case ZigTypeIdArray:365 case ZigTypeIdArray:
367 return expected->data.array.len == actual->data.array.len &&366 return expected->data.array.len == actual->data.array.len &&
368 expected->data.array.child_type == actual->data.array.child_type &&367 expected->data.array.child_type == actual->data.array.child_type &&
369 (!expected->data.array.is_null_terminated || actual->data.array.is_null_terminated);368 (expected->data.array.sentinel == nullptr || (actual->data.array.sentinel != nullptr &&
369 const_values_equal(codegen, expected->data.array.sentinel, actual->data.array.sentinel)));
370 }370 }
371 zig_unreachable();371 zig_unreachable();
372}372}
...@@ -1576,9 +1576,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_...@@ -1576,9 +1576,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_
15761576
1577static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,1577static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
1578 IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,1578 IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,
1579 IrInstruction *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero)1579 IrInstruction *sentinel, IrInstruction *align_value,
1580 uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero)
1580{1581{
1581 IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node);1582 IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node);
1583 ptr_type_of_instruction->sentinel = sentinel;
1582 ptr_type_of_instruction->align_value = align_value;1584 ptr_type_of_instruction->align_value = align_value;
1583 ptr_type_of_instruction->child_type = child_type;1585 ptr_type_of_instruction->child_type = child_type;
1584 ptr_type_of_instruction->is_const = is_const;1586 ptr_type_of_instruction->is_const = is_const;
...@@ -1588,6 +1590,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1588,6 +1590,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
1588 ptr_type_of_instruction->host_int_bytes = host_int_bytes;1590 ptr_type_of_instruction->host_int_bytes = host_int_bytes;
1589 ptr_type_of_instruction->is_allow_zero = is_allow_zero;1591 ptr_type_of_instruction->is_allow_zero = is_allow_zero;
15901592
1593 if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block);
1591 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);1594 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
1592 ir_ref_instruction(child_type, irb->current_basic_block);1595 ir_ref_instruction(child_type, irb->current_basic_block);
15931596
...@@ -1804,14 +1807,15 @@ static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstN...@@ -1804,14 +1807,15 @@ static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstN
1804}1807}
18051808
1806static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size,1809static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size,
1807 IrInstruction *child_type, bool is_null_terminated)1810 IrInstruction *sentinel, IrInstruction *child_type)
1808{1811{
1809 IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, scope, source_node);1812 IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, scope, source_node);
1810 instruction->size = size;1813 instruction->size = size;
1814 instruction->sentinel = sentinel;
1811 instruction->child_type = child_type;1815 instruction->child_type = child_type;
1812 instruction->is_null_terminated = is_null_terminated;
18131816
1814 ir_ref_instruction(size, irb->current_basic_block);1817 ir_ref_instruction(size, irb->current_basic_block);
1818 if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block);
1815 ir_ref_instruction(child_type, irb->current_basic_block);1819 ir_ref_instruction(child_type, irb->current_basic_block);
18161820
1817 return &instruction->base;1821 return &instruction->base;
...@@ -1827,20 +1831,22 @@ static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNo...@@ -1827,20 +1831,22 @@ static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNo
18271831
1828 return &instruction->base;1832 return &instruction->base;
1829}1833}
1834
1830static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,1835static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
1831 IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value, bool is_allow_zero,1836 IrInstruction *child_type, bool is_const, bool is_volatile,
1832 bool is_null_terminated)1837 IrInstruction *sentinel, IrInstruction *align_value, bool is_allow_zero)
1833{1838{
1834 IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node);1839 IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node);
1835 instruction->is_const = is_const;1840 instruction->is_const = is_const;
1836 instruction->is_volatile = is_volatile;1841 instruction->is_volatile = is_volatile;
1837 instruction->child_type = child_type;1842 instruction->child_type = child_type;
1843 instruction->sentinel = sentinel;
1838 instruction->align_value = align_value;1844 instruction->align_value = align_value;
1839 instruction->is_allow_zero = is_allow_zero;1845 instruction->is_allow_zero = is_allow_zero;
1840 instruction->is_null_terminated = is_null_terminated;
18411846
1847 if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block);
1848 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
1842 ir_ref_instruction(child_type, irb->current_basic_block);1849 ir_ref_instruction(child_type, irb->current_basic_block);
1843 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
18441850
1845 return &instruction->base;1851 return &instruction->base;
1846}1852}
...@@ -6067,9 +6073,9 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) {...@@ -6067,9 +6073,9 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) {
6067 case TokenIdStar:6073 case TokenIdStar:
6068 case TokenIdStarStar:6074 case TokenIdStarStar:
6069 return PtrLenSingle;6075 return PtrLenSingle;
6070 case TokenIdBracketStarBracket:6076 case TokenIdLBracket:
6071 return PtrLenUnknown;6077 return PtrLenUnknown;
6072 case TokenIdBracketStarCBracket:6078 case TokenIdSymbol:
6073 return PtrLenC;6079 return PtrLenC;
6074 default:6080 default:
6075 zig_unreachable();6081 zig_unreachable();
...@@ -6080,22 +6086,22 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -6080,22 +6086,22 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
6080 assert(node->type == NodeTypePointerType);6086 assert(node->type == NodeTypePointerType);
60816087
6082 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);6088 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
6083 if (node->data.pointer_type.is_null_terminated) {
6084 if (ptr_len == PtrLenUnknown) {
6085 ptr_len = PtrLenNull;
6086 } else {
6087 exec_add_error_node(irb->codegen, irb->exec, node,
6088 buf_sprintf("null-terminated pointer must be specified with [*] token"));
6089 return irb->codegen->invalid_instruction;
6090 }
6091 }
60926089
6093 bool is_const = node->data.pointer_type.is_const;6090 bool is_const = node->data.pointer_type.is_const;
6094 bool is_volatile = node->data.pointer_type.is_volatile;6091 bool is_volatile = node->data.pointer_type.is_volatile;
6095 bool is_allow_zero = node->data.pointer_type.allow_zero_token != nullptr;6092 bool is_allow_zero = node->data.pointer_type.allow_zero_token != nullptr;
6093 AstNode *sentinel_expr = node->data.pointer_type.sentinel;
6096 AstNode *expr_node = node->data.pointer_type.op_expr;6094 AstNode *expr_node = node->data.pointer_type.op_expr;
6097 AstNode *align_expr = node->data.pointer_type.align_expr;6095 AstNode *align_expr = node->data.pointer_type.align_expr;
60986096
6097 IrInstruction *sentinel;
6098 if (sentinel_expr != nullptr) {
6099 sentinel = ir_gen_node(irb, sentinel_expr, scope);
6100 if (sentinel == irb->codegen->invalid_instruction)
6101 return sentinel;
6102 } else {
6103 sentinel = nullptr;
6104 }
60996105
6100 IrInstruction *align_value;6106 IrInstruction *align_value;
6101 if (align_expr != nullptr) {6107 if (align_expr != nullptr) {
...@@ -6141,7 +6147,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -6141,7 +6147,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
6141 }6147 }
61426148
6143 return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile,6149 return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile,
6144 ptr_len, align_value, bit_offset_start, host_int_bytes, is_allow_zero);6150 ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero);
6145}6151}
61466152
6147static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node,6153static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node,
...@@ -6245,13 +6251,22 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -6245,13 +6251,22 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
6245 buf_sprintf("initializing array with struct syntax"));6251 buf_sprintf("initializing array with struct syntax"));
6246 return irb->codegen->invalid_instruction;6252 return irb->codegen->invalid_instruction;
6247 }6253 }
6254 IrInstruction *sentinel;
6255 if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) {
6256 sentinel = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.sentinel, scope);
6257 if (sentinel == irb->codegen->invalid_instruction)
6258 return sentinel;
6259 } else {
6260 sentinel = nullptr;
6261 }
6262
6248 IrInstruction *elem_type = ir_gen_node(irb,6263 IrInstruction *elem_type = ir_gen_node(irb,
6249 container_init_expr->type->data.inferred_array_type.child_type, scope);6264 container_init_expr->type->data.inferred_array_type.child_type, scope);
6250 if (elem_type == irb->codegen->invalid_instruction)6265 if (elem_type == irb->codegen->invalid_instruction)
6251 return elem_type;6266 return elem_type;
6252 size_t item_count = container_init_expr->entries.length;6267 size_t item_count = container_init_expr->entries.length;
6253 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);6268 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
6254 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type, false);6269 container_type = ir_build_array_type(irb, scope, node, item_count_inst, sentinel, elem_type);
6255 } else {6270 } else {
6256 container_type = ir_gen_node(irb, container_init_expr->type, scope);6271 container_type = ir_gen_node(irb, container_init_expr->type, scope);
6257 if (container_type == irb->codegen->invalid_instruction)6272 if (container_type == irb->codegen->invalid_instruction)
...@@ -6975,10 +6990,20 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6975,10 +6990,20 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
6975 bool is_const = node->data.array_type.is_const;6990 bool is_const = node->data.array_type.is_const;
6976 bool is_volatile = node->data.array_type.is_volatile;6991 bool is_volatile = node->data.array_type.is_volatile;
6977 bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr;6992 bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr;
6978 bool is_null_terminated = node->data.array_type.is_null_terminated;6993 AstNode *sentinel_expr = node->data.array_type.sentinel;
6979 AstNode *align_expr = node->data.array_type.align_expr;6994 AstNode *align_expr = node->data.array_type.align_expr;
69806995
6981 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);6996 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
6997
6998 IrInstruction *sentinel;
6999 if (sentinel_expr != nullptr) {
7000 sentinel = ir_gen_node(irb, sentinel_expr, comptime_scope);
7001 if (sentinel == irb->codegen->invalid_instruction)
7002 return sentinel;
7003 } else {
7004 sentinel = nullptr;
7005 }
7006
6982 if (size_node) {7007 if (size_node) {
6983 if (is_const) {7008 if (is_const) {
6984 add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type"));7009 add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type"));
...@@ -7005,7 +7030,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7005,7 +7030,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
7005 if (child_type == irb->codegen->invalid_instruction)7030 if (child_type == irb->codegen->invalid_instruction)
7006 return child_type;7031 return child_type;
70077032
7008 return ir_build_array_type(irb, scope, node, size_value, child_type, is_null_terminated);7033 return ir_build_array_type(irb, scope, node, size_value, sentinel, child_type);
7009 } else {7034 } else {
7010 IrInstruction *align_value;7035 IrInstruction *align_value;
7011 if (align_expr != nullptr) {7036 if (align_expr != nullptr) {
...@@ -7020,8 +7045,8 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7020,8 +7045,8 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
7020 if (child_type == irb->codegen->invalid_instruction)7045 if (child_type == irb->codegen->invalid_instruction)
7021 return child_type;7046 return child_type;
70227047
7023 return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, align_value, is_allow_zero,7048 return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, sentinel,
7024 is_null_terminated);7049 align_value, is_allow_zero);
7025 }7050 }
7026}7051}
70277052
...@@ -8698,7 +8723,7 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal...@@ -8698,7 +8723,7 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
8698 case OnePossibleValueYes:8723 case OnePossibleValueYes:
8699 return get_the_one_possible_value(codegen, expected_type);8724 return get_the_one_possible_value(codegen, expected_type);
8700 }8725 }
8701 if (!types_have_same_zig_comptime_repr(expected_type, val->type)) {8726 if (!types_have_same_zig_comptime_repr(codegen, expected_type, val->type)) {
8702 if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))8727 if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))
8703 return nullptr;8728 return nullptr;
8704 return const_ptr_pointee_unchecked(codegen, const_val);8729 return const_ptr_pointee_unchecked(codegen, const_val);
...@@ -9846,7 +9871,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9846,7 +9871,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9846 // alignment can be decreased9871 // alignment can be decreased
9847 // bit offset attributes must match exactly9872 // bit offset attributes must match exactly
9848 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one9873 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
9849 // PtrLenNull can coerce into PtrLenUnknown9874 // sentinel-terminated pointers can coerce into PtrLenUnknown
9850 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);9875 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
9851 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);9876 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
9852 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);9877 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
...@@ -9858,15 +9883,20 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9858,15 +9883,20 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9858 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&9883 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
9859 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);9884 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
9860 if (wanted_opt_or_ptr && actual_opt_or_ptr) {9885 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
9861 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
9862 bool ok_null_term_ptrs =9886 bool ok_null_term_ptrs =
9863 actual_ptr_type->data.pointer.ptr_len == PtrLenNull ||9887 wanted_ptr_type->data.pointer.sentinel == nullptr ||
9864 wanted_ptr_type->data.pointer.ptr_len == PtrLenUnknown;9888 (actual_ptr_type->data.pointer.sentinel != nullptr &&
9865 if (!(ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr || ok_null_term_ptrs)) {9889 const_values_equal(ira->codegen, wanted_ptr_type->data.pointer.sentinel,
9890 actual_ptr_type->data.pointer.sentinel));
9891 if (!ok_null_term_ptrs) {
9892 result.id = ConstCastResultIdPtrSentinel;
9893 result.data.bad_ptr_sentinel = allocate_nonzero<ConstCastPtrSentinel>(1);
9894 result.data.bad_ptr_sentinel->wanted_type = wanted_type;
9895 return result;
9896 }
9897 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
9898 if (!(ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr)) {
9866 result.id = ConstCastResultIdPtrLens;9899 result.id = ConstCastResultIdPtrLens;
9867 result.data.bad_ptr_lens = allocate_nonzero<ConstCastBadPtrLens>(1);
9868 result.data.bad_ptr_lens->wanted_type = wanted_type;
9869 result.data.bad_ptr_lens->actual_type = actual_type;
9870 return result;9900 return result;
9871 }9901 }
98729902
...@@ -9944,14 +9974,15 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9944,14 +9974,15 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9944 result.data.array_mismatch->actual_child = actual_type->data.array.child_type;9974 result.data.array_mismatch->actual_child = actual_type->data.array.child_type;
9945 return result;9975 return result;
9946 }9976 }
9947 bool ok_null_terminated = !wanted_type->data.array.is_null_terminated ||9977 bool ok_null_terminated = (wanted_type->data.array.sentinel == nullptr) ||
9948 actual_type->data.array.is_null_terminated;9978 (actual_type->data.array.sentinel != nullptr &&
9979 const_values_equal(ira->codegen, wanted_type->data.array.sentinel, actual_type->data.array.sentinel));
9949 if (!ok_null_terminated) {9980 if (!ok_null_terminated) {
9950 result.id = ConstCastResultIdBadNullTermArrays;9981 result.id = ConstCastResultIdSentinelArrays;
9951 result.data.bad_null_term_arrays = allocate_nonzero<ConstCastBadNullTermArrays>(1);9982 result.data.sentinel_arrays = allocate_nonzero<ConstCastBadNullTermArrays>(1);
9952 result.data.bad_null_term_arrays->child = child;9983 result.data.sentinel_arrays->child = child;
9953 result.data.bad_null_term_arrays->wanted_type = wanted_type;9984 result.data.sentinel_arrays->wanted_type = wanted_type;
9954 result.data.bad_null_term_arrays->actual_type = actual_type;9985 result.data.sentinel_arrays->actual_type = actual_type;
9955 return result;9986 return result;
9956 }9987 }
9957 return result;9988 return result;
...@@ -10781,8 +10812,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10781,8 +10812,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10781 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&10812 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
10782 (cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||10813 (cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
10783 prev_type->data.pointer.child_type->data.array.len == 0) &&10814 prev_type->data.pointer.child_type->data.array.len == 0) &&
10784 (cur_type->data.pointer.child_type->data.array.is_null_terminated ||10815 (
10785 !prev_type->data.pointer.child_type->data.array.is_null_terminated) &&10816 prev_type->data.pointer.child_type->data.array.sentinel == nullptr ||
10817 (cur_type->data.pointer.child_type->data.array.sentinel != nullptr &&
10818 const_values_equal(ira->codegen, prev_type->data.pointer.child_type->data.array.sentinel,
10819 cur_type->data.pointer.child_type->data.array.sentinel))
10820 ) &&
10786 types_match_const_cast_only(ira,10821 types_match_const_cast_only(ira,
10787 cur_type->data.pointer.child_type->data.array.child_type,10822 cur_type->data.pointer.child_type->data.array.child_type,
10788 prev_type->data.pointer.child_type->data.array.child_type,10823 prev_type->data.pointer.child_type->data.array.child_type,
...@@ -10798,8 +10833,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10798,8 +10833,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10798 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&10833 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
10799 (prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||10834 (prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
10800 cur_type->data.pointer.child_type->data.array.len == 0) &&10835 cur_type->data.pointer.child_type->data.array.len == 0) &&
10801 (prev_type->data.pointer.child_type->data.array.is_null_terminated ||10836 (
10802 !cur_type->data.pointer.child_type->data.array.is_null_terminated) &&10837 cur_type->data.pointer.child_type->data.array.sentinel == nullptr ||
10838 (prev_type->data.pointer.child_type->data.array.sentinel != nullptr &&
10839 const_values_equal(ira->codegen, cur_type->data.pointer.child_type->data.array.sentinel,
10840 prev_type->data.pointer.child_type->data.array.sentinel))
10841 ) &&
10803 types_match_const_cast_only(ira,10842 types_match_const_cast_only(ira,
10804 prev_type->data.pointer.child_type->data.array.child_type,10843 prev_type->data.pointer.child_type->data.array.child_type,
10805 cur_type->data.pointer.child_type->data.array.child_type,10844 cur_type->data.pointer.child_type->data.array.child_type,
...@@ -10871,11 +10910,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10871,11 +10910,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10871 } else if (prev_inst->value.type->id == ZigTypeIdPointer) {10910 } else if (prev_inst->value.type->id == ZigTypeIdPointer) {
10872 ZigType *array_type = prev_inst->value.type->data.pointer.child_type;10911 ZigType *array_type = prev_inst->value.type->data.pointer.child_type;
10873 src_assert(array_type->id == ZigTypeIdArray, source_node);10912 src_assert(array_type->id == ZigTypeIdArray, source_node);
10874 ZigType *ptr_type = get_pointer_to_type_extra(10913 ZigType *ptr_type = get_pointer_to_type_extra2(
10875 ira->codegen, array_type->data.array.child_type,10914 ira->codegen, array_type->data.array.child_type,
10876 prev_inst->value.type->data.pointer.is_const, false,10915 prev_inst->value.type->data.pointer.is_const, false,
10877 array_type->data.array.is_null_terminated ? PtrLenNull : PtrLenUnknown,10916 PtrLenUnknown,
10878 0, 0, 0, false);10917 0, 0, 0, false,
10918 VECTOR_INDEX_NONE, nullptr, array_type->data.array.sentinel);
10879 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);10919 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
10880 if (err_set_type != nullptr) {10920 if (err_set_type != nullptr) {
10881 return get_error_union_type(ira->codegen, err_set_type, slice_type);10921 return get_error_union_type(ira->codegen, err_set_type, slice_type);
...@@ -11682,7 +11722,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so...@@ -11682,7 +11722,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
11682 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,11722 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
11683 source_instr->scope, source_instr->source_node);11723 source_instr->scope, source_instr->source_node);
11684 const_instruction->base.value.special = ConstValSpecialStatic;11724 const_instruction->base.value.special = ConstValSpecialStatic;
11685 if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) {11725 if (types_have_same_zig_comptime_repr(ira->codegen, wanted_type, payload_type)) {
11686 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);11726 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
11687 } else {11727 } else {
11688 const_instruction->base.value.data.x_optional = val;11728 const_instruction->base.value.data.x_optional = val;
...@@ -12601,14 +12641,24 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -12601,14 +12641,24 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
12601 break;12641 break;
12602 }12642 }
12603 case ConstCastResultIdPtrLens: {12643 case ConstCastResultIdPtrLens: {
12604 ZigType *wanted_type = cast_result->data.bad_ptr_lens->wanted_type;12644 add_error_note(ira->codegen, parent_msg, source_node,
12605 ZigType *actual_type = cast_result->data.bad_ptr_lens->actual_type;12645 buf_sprintf("pointer length mismatch"));
12606 bool wanted_null_term = wanted_type->data.pointer.ptr_len == PtrLenNull;12646 break;
12607 bool actual_null_term = actual_type->data.pointer.ptr_len == PtrLenNull;12647 }
12608 if (wanted_null_term && !actual_null_term) {12648 case ConstCastResultIdPtrSentinel: {
12609 add_error_note(ira->codegen, parent_msg, source_node,12649 ZigType *wanted_type = cast_result->data.bad_ptr_sentinel->wanted_type;
12610 buf_sprintf("destination type requires null termination"));12650 Buf *msg = buf_sprintf("destination pointer requires a terminating '");
12611 }12651 render_const_value(ira->codegen, msg, wanted_type->data.pointer.sentinel);
12652 buf_appendf(msg, "' sentinel value");
12653 add_error_note(ira->codegen, parent_msg, source_node, msg);
12654 break;
12655 }
12656 case ConstCastResultIdSentinelArrays: {
12657 ZigType *wanted_type = cast_result->data.sentinel_arrays->wanted_type;
12658 Buf *msg = buf_sprintf("destination array requires a terminating '");
12659 render_const_value(ira->codegen, msg, wanted_type->data.pointer.sentinel);
12660 buf_appendf(msg, "' sentinel value");
12661 add_error_note(ira->codegen, parent_msg, source_node, msg);
12612 break;12662 break;
12613 }12663 }
12614 case ConstCastResultIdCV: {12664 case ConstCastResultIdCV: {
...@@ -12642,7 +12692,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -12642,7 +12692,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
12642 case ConstCastResultIdUnresolvedInferredErrSet: // TODO12692 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
12643 case ConstCastResultIdAsyncAllocatorType: // TODO12693 case ConstCastResultIdAsyncAllocatorType: // TODO
12644 case ConstCastResultIdArrayChild: // TODO12694 case ConstCastResultIdArrayChild: // TODO
12645 case ConstCastResultIdBadNullTermArrays: // TODO
12646 break;12695 break;
12647 }12696 }
12648}12697}
...@@ -13013,16 +13062,18 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -13013,16 +13062,18 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1301313062
13014 // *[N]T to [*]T and [*c]T13063 // *[N]T to [*]T and [*c]T
13015 if (wanted_type->id == ZigTypeIdPointer &&13064 if (wanted_type->id == ZigTypeIdPointer &&
13016 (wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC ||13065 (wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC) &&
13017 wanted_type->data.pointer.ptr_len == PtrLenNull) &&
13018 actual_type->id == ZigTypeIdPointer &&13066 actual_type->id == ZigTypeIdPointer &&
13019 actual_type->data.pointer.ptr_len == PtrLenSingle &&13067 actual_type->data.pointer.ptr_len == PtrLenSingle &&
13020 actual_type->data.pointer.child_type->id == ZigTypeIdArray &&13068 actual_type->data.pointer.child_type->id == ZigTypeIdArray &&
13021 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&13069 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
13022 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))13070 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
13023 {13071 {
13024 if (wanted_type->data.pointer.ptr_len != PtrLenNull ||13072 ZigType *actual_array_type = actual_type->data.pointer.child_type;
13025 actual_type->data.pointer.child_type->data.array.is_null_terminated)13073 if (wanted_type->data.pointer.sentinel == nullptr ||
13074 (actual_array_type->data.array.sentinel != nullptr &&
13075 const_values_equal(ira->codegen, wanted_type->data.pointer.sentinel,
13076 actual_array_type->data.array.sentinel)))
13026 {13077 {
13027 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))13078 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
13028 return ira->codegen->invalid_instruction;13079 return ira->codegen->invalid_instruction;
...@@ -14741,7 +14792,6 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {...@@ -14741,7 +14792,6 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
14741 case PtrLenSingle:14792 case PtrLenSingle:
14742 return lhs_type->data.pointer.child_type->id == ZigTypeIdArray;14793 return lhs_type->data.pointer.child_type->id == ZigTypeIdArray;
14743 case PtrLenUnknown:14794 case PtrLenUnknown:
14744 case PtrLenNull:
14745 case PtrLenC:14795 case PtrLenC:
14746 return true;14796 return true;
14747 }14797 }
...@@ -15007,7 +15057,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15007,7 +15057,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15007 if (!op2_val)15057 if (!op2_val)
15008 return ira->codegen->invalid_instruction;15058 return ira->codegen->invalid_instruction;
1500915059
15010 bool is_null_terminated = false;15060 ConstExprValue *sentinel1 = nullptr;
15011 ConstExprValue *op1_array_val;15061 ConstExprValue *op1_array_val;
15012 size_t op1_array_index;15062 size_t op1_array_index;
15013 size_t op1_array_end;15063 size_t op1_array_end;
...@@ -15017,16 +15067,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15017,16 +15067,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15017 op1_array_val = op1_val;15067 op1_array_val = op1_val;
15018 op1_array_index = 0;15068 op1_array_index = 0;
15019 op1_array_end = op1_type->data.array.len;15069 op1_array_end = op1_type->data.array.len;
15070 sentinel1 = op1_type->data.array.sentinel;
15020 } else if (op1_type->id == ZigTypeIdPointer &&15071 } else if (op1_type->id == ZigTypeIdPointer &&
15021 op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&15072 op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
15022 op1_type->data.pointer.ptr_len == PtrLenNull &&15073 op1_type->data.pointer.sentinel != nullptr &&
15023 op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray)15074 op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
15024 {15075 {
15025 child_type = op1_type->data.pointer.child_type;15076 child_type = op1_type->data.pointer.child_type;
15026 op1_array_val = op1_val->data.x_ptr.data.base_array.array_val;15077 op1_array_val = op1_val->data.x_ptr.data.base_array.array_val;
15027 op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index;15078 op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index;
15028 op1_array_end = op1_array_val->type->data.array.len;15079 op1_array_end = op1_array_val->type->data.array.len;
15029 is_null_terminated = true;15080 sentinel1 = op1_type->data.pointer.sentinel;
15030 } else if (is_slice(op1_type)) {15081 } else if (is_slice(op1_type)) {
15031 ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry;15082 ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry;
15032 child_type = ptr_type->data.pointer.child_type;15083 child_type = ptr_type->data.pointer.child_type;
...@@ -15036,6 +15087,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15036,6 +15087,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15036 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;15087 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
15037 ConstExprValue *len_val = op1_val->data.x_struct.fields[slice_len_index];15088 ConstExprValue *len_val = op1_val->data.x_struct.fields[slice_len_index];
15038 op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint);15089 op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint);
15090 sentinel1 = ptr_type->data.pointer.sentinel;
15039 } else if (op1_type->id == ZigTypeIdPointer && op1_type->data.pointer.ptr_len == PtrLenSingle &&15091 } else if (op1_type->id == ZigTypeIdPointer && op1_type->data.pointer.ptr_len == PtrLenSingle &&
15040 op1_type->data.pointer.child_type->id == ZigTypeIdArray)15092 op1_type->data.pointer.child_type->id == ZigTypeIdArray)
15041 {15093 {
...@@ -15046,13 +15098,14 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15046,13 +15098,14 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15046 return ira->codegen->invalid_instruction;15098 return ira->codegen->invalid_instruction;
15047 op1_array_index = 0;15099 op1_array_index = 0;
15048 op1_array_end = array_type->data.array.len;15100 op1_array_end = array_type->data.array.len;
15049 is_null_terminated = is_null_terminated || array_type->data.array.is_null_terminated;15101 sentinel1 = array_type->data.array.sentinel;
15050 } else {15102 } else {
15051 ir_add_error(ira, op1,15103 ir_add_error(ira, op1,
15052 buf_sprintf("expected array, found '%s'", buf_ptr(&op1->value.type->name)));15104 buf_sprintf("expected array, found '%s'", buf_ptr(&op1->value.type->name)));
15053 return ira->codegen->invalid_instruction;15105 return ira->codegen->invalid_instruction;
15054 }15106 }
1505515107
15108 ConstExprValue *sentinel2 = nullptr;
15056 ConstExprValue *op2_array_val;15109 ConstExprValue *op2_array_val;
15057 size_t op2_array_index;15110 size_t op2_array_index;
15058 size_t op2_array_end;15111 size_t op2_array_end;
...@@ -15062,15 +15115,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15062,15 +15115,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15062 op2_array_val = op2_val;15115 op2_array_val = op2_val;
15063 op2_array_index = 0;15116 op2_array_index = 0;
15064 op2_array_end = op2_array_val->type->data.array.len;15117 op2_array_end = op2_array_val->type->data.array.len;
15118 sentinel2 = op2_type->data.array.sentinel;
15065 } else if (op2_type->id == ZigTypeIdPointer &&15119 } else if (op2_type->id == ZigTypeIdPointer &&
15066 op2_type->data.pointer.ptr_len == PtrLenNull &&15120 op2_type->data.pointer.sentinel != nullptr &&
15067 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray)15121 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
15068 {15122 {
15069 op2_type_valid = op2_type->data.pointer.child_type == child_type;15123 op2_type_valid = op2_type->data.pointer.child_type == child_type;
15070 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;15124 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
15071 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;15125 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
15072 op2_array_end = op2_array_val->type->data.array.len;15126 op2_array_end = op2_array_val->type->data.array.len;
15073 is_null_terminated = true;15127
15128 sentinel2 = op2_type->data.pointer.sentinel;
15074 } else if (is_slice(op2_type)) {15129 } else if (is_slice(op2_type)) {
15075 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry;15130 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry;
15076 op2_type_valid = ptr_type->data.pointer.child_type == child_type;15131 op2_type_valid = ptr_type->data.pointer.child_type == child_type;
...@@ -15080,6 +15135,8 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15080,6 +15135,8 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15080 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;15135 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
15081 ConstExprValue *len_val = op2_val->data.x_struct.fields[slice_len_index];15136 ConstExprValue *len_val = op2_val->data.x_struct.fields[slice_len_index];
15082 op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint);15137 op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint);
15138
15139 sentinel2 = ptr_type->data.pointer.sentinel;
15083 } else if (op2_type->id == ZigTypeIdPointer && op2_type->data.pointer.ptr_len == PtrLenSingle &&15140 } else if (op2_type->id == ZigTypeIdPointer && op2_type->data.pointer.ptr_len == PtrLenSingle &&
15084 op2_type->data.pointer.child_type->id == ZigTypeIdArray)15141 op2_type->data.pointer.child_type->id == ZigTypeIdArray)
15085 {15142 {
...@@ -15090,7 +15147,8 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15090,7 +15147,8 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15090 return ira->codegen->invalid_instruction;15147 return ira->codegen->invalid_instruction;
15091 op2_array_index = 0;15148 op2_array_index = 0;
15092 op2_array_end = array_type->data.array.len;15149 op2_array_end = array_type->data.array.len;
15093 is_null_terminated = is_null_terminated || array_type->data.array.is_null_terminated;15150
15151 sentinel2 = array_type->data.array.sentinel;
15094 } else {15152 } else {
15095 ir_add_error(ira, op2,15153 ir_add_error(ira, op2,
15096 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));15154 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
...@@ -15103,6 +15161,19 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15103,6 +15161,19 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15103 return ira->codegen->invalid_instruction;15161 return ira->codegen->invalid_instruction;
15104 }15162 }
1510515163
15164 ConstExprValue *sentinel;
15165 if (sentinel1 != nullptr && sentinel2 != nullptr) {
15166 // When there is a sentinel mismatch, no sentinel on the result. The type system
15167 // will catch this if it is a problem.
15168 sentinel = const_values_equal(ira->codegen, sentinel1, sentinel2) ? sentinel1 : nullptr;
15169 } else if (sentinel1 != nullptr) {
15170 sentinel = sentinel1;
15171 } else if (sentinel2 != nullptr) {
15172 sentinel = sentinel2;
15173 } else {
15174 sentinel = nullptr;
15175 }
15176
15106 // The type of result is populated in the following if blocks15177 // The type of result is populated in the following if blocks
15107 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);15178 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
15108 ConstExprValue *out_val = &result->value;15179 ConstExprValue *out_val = &result->value;
...@@ -15110,24 +15181,25 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15110,24 +15181,25 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15110 ConstExprValue *out_array_val;15181 ConstExprValue *out_array_val;
15111 size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);15182 size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);
15112 if (op1_type->id == ZigTypeIdArray || op2_type->id == ZigTypeIdArray) {15183 if (op1_type->id == ZigTypeIdArray || op2_type->id == ZigTypeIdArray) {
15113 result->value.type = get_array_type(ira->codegen, child_type, new_len, false);15184 result->value.type = get_array_type(ira->codegen, child_type, new_len, sentinel);
1511415185
15115 out_array_val = out_val;15186 out_array_val = out_val;
15116 } else if (op1_type->id == ZigTypeIdPointer || op2_type->id == ZigTypeIdPointer) {15187 } else if (op1_type->id == ZigTypeIdPointer || op2_type->id == ZigTypeIdPointer) {
15117 out_array_val = create_const_vals(1);15188 out_array_val = create_const_vals(1);
15118 out_array_val->special = ConstValSpecialStatic;15189 out_array_val->special = ConstValSpecialStatic;
15119 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, is_null_terminated);15190 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
1512015191
15121 out_val->data.x_ptr.special = ConstPtrSpecialRef;15192 out_val->data.x_ptr.special = ConstPtrSpecialRef;
15122 out_val->data.x_ptr.data.ref.pointee = out_array_val;15193 out_val->data.x_ptr.data.ref.pointee = out_array_val;
15123 out_val->type = get_pointer_to_type(ira->codegen, out_array_val->type, true);15194 out_val->type = get_pointer_to_type(ira->codegen, out_array_val->type, true);
15124 } else if (is_slice(op1_type) || is_slice(op2_type)) {15195 } else if (is_slice(op1_type) || is_slice(op2_type)) {
15125 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,15196 ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen, child_type,
15126 true, false, PtrLenUnknown, 0, 0, 0, false);15197 true, false, PtrLenUnknown, 0, 0, 0, false,
15198 VECTOR_INDEX_NONE, nullptr, sentinel);
15127 result->value.type = get_slice_type(ira->codegen, ptr_type);15199 result->value.type = get_slice_type(ira->codegen, ptr_type);
15128 out_array_val = create_const_vals(1);15200 out_array_val = create_const_vals(1);
15129 out_array_val->special = ConstValSpecialStatic;15201 out_array_val->special = ConstValSpecialStatic;
15130 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, false);15202 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
1513115203
15132 out_val->data.x_struct.fields = alloc_const_vals_ptrs(2);15204 out_val->data.x_struct.fields = alloc_const_vals_ptrs(2);
1513315205
...@@ -15141,12 +15213,12 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15141,12 +15213,12 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15141 out_val->data.x_struct.fields[slice_len_index]->special = ConstValSpecialStatic;15213 out_val->data.x_struct.fields[slice_len_index]->special = ConstValSpecialStatic;
15142 bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len);15214 bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len);
15143 } else {15215 } else {
15144 result->value.type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenNull,15216 result->value.type = get_pointer_to_type_extra2(ira->codegen, child_type, true, false, PtrLenUnknown,
15145 0, 0, 0, false);15217 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, sentinel);
1514615218
15147 out_array_val = create_const_vals(1);15219 out_array_val = create_const_vals(1);
15148 out_array_val->special = ConstValSpecialStatic;15220 out_array_val->special = ConstValSpecialStatic;
15149 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, false);15221 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
15150 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;15222 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
15151 out_val->data.x_ptr.data.base_array.array_val = out_array_val;15223 out_val->data.x_ptr.data.base_array.array_val = out_array_val;
15152 out_val->data.x_ptr.data.base_array.elem_index = 0;15224 out_val->data.x_ptr.data.base_array.elem_index = 0;
...@@ -15159,26 +15231,36 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -15159,26 +15231,36 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
15159 return result;15231 return result;
15160 }15232 }
1516115233
15162 out_array_val->data.x_array.data.s_none.elements = create_const_vals(new_len);15234 uint64_t full_len = new_len + ((sentinel != nullptr) ? 1 : 0);
15235 out_array_val->data.x_array.data.s_none.elements = create_const_vals(full_len);
15163 // TODO handle the buf case here for an optimization15236 // TODO handle the buf case here for an optimization
15164 expand_undef_array(ira->codegen, op1_array_val);15237 expand_undef_array(ira->codegen, op1_array_val);
15165 expand_undef_array(ira->codegen, op2_array_val);15238 expand_undef_array(ira->codegen, op2_array_val);
1516615239
15167 size_t next_index = 0;15240 size_t next_index = 0;
15168 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {15241 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {
15169 copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],15242 ConstExprValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index];
15170 &op1_array_val->data.x_array.data.s_none.elements[i], true);15243 copy_const_val(elem_dest_val, &op1_array_val->data.x_array.data.s_none.elements[i], false);
15244 elem_dest_val->parent.id = ConstParentIdArray;
15245 elem_dest_val->parent.data.p_array.array_val = out_array_val;
15246 elem_dest_val->parent.data.p_array.elem_index = next_index;
15171 }15247 }
15172 for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {15248 for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {
15173 copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],15249 ConstExprValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index];
15174 &op2_array_val->data.x_array.data.s_none.elements[i], true);15250 copy_const_val(elem_dest_val, &op2_array_val->data.x_array.data.s_none.elements[i], false);
15175 }15251 elem_dest_val->parent.id = ConstParentIdArray;
15176 if (next_index < new_len) {15252 elem_dest_val->parent.data.p_array.array_val = out_array_val;
15177 ConstExprValue *null_byte = &out_array_val->data.x_array.data.s_none.elements[next_index];15253 elem_dest_val->parent.data.p_array.elem_index = next_index;
15178 init_const_unsigned_negative(null_byte, child_type, 0, false);15254 }
15255 if (next_index < full_len) {
15256 ConstExprValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index];
15257 copy_const_val(elem_dest_val, sentinel, false);
15258 elem_dest_val->parent.id = ConstParentIdArray;
15259 elem_dest_val->parent.data.p_array.array_val = out_array_val;
15260 elem_dest_val->parent.data.p_array.elem_index = next_index;
15179 next_index += 1;15261 next_index += 1;
15180 }15262 }
15181 assert(next_index == new_len);15263 assert(next_index == full_len);
1518215264
15183 return result;15265 return result;
15184}15266}
...@@ -15230,7 +15312,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -15230,7 +15312,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
1523015312
15231 ZigType *child_type = array_type->data.array.child_type;15313 ZigType *child_type = array_type->data.array.child_type;
15232 ZigType *result_array_type = get_array_type(ira->codegen, child_type, new_array_len,15314 ZigType *result_array_type = get_array_type(ira->codegen, child_type, new_array_len,
15233 array_type->data.array.is_null_terminated);15315 array_type->data.array.sentinel);
1523415316
15235 IrInstruction *array_result;15317 IrInstruction *array_result;
15236 if (array_val->special == ConstValSpecialUndef || array_val->data.x_array.special == ConstArraySpecialUndef) {15318 if (array_val->special == ConstValSpecialUndef || array_val->data.x_array.special == ConstArraySpecialUndef) {
...@@ -15250,7 +15332,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -15250,7 +15332,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
1525015332
15251 // TODO optimize the buf case15333 // TODO optimize the buf case
15252 expand_undef_array(ira->codegen, array_val);15334 expand_undef_array(ira->codegen, array_val);
15253 size_t extra_null_term = array_type->data.array.is_null_terminated ? 1 : 0;15335 size_t extra_null_term = (array_type->data.array.sentinel != nullptr) ? 1 : 0;
15254 out_val->data.x_array.data.s_none.elements = create_const_vals(new_array_len + extra_null_term);15336 out_val->data.x_array.data.s_none.elements = create_const_vals(new_array_len + extra_null_term);
1525515337
15256 uint64_t i = 0;15338 uint64_t i = 0;
...@@ -15266,10 +15348,9 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -15266,10 +15348,9 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
15266 }15348 }
15267 assert(i == new_array_len);15349 assert(i == new_array_len);
1526815350
15269 if (array_type->data.array.is_null_terminated) {15351 if (array_type->data.array.sentinel != nullptr) {
15270 ConstExprValue *null_value = get_null_value(array_type->data.array.child_type);
15271 ConstExprValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i];15352 ConstExprValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i];
15272 copy_const_val(elem_dest_val, null_value, false);15353 copy_const_val(elem_dest_val, array_type->data.array.sentinel, false);
15273 elem_dest_val->parent.id = ConstParentIdArray;15354 elem_dest_val->parent.id = ConstParentIdArray;
15274 elem_dest_val->parent.data.p_array.array_val = out_val;15355 elem_dest_val->parent.data.p_array.array_val = out_val;
15275 elem_dest_val->parent.data.p_array.elem_index = i;15356 elem_dest_val->parent.data.p_array.elem_index = i;
...@@ -17565,7 +17646,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -17565,7 +17646,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
17565 size_t dst_size = type_size(codegen, out_val->type);17646 size_t dst_size = type_size(codegen, out_val->type);
1756617647
17567 if (dst_size <= src_size) {17648 if (dst_size <= src_size) {
17568 if (src_size == dst_size && types_have_same_zig_comptime_repr(out_val->type, pointee->type)) {17649 if (src_size == dst_size && types_have_same_zig_comptime_repr(codegen, out_val->type, pointee->type)) {
17569 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);17650 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);
17570 return ErrorNone;17651 return ErrorNone;
17571 }17652 }
...@@ -18316,11 +18397,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18316,11 +18397,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18316 uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);18397 uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);
18317 if (array_type->id == ZigTypeIdArray) {18398 if (array_type->id == ZigTypeIdArray) {
18318 uint64_t array_len = array_type->data.array.len;18399 uint64_t array_len = array_type->data.array.len;
18319 if (index == array_len && array_type->data.array.is_null_terminated) {18400 if (index == array_len && array_type->data.array.sentinel != nullptr) {
18320 ZigType *elem_type = array_type->data.array.child_type;18401 ZigType *elem_type = array_type->data.array.child_type;
18321 IrInstruction *null_element = ir_const(ira, &elem_ptr_instruction->base, elem_type);18402 IrInstruction *sentinel_elem = ir_const(ira, &elem_ptr_instruction->base, elem_type);
18322 null_element->value = *get_null_value(elem_type);18403 copy_const_val(&sentinel_elem->value, array_type->data.array.sentinel, false);
18323 return ir_get_ref(ira, &elem_ptr_instruction->base, null_element, true, false);18404 return ir_get_ref(ira, &elem_ptr_instruction->base, sentinel_elem, true, false);
18324 }18405 }
18325 if (index >= array_len) {18406 if (index >= array_len) {
18326 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,18407 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
...@@ -18337,7 +18418,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18337,7 +18418,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18337 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,18418 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
18338 elem_ptr_instruction->ptr_len,18419 elem_ptr_instruction->ptr_len,
18339 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,18420 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,
18340 nullptr);18421 nullptr, nullptr);
18341 } else if (return_type->data.pointer.explicit_alignment != 0) {18422 } else if (return_type->data.pointer.explicit_alignment != 0) {
18342 // figure out the largest alignment possible18423 // figure out the largest alignment possible
1834318424
...@@ -18457,7 +18538,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18457,7 +18538,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18457 new_index = offset + index;18538 new_index = offset + index;
18458 ZigType *array_type = array_ptr_val->data.x_ptr.data.base_array.array_val->type;18539 ZigType *array_type = array_ptr_val->data.x_ptr.data.base_array.array_val->type;
18459 mem_size = array_type->data.array.len;18540 mem_size = array_type->data.array.len;
18460 if (array_type->data.array.is_null_terminated) {18541 if (array_type->data.array.sentinel != nullptr) {
18461 mem_size += 1;18542 mem_size += 1;
18462 }18543 }
18463 old_size = mem_size - offset;18544 old_size = mem_size - offset;
...@@ -18579,7 +18660,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18579,7 +18660,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18579 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,18660 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
18580 elem_ptr_instruction->ptr_len,18661 elem_ptr_instruction->ptr_len,
18581 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME,18662 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME,
18582 nullptr);18663 nullptr, nullptr);
18583 } else {18664 } else {
18584 // runtime known element index18665 // runtime known element index
18585 switch (type_requires_comptime(ira->codegen, return_type)) {18666 switch (type_requires_comptime(ira->codegen, return_type)) {
...@@ -18783,7 +18864,7 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n...@@ -18783,7 +18864,7 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n
18783 ZigType *elem_type = ira->codegen->builtin_types.entry_var;18864 ZigType *elem_type = ira->codegen->builtin_types.entry_var;
18784 ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,18865 ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
18785 container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile,18866 container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile,
18786 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field);18867 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field, nullptr);
1878718868
18788 if (instr_is_comptime(container_ptr)) {18869 if (instr_is_comptime(container_ptr)) {
18789 IrInstruction *result = ir_const(ira, source_instr, field_ptr_type);18870 IrInstruction *result = ir_const(ira, source_instr, field_ptr_type);
...@@ -19565,6 +19646,12 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -19565,6 +19646,12 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
19565 return ira->codegen->invalid_instruction;19646 return ira->codegen->invalid_instruction;
19566 }19647 }
1956719648
19649 if (slice_type_instruction->sentinel != nullptr) {
19650 lazy_slice_type->sentinel = slice_type_instruction->sentinel->child;
19651 if (ir_resolve_const(ira, lazy_slice_type->sentinel, LazyOk) == nullptr)
19652 return ira->codegen->invalid_instruction;
19653 }
19654
19568 lazy_slice_type->elem_type = slice_type_instruction->child_type->child;19655 lazy_slice_type->elem_type = slice_type_instruction->child_type->child;
19569 if (ir_resolve_type_lazy(ira, lazy_slice_type->elem_type) == nullptr)19656 if (ir_resolve_type_lazy(ira, lazy_slice_type->elem_type) == nullptr)
19570 return ira->codegen->invalid_instruction;19657 return ira->codegen->invalid_instruction;
...@@ -19572,7 +19659,6 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -19572,7 +19659,6 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
19572 lazy_slice_type->is_const = slice_type_instruction->is_const;19659 lazy_slice_type->is_const = slice_type_instruction->is_const;
19573 lazy_slice_type->is_volatile = slice_type_instruction->is_volatile;19660 lazy_slice_type->is_volatile = slice_type_instruction->is_volatile;
19574 lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero;19661 lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero;
19575 lazy_slice_type->is_null_terminated = slice_type_instruction->is_null_terminated;
1957619662
19577 return result;19663 return result;
19578}19664}
...@@ -19647,6 +19733,22 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -19647,6 +19733,22 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
19647 ZigType *child_type = ir_resolve_type(ira, child_type_value);19733 ZigType *child_type = ir_resolve_type(ira, child_type_value);
19648 if (type_is_invalid(child_type))19734 if (type_is_invalid(child_type))
19649 return ira->codegen->invalid_instruction;19735 return ira->codegen->invalid_instruction;
19736
19737 ConstExprValue *sentinel_val;
19738 if (array_type_instruction->sentinel != nullptr) {
19739 IrInstruction *uncasted_sentinel = array_type_instruction->sentinel->child;
19740 if (type_is_invalid(uncasted_sentinel->value.type))
19741 return ira->codegen->invalid_instruction;
19742 IrInstruction *sentinel = ir_implicit_cast(ira, uncasted_sentinel, child_type);
19743 if (type_is_invalid(sentinel->value.type))
19744 return ira->codegen->invalid_instruction;
19745 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
19746 if (sentinel_val == nullptr)
19747 return ira->codegen->invalid_instruction;
19748 } else {
19749 sentinel_val = nullptr;
19750 }
19751
19650 switch (child_type->id) {19752 switch (child_type->id) {
19651 case ZigTypeIdInvalid: // handled above19753 case ZigTypeIdInvalid: // handled above
19652 zig_unreachable();19754 zig_unreachable();
...@@ -19682,8 +19784,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -19682,8 +19784,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
19682 {19784 {
19683 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))19785 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
19684 return ira->codegen->invalid_instruction;19786 return ira->codegen->invalid_instruction;
19685 ZigType *result_type = get_array_type(ira->codegen, child_type, size,19787 ZigType *result_type = get_array_type(ira->codegen, child_type, size, sentinel_val);
19686 array_type_instruction->is_null_terminated);
19687 return ir_const_type(ira, &array_type_instruction->base, result_type);19788 return ir_const_type(ira, &array_type_instruction->base, result_type);
19688 }19789 }
19689 }19790 }
...@@ -19802,7 +19903,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr...@@ -19802,7 +19903,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
19802 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,19903 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
19803 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);19904 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);
1980419905
19805 bool same_comptime_repr = types_have_same_zig_comptime_repr(child_type, type_entry);19906 bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, child_type, type_entry);
1980619907
19807 if (instr_is_comptime(base_ptr)) {19908 if (instr_is_comptime(base_ptr)) {
19808 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);19909 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
...@@ -20759,7 +20860,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -20759,7 +20860,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
20759 if (container_type->id == ZigTypeIdArray) {20860 if (container_type->id == ZigTypeIdArray) {
20760 ZigType *child_type = container_type->data.array.child_type;20861 ZigType *child_type = container_type->data.array.child_type;
20761 if (container_type->data.array.len != elem_count) {20862 if (container_type->data.array.len != elem_count) {
20762 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count, false);20863 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count, nullptr);
2076320864
20764 ir_add_error(ira, &instruction->base,20865 ir_add_error(ira, &instruction->base,
20765 buf_sprintf("expected %s literal, found %s literal",20866 buf_sprintf("expected %s literal, found %s literal",
...@@ -21246,7 +21347,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -21246,7 +21347,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
2124621347
21247 ConstExprValue *declaration_array = create_const_vals(1);21348 ConstExprValue *declaration_array = create_const_vals(1);
21248 declaration_array->special = ConstValSpecialStatic;21349 declaration_array->special = ConstValSpecialStatic;
21249 declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count, false);21350 declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count, nullptr);
21250 declaration_array->data.x_array.special = ConstArraySpecialNone;21351 declaration_array->data.x_array.special = ConstArraySpecialNone;
21251 declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count);21352 declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count);
21252 init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false);21353 init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false);
...@@ -21391,7 +21492,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -21391,7 +21492,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
21391 ConstExprValue *fn_arg_name_array = create_const_vals(1);21492 ConstExprValue *fn_arg_name_array = create_const_vals(1);
21392 fn_arg_name_array->special = ConstValSpecialStatic;21493 fn_arg_name_array->special = ConstValSpecialStatic;
21393 fn_arg_name_array->type = get_array_type(ira->codegen,21494 fn_arg_name_array->type = get_array_type(ira->codegen,
21394 get_slice_type(ira->codegen, u8_ptr), fn_arg_count, false);21495 get_slice_type(ira->codegen, u8_ptr), fn_arg_count, nullptr);
21395 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;21496 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
21396 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);21497 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
2139721498
...@@ -21446,7 +21547,6 @@ static BuiltinPtrSize ptr_len_to_size_enum_index(PtrLen ptr_len) {...@@ -21446,7 +21547,6 @@ static BuiltinPtrSize ptr_len_to_size_enum_index(PtrLen ptr_len) {
21446 case PtrLenSingle:21547 case PtrLenSingle:
21447 return BuiltinPtrSizeOne;21548 return BuiltinPtrSizeOne;
21448 case PtrLenUnknown:21549 case PtrLenUnknown:
21449 case PtrLenNull:
21450 return BuiltinPtrSizeMany;21550 return BuiltinPtrSizeMany;
21451 case PtrLenC:21551 case PtrLenC:
21452 return BuiltinPtrSizeC;21552 return BuiltinPtrSizeC;
...@@ -21527,11 +21627,21 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -21527,11 +21627,21 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
21527 fields[5]->special = ConstValSpecialStatic;21627 fields[5]->special = ConstValSpecialStatic;
21528 fields[5]->type = ira->codegen->builtin_types.entry_bool;21628 fields[5]->type = ira->codegen->builtin_types.entry_bool;
21529 fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero;21629 fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero;
21530 // is_null_terminated: bool21630 // sentinel: ?*const c_void
21531 ensure_field_index(result->type, "is_null_terminated", 6);21631 ZigType *ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_c_void, true);
21632 ensure_field_index(result->type, "sentinel", 6);
21532 fields[6]->special = ConstValSpecialStatic;21633 fields[6]->special = ConstValSpecialStatic;
21533 fields[6]->type = ira->codegen->builtin_types.entry_bool;21634 fields[6]->type = get_optional_type(ira->codegen, ptr_type);
21534 fields[6]->data.x_bool = attrs_type->data.pointer.ptr_len == PtrLenNull;21635 if (attrs_type->data.pointer.sentinel == nullptr) {
21636 fields[6]->data.x_optional = nullptr;
21637 } else {
21638 ConstExprValue *ptr_val = create_const_vals(1);
21639 fields[6]->data.x_optional = ptr_val;
21640 ptr_val->data.x_ptr.special = ConstPtrSpecialRef;
21641 ptr_val->data.x_ptr.mut = ConstPtrMutComptimeConst;
21642 ptr_val->data.x_ptr.data.ref.pointee = create_const_vals(1);
21643 copy_const_val(ptr_val->data.x_ptr.data.ref.pointee, attrs_type->data.pointer.sentinel, false);
21644 }
2153521645
21536 return result;21646 return result;
21537};21647};
...@@ -21652,11 +21762,22 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21652,11 +21762,22 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21652 fields[1]->special = ConstValSpecialStatic;21762 fields[1]->special = ConstValSpecialStatic;
21653 fields[1]->type = ira->codegen->builtin_types.entry_type;21763 fields[1]->type = ira->codegen->builtin_types.entry_type;
21654 fields[1]->data.x_type = type_entry->data.array.child_type;21764 fields[1]->data.x_type = type_entry->data.array.child_type;
21655 // is_null_terminated: bool21765 // sentinel: ?*const c_void
21656 ensure_field_index(result->type, "is_null_terminated", 2);
21657 fields[2]->special = ConstValSpecialStatic;21766 fields[2]->special = ConstValSpecialStatic;
21658 fields[2]->type = ira->codegen->builtin_types.entry_bool;21767 ZigType *ptr_type = get_pointer_to_type(ira->codegen,
21659 fields[2]->data.x_bool = type_entry->data.array.is_null_terminated;21768 ira->codegen->builtin_types.entry_c_void, true);
21769 fields[2]->type = get_optional_type(ira->codegen, ptr_type);
21770 if (type_entry->data.array.sentinel == nullptr) {
21771 fields[2]->data.x_optional = nullptr;
21772 } else {
21773 ConstExprValue *ptr_val = create_const_vals(1);
21774 fields[2]->data.x_optional = ptr_val;
21775 ptr_val->type = ptr_type;
21776 ptr_val->data.x_ptr.special = ConstPtrSpecialRef;
21777 ptr_val->data.x_ptr.mut = ConstPtrMutComptimeConst;
21778 ptr_val->data.x_ptr.data.ref.pointee = create_const_vals(1);
21779 copy_const_val(ptr_val->data.x_ptr.data.ref.pointee, type_entry->data.array.sentinel, false);
21780 }
2166021781
21661 break;21782 break;
21662 }21783 }
...@@ -21744,7 +21865,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21744,7 +21865,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2174421865
21745 ConstExprValue *enum_field_array = create_const_vals(1);21866 ConstExprValue *enum_field_array = create_const_vals(1);
21746 enum_field_array->special = ConstValSpecialStatic;21867 enum_field_array->special = ConstValSpecialStatic;
21747 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count, false);21868 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count, nullptr);
21748 enum_field_array->data.x_array.special = ConstArraySpecialNone;21869 enum_field_array->data.x_array.special = ConstArraySpecialNone;
21749 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);21870 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
2175021871
...@@ -21792,7 +21913,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21792,7 +21913,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21792 uint32_t error_count = type_entry->data.error_set.err_count;21913 uint32_t error_count = type_entry->data.error_set.err_count;
21793 ConstExprValue *error_array = create_const_vals(1);21914 ConstExprValue *error_array = create_const_vals(1);
21794 error_array->special = ConstValSpecialStatic;21915 error_array->special = ConstValSpecialStatic;
21795 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count, false);21916 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count, nullptr);
21796 error_array->data.x_array.special = ConstArraySpecialNone;21917 error_array->data.x_array.special = ConstArraySpecialNone;
21797 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);21918 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
2179821919
...@@ -21888,7 +22009,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21888,7 +22009,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2188822009
21889 ConstExprValue *union_field_array = create_const_vals(1);22010 ConstExprValue *union_field_array = create_const_vals(1);
21890 union_field_array->special = ConstValSpecialStatic;22011 union_field_array->special = ConstValSpecialStatic;
21891 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count, false);22012 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count, nullptr);
21892 union_field_array->data.x_array.special = ConstArraySpecialNone;22013 union_field_array->data.x_array.special = ConstArraySpecialNone;
21893 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);22014 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
2189422015
...@@ -21968,7 +22089,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21968,7 +22089,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2196822089
21969 ConstExprValue *struct_field_array = create_const_vals(1);22090 ConstExprValue *struct_field_array = create_const_vals(1);
21970 struct_field_array->special = ConstValSpecialStatic;22091 struct_field_array->special = ConstValSpecialStatic;
21971 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count, false);22092 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count, nullptr);
21972 struct_field_array->data.x_array.special = ConstArraySpecialNone;22093 struct_field_array->data.x_array.special = ConstArraySpecialNone;
21973 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);22094 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
2197422095
...@@ -22071,7 +22192,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -22071,7 +22192,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2207122192
22072 ConstExprValue *fn_arg_array = create_const_vals(1);22193 ConstExprValue *fn_arg_array = create_const_vals(1);
22073 fn_arg_array->special = ConstValSpecialStatic;22194 fn_arg_array->special = ConstValSpecialStatic;
22074 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count, false);22195 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count, nullptr);
22075 fn_arg_array->data.x_array.special = ConstArraySpecialNone;22196 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
22076 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);22197 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
2207722198
...@@ -22169,6 +22290,17 @@ static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_va...@@ -22169,6 +22290,17 @@ static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_va
22169 return struct_value->data.x_struct.fields[field_index];22290 return struct_value->data.x_struct.fields[field_index];
22170}22291}
2217122292
22293static ConstExprValue *get_const_field_variant(IrAnalyze *ira, ConstExprValue *struct_value,
22294 const char *name, size_t field_index)
22295{
22296 ConstExprValue *field_val = get_const_field(ira, struct_value, name, field_index);
22297 assert(field_val->type->id == ZigTypeIdOptional);
22298 ConstExprValue *opt_val = field_val->data.x_optional;
22299 if (opt_val == nullptr) return nullptr;
22300 assert(opt_val->type->id == ZigTypeIdPointer);
22301 return const_ptr_pointee_unchecked(ira->codegen, opt_val);
22302}
22303
22172static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)22304static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
22173{22305{
22174 ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);22306 ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);
...@@ -22232,7 +22364,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi...@@ -22232,7 +22364,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi
22232 assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));22364 assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));
22233 BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);22365 BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);
22234 PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);22366 PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);
22235 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen,22367 ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen,
22236 get_const_field_meta_type(ira, payload, "child", 4),22368 get_const_field_meta_type(ira, payload, "child", 4),
22237 get_const_field_bool(ira, payload, "is_const", 1),22369 get_const_field_bool(ira, payload, "is_const", 1),
22238 get_const_field_bool(ira, payload, "is_volatile", 2),22370 get_const_field_bool(ira, payload, "is_volatile", 2),
...@@ -22240,7 +22372,10 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi...@@ -22240,7 +22372,10 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi
22240 bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)),22372 bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)),
22241 0, // bit_offset_in_host22373 0, // bit_offset_in_host
22242 0, // host_int_bytes22374 0, // host_int_bytes
22243 get_const_field_bool(ira, payload, "is_allowzero", 5)22375 get_const_field_bool(ira, payload, "is_allowzero", 5),
22376 VECTOR_INDEX_NONE,
22377 nullptr,
22378 get_const_field_variant(ira, payload, "sentinel", 6)
22244 );22379 );
22245 if (size_enum_index != 2)22380 if (size_enum_index != 2)
22246 return ptr_type;22381 return ptr_type;
...@@ -22252,7 +22387,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi...@@ -22252,7 +22387,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi
22252 return get_array_type(ira->codegen,22387 return get_array_type(ira->codegen,
22253 get_const_field_meta_type(ira, payload, "child", 1),22388 get_const_field_meta_type(ira, payload, "child", 1),
22254 bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0)),22389 bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0)),
22255 get_const_field_bool(ira, payload, "is_null_terminated", 2)22390 get_const_field_variant(ira, payload, "sentinel", 2)
22256 );22391 );
22257 case ZigTypeIdComptimeFloat:22392 case ZigTypeIdComptimeFloat:
22258 return ira->codegen->builtin_types.entry_num_lit_float;22393 return ira->codegen->builtin_types.entry_num_lit_float;
...@@ -22635,7 +22770,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru...@@ -22635,7 +22770,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
22635 }22770 }
2263622771
22637 ZigType *result_type = get_array_type(ira->codegen,22772 ZigType *result_type = get_array_type(ira->codegen,
22638 ira->codegen->builtin_types.entry_u8, buf_len(file_contents), false);22773 ira->codegen->builtin_types.entry_u8, buf_len(file_contents), nullptr);
22639 IrInstruction *result = ir_const(ira, &instruction->base, result_type);22774 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
22640 init_const_str_lit(ira->codegen, &result->value, file_contents);22775 init_const_str_lit(ira->codegen, &result->value, file_contents);
22641 return result;22776 return result;
...@@ -25858,6 +25993,12 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -25858,6 +25993,12 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
25858 result->value.data.x_lazy = &lazy_ptr_type->base;25993 result->value.data.x_lazy = &lazy_ptr_type->base;
25859 lazy_ptr_type->base.id = LazyValueIdPtrType;25994 lazy_ptr_type->base.id = LazyValueIdPtrType;
2586025995
25996 if (instruction->sentinel != nullptr) {
25997 lazy_ptr_type->sentinel = instruction->sentinel->child;
25998 if (ir_resolve_const(ira, lazy_ptr_type->sentinel, LazyOk) == nullptr)
25999 return ira->codegen->invalid_instruction;
26000 }
26001
25861 lazy_ptr_type->elem_type = instruction->child_type->child;26002 lazy_ptr_type->elem_type = instruction->child_type->child;
25862 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)26003 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)
25863 return ira->codegen->invalid_instruction;26004 return ira->codegen->invalid_instruction;
...@@ -27804,6 +27945,20 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -27804,6 +27945,20 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
27804 if (type_is_invalid(elem_type))27945 if (type_is_invalid(elem_type))
27805 return ErrorSemanticAnalyzeFail;27946 return ErrorSemanticAnalyzeFail;
2780627947
27948 ConstExprValue *sentinel_val;
27949 if (lazy_slice_type->sentinel != nullptr) {
27950 if (type_is_invalid(lazy_slice_type->sentinel->value.type))
27951 return ErrorSemanticAnalyzeFail;
27952 IrInstruction *sentinel = ir_implicit_cast(ira, lazy_slice_type->sentinel, elem_type);
27953 if (type_is_invalid(sentinel->value.type))
27954 return ErrorSemanticAnalyzeFail;
27955 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
27956 if (sentinel_val == nullptr)
27957 return ErrorSemanticAnalyzeFail;
27958 } else {
27959 sentinel_val = nullptr;
27960 }
27961
27807 uint32_t align_bytes = 0;27962 uint32_t align_bytes = 0;
27808 if (lazy_slice_type->align_inst != nullptr) {27963 if (lazy_slice_type->align_inst != nullptr) {
27809 if (!ir_resolve_align(ira, lazy_slice_type->align_inst, elem_type, &align_bytes))27964 if (!ir_resolve_align(ira, lazy_slice_type->align_inst, elem_type, &align_bytes))
...@@ -27849,11 +28004,12 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -27849,11 +28004,12 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
27849 ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;28004 ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
27850 if ((err = type_resolve(ira->codegen, elem_type, needed_status)))28005 if ((err = type_resolve(ira->codegen, elem_type, needed_status)))
27851 return err;28006 return err;
27852 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type,28007 ZigType *slice_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
27853 lazy_slice_type->is_const, lazy_slice_type->is_volatile,28008 lazy_slice_type->is_const, lazy_slice_type->is_volatile,
27854 lazy_slice_type->is_null_terminated ? PtrLenNull : PtrLenUnknown,28009 PtrLenUnknown,
27855 align_bytes,28010 align_bytes,
27856 0, 0, lazy_slice_type->is_allowzero);28011 0, 0, lazy_slice_type->is_allowzero,
28012 VECTOR_INDEX_NONE, nullptr, sentinel_val);
27857 val->special = ConstValSpecialStatic;28013 val->special = ConstValSpecialStatic;
27858 assert(val->type->id == ZigTypeIdMetaType);28014 assert(val->type->id == ZigTypeIdMetaType);
27859 val->data.x_type = get_slice_type(ira->codegen, slice_ptr_type);28015 val->data.x_type = get_slice_type(ira->codegen, slice_ptr_type);
...@@ -27867,6 +28023,20 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -27867,6 +28023,20 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
27867 if (type_is_invalid(elem_type))28023 if (type_is_invalid(elem_type))
27868 return ErrorSemanticAnalyzeFail;28024 return ErrorSemanticAnalyzeFail;
2786928025
28026 ConstExprValue *sentinel_val;
28027 if (lazy_ptr_type->sentinel != nullptr) {
28028 if (type_is_invalid(lazy_ptr_type->sentinel->value.type))
28029 return ErrorSemanticAnalyzeFail;
28030 IrInstruction *sentinel = ir_implicit_cast(ira, lazy_ptr_type->sentinel, elem_type);
28031 if (type_is_invalid(sentinel->value.type))
28032 return ErrorSemanticAnalyzeFail;
28033 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
28034 if (sentinel_val == nullptr)
28035 return ErrorSemanticAnalyzeFail;
28036 } else {
28037 sentinel_val = nullptr;
28038 }
28039
27870 uint32_t align_bytes = 0;28040 uint32_t align_bytes = 0;
27871 if (lazy_ptr_type->align_inst != nullptr) {28041 if (lazy_ptr_type->align_inst != nullptr) {
27872 if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, elem_type, &align_bytes))28042 if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, elem_type, &align_bytes))
...@@ -27909,10 +28079,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -27909,10 +28079,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
27909 }28079 }
27910 bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC;28080 bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC;
27911 assert(val->type->id == ZigTypeIdMetaType);28081 assert(val->type->id == ZigTypeIdMetaType);
27912 val->data.x_type = get_pointer_to_type_extra(ira->codegen, elem_type,28082 val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
27913 lazy_ptr_type->is_const, lazy_ptr_type->is_volatile, lazy_ptr_type->ptr_len, align_bytes,28083 lazy_ptr_type->is_const, lazy_ptr_type->is_volatile, lazy_ptr_type->ptr_len, align_bytes,
27914 lazy_ptr_type->bit_offset_in_host, lazy_ptr_type->host_int_bytes,28084 lazy_ptr_type->bit_offset_in_host, lazy_ptr_type->host_int_bytes,
27915 allow_zero);28085 allow_zero, VECTOR_INDEX_NONE, nullptr, sentinel_val);
27916 val->special = ConstValSpecialStatic;28086 val->special = ConstValSpecialStatic;
27917 return ErrorNone;28087 return ErrorNone;
27918 }28088 }
src/parser.cpp+111-73
...@@ -1833,8 +1833,10 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) {...@@ -1833,8 +1833,10 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) {
1833 return loop;1833 return loop;
1834 }1834 }
18351835
1836 if (label != nullptr)1836 if (label != nullptr) {
1837 ast_invalid_token_error(pc, peek_token(pc));1837 put_back_token(pc);
1838 put_back_token(pc);
1839 }
1838 return nullptr;1840 return nullptr;
1839}1841}
18401842
...@@ -1931,15 +1933,11 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) {...@@ -1931,15 +1933,11 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) {
19311933
1932// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN1934// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
1933static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {1935static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
1934 Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);1936 if (eat_token_if(pc, TokenIdLBracket) == nullptr)
1935 if (sym_name == nullptr) {1937 return nullptr;
1936 if (eat_token_if(pc, TokenIdLBracket) == nullptr) {1938
1937 return nullptr;1939 Token *sym_name = expect_token(pc, TokenIdSymbol);
1938 } else {1940 expect_token(pc, TokenIdRBracket);
1939 sym_name = expect_token(pc, TokenIdSymbol);
1940 expect_token(pc, TokenIdRBracket);
1941 }
1942 }
19431941
1944 Token *str = expect_token(pc, TokenIdStringLiteral);1942 Token *str = expect_token(pc, TokenIdStringLiteral);
1945 expect_token(pc, TokenIdLParen);1943 expect_token(pc, TokenIdLParen);
...@@ -1954,7 +1952,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {...@@ -1954,7 +1952,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
1954 expect_token(pc, TokenIdRParen);1952 expect_token(pc, TokenIdRParen);
19551953
1956 AsmOutput *res = allocate<AsmOutput>(1);1954 AsmOutput *res = allocate<AsmOutput>(1);
1957 res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);1955 res->asm_symbolic_name = token_buf(sym_name);
1958 res->constraint = token_buf(str);1956 res->constraint = token_buf(str);
1959 res->variable_name = token_buf(var_name);1957 res->variable_name = token_buf(var_name);
1960 res->return_type = return_type;1958 res->return_type = return_type;
...@@ -1977,15 +1975,11 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) {...@@ -1977,15 +1975,11 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) {
19771975
1978// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN1976// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
1979static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {1977static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
1980 Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);1978 if (eat_token_if(pc, TokenIdLBracket) == nullptr)
1981 if (sym_name == nullptr) {1979 return nullptr;
1982 if (eat_token_if(pc, TokenIdLBracket) == nullptr) {1980
1983 return nullptr;1981 Token *sym_name = expect_token(pc, TokenIdSymbol);
1984 } else {1982 expect_token(pc, TokenIdRBracket);
1985 sym_name = expect_token(pc, TokenIdSymbol);
1986 expect_token(pc, TokenIdRBracket);
1987 }
1988 }
19891983
1990 Token *constraint = expect_token(pc, TokenIdStringLiteral);1984 Token *constraint = expect_token(pc, TokenIdStringLiteral);
1991 expect_token(pc, TokenIdLParen);1985 expect_token(pc, TokenIdLParen);
...@@ -1993,7 +1987,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {...@@ -1993,7 +1987,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
1993 expect_token(pc, TokenIdRParen);1987 expect_token(pc, TokenIdRParen);
19941988
1995 AsmInput *res = allocate<AsmInput>(1);1989 AsmInput *res = allocate<AsmInput>(1);
1996 res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);1990 res->asm_symbolic_name = token_buf(sym_name);
1997 res->constraint = token_buf(constraint);1991 res->constraint = token_buf(constraint);
1998 res->expr = expr;1992 res->expr = expr;
1999 return res;1993 return res;
...@@ -2613,42 +2607,28 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {...@@ -2613,42 +2607,28 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
2613 put_back_token(pc);2607 put_back_token(pc);
2614 }2608 }
26152609
2616 AstNode *array = ast_parse_array_type_start(pc);2610 Token *arr_init_lbracket = eat_token_if(pc, TokenIdLBracket);
2617 if (array != nullptr) {2611 if (arr_init_lbracket != nullptr) {
2618 assert(array->type == NodeTypeArrayType);2612 Token *underscore = eat_token_if(pc, TokenIdSymbol);
2619 while (true) {2613 if (underscore == nullptr) {
2620 if (eat_token_if(pc, TokenIdKeywordNull) != nullptr) {2614 put_back_token(pc);
2621 array->data.array_type.is_null_terminated = true;2615 } else if (!buf_eql_str(token_buf(underscore), "_")) {
2622 continue;2616 put_back_token(pc);
2623 }2617 put_back_token(pc);
26242618 } else {
2625 Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);2619 AstNode *sentinel = nullptr;
2626 if (allowzero_token != nullptr) {2620 Token *colon = eat_token_if(pc, TokenIdColon);
2627 array->data.array_type.allow_zero_token = allowzero_token;2621 if (colon != nullptr) {
2628 continue;2622 sentinel = ast_expect(pc, ast_parse_expr);
2629 }
2630
2631 AstNode *align_expr = ast_parse_byte_align(pc);
2632 if (align_expr != nullptr) {
2633 array->data.array_type.align_expr = align_expr;
2634 continue;
2635 }
2636
2637 if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) {
2638 array->data.array_type.is_const = true;
2639 continue;
2640 }
2641
2642 if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) {
2643 array->data.array_type.is_volatile = true;
2644 continue;
2645 }2623 }
2646 break;2624 expect_token(pc, TokenIdRBracket);
2625 AstNode *node = ast_create_node(pc, NodeTypeInferredArrayType, arr_init_lbracket);
2626 node->data.inferred_array_type.sentinel = sentinel;
2627 return node;
2647 }2628 }
2648
2649 return array;
2650 }2629 }
26512630
2631
2652 AstNode *ptr = ast_parse_ptr_type_start(pc);2632 AstNode *ptr = ast_parse_ptr_type_start(pc);
2653 if (ptr != nullptr) {2633 if (ptr != nullptr) {
2654 assert(ptr->type == NodeTypePointerType);2634 assert(ptr->type == NodeTypePointerType);
...@@ -2657,11 +2637,6 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {...@@ -2657,11 +2637,6 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
2657 if (child == nullptr)2637 if (child == nullptr)
2658 child = ptr;2638 child = ptr;
2659 while (true) {2639 while (true) {
2660 if (eat_token_if(pc, TokenIdKeywordNull) != nullptr) {
2661 child->data.pointer_type.is_null_terminated = true;
2662 continue;
2663 }
2664
2665 Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);2640 Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
2666 if (allowzero_token != nullptr) {2641 if (allowzero_token != nullptr) {
2667 child->data.pointer_type.allow_zero_token = allowzero_token;2642 child->data.pointer_type.allow_zero_token = allowzero_token;
...@@ -2699,9 +2674,35 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {...@@ -2699,9 +2674,35 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
2699 return ptr;2674 return ptr;
2700 }2675 }
27012676
2702 Token *arr_init = eat_token_if(pc, TokenIdBracketUnderscoreBracket);2677 AstNode *array = ast_parse_array_type_start(pc);
2703 if (arr_init != nullptr) {2678 if (array != nullptr) {
2704 return ast_create_node(pc, NodeTypeInferredArrayType, arr_init);2679 assert(array->type == NodeTypeArrayType);
2680 while (true) {
2681 Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
2682 if (allowzero_token != nullptr) {
2683 array->data.array_type.allow_zero_token = allowzero_token;
2684 continue;
2685 }
2686
2687 AstNode *align_expr = ast_parse_byte_align(pc);
2688 if (align_expr != nullptr) {
2689 array->data.array_type.align_expr = align_expr;
2690 continue;
2691 }
2692
2693 if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) {
2694 array->data.array_type.is_const = true;
2695 continue;
2696 }
2697
2698 if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) {
2699 array->data.array_type.is_volatile = true;
2700 continue;
2701 }
2702 break;
2703 }
2704
2705 return array;
2705 }2706 }
27062707
27072708
...@@ -2775,9 +2776,15 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {...@@ -2775,9 +2776,15 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
2775 return nullptr;2776 return nullptr;
27762777
2777 AstNode *size = ast_parse_expr(pc);2778 AstNode *size = ast_parse_expr(pc);
2779 AstNode *sentinel = nullptr;
2780 Token *colon = eat_token_if(pc, TokenIdColon);
2781 if (colon != nullptr) {
2782 sentinel = ast_expect(pc, ast_parse_expr);
2783 }
2778 expect_token(pc, TokenIdRBracket);2784 expect_token(pc, TokenIdRBracket);
2779 AstNode *res = ast_create_node(pc, NodeTypeArrayType, lbracket);2785 AstNode *res = ast_create_node(pc, NodeTypeArrayType, lbracket);
2780 res->data.array_type.size = size;2786 res->data.array_type.size = size;
2787 res->data.array_type.sentinel = sentinel;
2781 return res;2788 return res;
2782}2789}
27832790
...@@ -2787,35 +2794,63 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {...@@ -2787,35 +2794,63 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
2787// / PTRUNKNOWN2794// / PTRUNKNOWN
2788// / PTRC2795// / PTRC
2789static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {2796static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2797 AstNode *sentinel = nullptr;
2798
2790 Token *asterisk = eat_token_if(pc, TokenIdStar);2799 Token *asterisk = eat_token_if(pc, TokenIdStar);
2791 if (asterisk != nullptr) {2800 if (asterisk != nullptr) {
2801 Token *colon = eat_token_if(pc, TokenIdColon);
2802 if (colon != nullptr) {
2803 sentinel = ast_expect(pc, ast_parse_expr);
2804 }
2792 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk);2805 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk);
2793 res->data.pointer_type.star_token = asterisk;2806 res->data.pointer_type.star_token = asterisk;
2807 res->data.pointer_type.sentinel = sentinel;
2794 return res;2808 return res;
2795 }2809 }
27962810
2797 Token *asterisk2 = eat_token_if(pc, TokenIdStarStar);2811 Token *asterisk2 = eat_token_if(pc, TokenIdStarStar);
2798 if (asterisk2 != nullptr) {2812 if (asterisk2 != nullptr) {
2813 Token *colon = eat_token_if(pc, TokenIdColon);
2814 if (colon != nullptr) {
2815 sentinel = ast_expect(pc, ast_parse_expr);
2816 }
2799 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2);2817 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2);
2800 AstNode *res2 = ast_create_node(pc, NodeTypePointerType, asterisk2);2818 AstNode *res2 = ast_create_node(pc, NodeTypePointerType, asterisk2);
2801 res->data.pointer_type.star_token = asterisk2;2819 res->data.pointer_type.star_token = asterisk2;
2802 res2->data.pointer_type.star_token = asterisk2;2820 res2->data.pointer_type.star_token = asterisk2;
2821 res2->data.pointer_type.sentinel = sentinel;
2803 res->data.pointer_type.op_expr = res2;2822 res->data.pointer_type.op_expr = res2;
2804 return res;2823 return res;
2805 }2824 }
28062825
2807 Token *multptr = eat_token_if(pc, TokenIdBracketStarBracket);2826 Token *lbracket = eat_token_if(pc, TokenIdLBracket);
2808 if (multptr != nullptr) {2827 if (lbracket != nullptr) {
2809 AstNode *res = ast_create_node(pc, NodeTypePointerType, multptr);2828 Token *star = eat_token_if(pc, TokenIdStar);
2810 res->data.pointer_type.star_token = multptr;2829 if (star == nullptr) {
2811 return res;2830 put_back_token(pc);
2812 }2831 } else {
2832 Token *c_tok = eat_token_if(pc, TokenIdSymbol);
2833 if (c_tok != nullptr) {
2834 if (!buf_eql_str(token_buf(c_tok), "c")) {
2835 put_back_token(pc); // c symbol
2836 } else {
2837 expect_token(pc, TokenIdRBracket);
2838 AstNode *res = ast_create_node(pc, NodeTypePointerType, lbracket);
2839 res->data.pointer_type.star_token = c_tok;
2840 return res;
2841 }
2842 }
28132843
2814 Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket);2844 Token *colon = eat_token_if(pc, TokenIdColon);
2815 if (cptr != nullptr) {2845 if (colon != nullptr) {
2816 AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);2846 sentinel = ast_expect(pc, ast_parse_expr);
2817 res->data.pointer_type.star_token = cptr;2847 }
2818 return res;2848 expect_token(pc, TokenIdRBracket);
2849 AstNode *res = ast_create_node(pc, NodeTypePointerType, lbracket);
2850 res->data.pointer_type.star_token = lbracket;
2851 res->data.pointer_type.sentinel = sentinel;
2852 return res;
2853 }
2819 }2854 }
28202855
2821 return nullptr;2856 return nullptr;
...@@ -3093,10 +3128,12 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3093,10 +3128,12 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3093 break;3128 break;
3094 case NodeTypeArrayType:3129 case NodeTypeArrayType:
3095 visit_field(&node->data.array_type.size, visit, context);3130 visit_field(&node->data.array_type.size, visit, context);
3131 visit_field(&node->data.array_type.sentinel, visit, context);
3096 visit_field(&node->data.array_type.child_type, visit, context);3132 visit_field(&node->data.array_type.child_type, visit, context);
3097 visit_field(&node->data.array_type.align_expr, visit, context);3133 visit_field(&node->data.array_type.align_expr, visit, context);
3098 break;3134 break;
3099 case NodeTypeInferredArrayType:3135 case NodeTypeInferredArrayType:
3136 visit_field(&node->data.array_type.sentinel, visit, context);
3100 visit_field(&node->data.array_type.child_type, visit, context);3137 visit_field(&node->data.array_type.child_type, visit, context);
3101 break;3138 break;
3102 case NodeTypeAnyFrameType:3139 case NodeTypeAnyFrameType:
...@@ -3106,6 +3143,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3106,6 +3143,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3106 // none3143 // none
3107 break;3144 break;
3108 case NodeTypePointerType:3145 case NodeTypePointerType:
3146 visit_field(&node->data.pointer_type.sentinel, visit, context);
3109 visit_field(&node->data.pointer_type.align_expr, visit, context);3147 visit_field(&node->data.pointer_type.align_expr, visit, context);
3110 visit_field(&node->data.pointer_type.op_expr, visit, context);3148 visit_field(&node->data.pointer_type.op_expr, visit, context);
3111 break;3149 break;
src/tokenizer.cpp+1-68
...@@ -222,10 +222,6 @@ enum TokenizeState {...@@ -222,10 +222,6 @@ enum TokenizeState {
222 TokenizeStateSawAtSign,222 TokenizeStateSawAtSign,
223 TokenizeStateCharCode,223 TokenizeStateCharCode,
224 TokenizeStateError,224 TokenizeStateError,
225 TokenizeStateLBracket,
226 TokenizeStateLBracketStar,
227 TokenizeStateLBracketStarC,
228 TokenizeStateLBracketUnderscore,
229};225};
230226
231227
...@@ -480,8 +476,8 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -480,8 +476,8 @@ void tokenize(Buf *buf, Tokenization *out) {
480 end_token(&t);476 end_token(&t);
481 break;477 break;
482 case '[':478 case '[':
483 t.state = TokenizeStateLBracket;
484 begin_token(&t, TokenIdLBracket);479 begin_token(&t, TokenIdLBracket);
480 end_token(&t);
485 break;481 break;
486 case ']':482 case ']':
487 begin_token(&t, TokenIdRBracket);483 begin_token(&t, TokenIdRBracket);
...@@ -775,62 +771,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -775,62 +771,6 @@ void tokenize(Buf *buf, Tokenization *out) {
775 continue;771 continue;
776 }772 }
777 break;773 break;
778 case TokenizeStateLBracket:
779 switch (c) {
780 case '*':
781 t.state = TokenizeStateLBracketStar;
782 break;
783 case '_':
784 t.state = TokenizeStateLBracketUnderscore;
785 break;
786 default:
787 // reinterpret as just an lbracket
788 t.pos -= 1;
789 end_token(&t);
790 t.state = TokenizeStateStart;
791 continue;
792 }
793 break;
794 case TokenizeStateLBracketUnderscore:
795 switch (c) {
796 case ']':
797 set_token_id(&t, t.cur_tok, TokenIdBracketUnderscoreBracket);
798 end_token(&t);
799 t.state = TokenizeStateStart;
800 break;
801 default:
802 // reinterpret as just an lbracket
803 t.pos -= 2;
804 end_token(&t);
805 t.state = TokenizeStateStart;
806 continue;
807 }
808 break;
809 case TokenizeStateLBracketStar:
810 switch (c) {
811 case 'c':
812 t.state = TokenizeStateLBracketStarC;
813 set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket);
814 break;
815 case ']':
816 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
817 end_token(&t);
818 t.state = TokenizeStateStart;
819 break;
820 default:
821 invalid_char_error(&t, c);
822 }
823 break;
824 case TokenizeStateLBracketStarC:
825 switch (c) {
826 case ']':
827 end_token(&t);
828 t.state = TokenizeStateStart;
829 break;
830 default:
831 invalid_char_error(&t, c);
832 }
833 break;
834 case TokenizeStateSawPlusPercent:774 case TokenizeStateSawPlusPercent:
835 switch (c) {775 switch (c) {
836 case '=':776 case '=':
...@@ -1525,7 +1465,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1525,7 +1465,6 @@ void tokenize(Buf *buf, Tokenization *out) {
1525 case TokenizeStateLineString:1465 case TokenizeStateLineString:
1526 case TokenizeStateLineStringEnd:1466 case TokenizeStateLineStringEnd:
1527 case TokenizeStateSawBarBar:1467 case TokenizeStateSawBarBar:
1528 case TokenizeStateLBracket:
1529 case TokenizeStateDocComment:1468 case TokenizeStateDocComment:
1530 case TokenizeStateContainerDocComment:1469 case TokenizeStateContainerDocComment:
1531 end_token(&t);1470 end_token(&t);
...@@ -1534,9 +1473,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1534,9 +1473,6 @@ void tokenize(Buf *buf, Tokenization *out) {
1534 case TokenizeStateSawBackslash:1473 case TokenizeStateSawBackslash:
1535 case TokenizeStateLineStringContinue:1474 case TokenizeStateLineStringContinue:
1536 case TokenizeStateLineStringContinueC:1475 case TokenizeStateLineStringContinueC:
1537 case TokenizeStateLBracketStar:
1538 case TokenizeStateLBracketStarC:
1539 case TokenizeStateLBracketUnderscore:
1540 tokenize_error(&t, "unexpected EOF");1476 tokenize_error(&t, "unexpected EOF");
1541 break;1477 break;
1542 case TokenizeStateLineComment:1478 case TokenizeStateLineComment:
...@@ -1576,8 +1512,6 @@ const char * token_name(TokenId id) {...@@ -1576,8 +1512,6 @@ const char * token_name(TokenId id) {
1576 case TokenIdBitShiftRight: return ">>";1512 case TokenIdBitShiftRight: return ">>";
1577 case TokenIdBitShiftRightEq: return ">>=";1513 case TokenIdBitShiftRightEq: return ">>=";
1578 case TokenIdBitXorEq: return "^=";1514 case TokenIdBitXorEq: return "^=";
1579 case TokenIdBracketStarBracket: return "[*]";
1580 case TokenIdBracketStarCBracket: return "[*c]";
1581 case TokenIdCharLiteral: return "CharLiteral";1515 case TokenIdCharLiteral: return "CharLiteral";
1582 case TokenIdCmpEq: return "==";1516 case TokenIdCmpEq: return "==";
1583 case TokenIdCmpGreaterOrEq: return ">=";1517 case TokenIdCmpGreaterOrEq: return ">=";
...@@ -1681,7 +1615,6 @@ const char * token_name(TokenId id) {...@@ -1681,7 +1615,6 @@ const char * token_name(TokenId id) {
1681 case TokenIdTimesPercent: return "*%";1615 case TokenIdTimesPercent: return "*%";
1682 case TokenIdTimesPercentEq: return "*%=";1616 case TokenIdTimesPercentEq: return "*%=";
1683 case TokenIdBarBarEq: return "||=";1617 case TokenIdBarBarEq: return "||=";
1684 case TokenIdBracketUnderscoreBracket: return "[_]";
1685 case TokenIdCount:1618 case TokenIdCount:
1686 zig_unreachable();1619 zig_unreachable();
1687 }1620 }
src/tokenizer.hpp-3
...@@ -28,9 +28,6 @@ enum TokenId {...@@ -28,9 +28,6 @@ enum TokenId {
28 TokenIdBitShiftRight,28 TokenIdBitShiftRight,
29 TokenIdBitShiftRightEq,29 TokenIdBitShiftRightEq,
30 TokenIdBitXorEq,30 TokenIdBitXorEq,
31 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
33 TokenIdBracketUnderscoreBracket,
34 TokenIdCharLiteral,31 TokenIdCharLiteral,
35 TokenIdCmpEq,32 TokenIdCmpEq,
36 TokenIdCmpGreaterOrEq,33 TokenIdCmpGreaterOrEq,
src/translate_c.cpp+2-4
...@@ -291,10 +291,9 @@ static TokenId ptr_len_to_token_id(PtrLen ptr_len) {...@@ -291,10 +291,9 @@ static TokenId ptr_len_to_token_id(PtrLen ptr_len) {
291 case PtrLenSingle:291 case PtrLenSingle:
292 return TokenIdStar;292 return TokenIdStar;
293 case PtrLenUnknown:293 case PtrLenUnknown:
294 case PtrLenNull:294 return TokenIdLBracket;
295 return TokenIdBracketStarBracket;
296 case PtrLenC:295 case PtrLenC:
297 return TokenIdBracketStarCBracket;296 return TokenIdSymbol;
298 }297 }
299 zig_unreachable();298 zig_unreachable();
300}299}
...@@ -303,7 +302,6 @@ static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_vo...@@ -303,7 +302,6 @@ static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_vo
303 AstNode *node = trans_create_node(c, NodeTypePointerType);302 AstNode *node = trans_create_node(c, NodeTypePointerType);
304 node->data.pointer_type.star_token = allocate<ZigToken>(1);303 node->data.pointer_type.star_token = allocate<ZigToken>(1);
305 node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);304 node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
306 node->data.pointer_type.is_null_terminated = (ptr_len == PtrLenNull);
307 node->data.pointer_type.is_const = is_const;305 node->data.pointer_type.is_const = is_const;
308 node->data.pointer_type.is_volatile = is_volatile;306 node->data.pointer_type.is_volatile = is_volatile;
309 node->data.pointer_type.op_expr = child_node;307 node->data.pointer_type.op_expr = child_node;
test/stage1/behavior/array.zig+1-1
...@@ -351,7 +351,7 @@ test "anonymous literal in array" {...@@ -351,7 +351,7 @@ test "anonymous literal in array" {
351test "access the null element of a null terminated array" {351test "access the null element of a null terminated array" {
352 const S = struct {352 const S = struct {
353 fn doTheTest() void {353 fn doTheTest() void {
354 var array: [4]null u8 = .{'a', 'o', 'e', 'u'};354 var array: [4:0]u8 = .{'a', 'o', 'e', 'u'};
355 comptime expect(array[4] == 0);355 comptime expect(array[4] == 0);
356 var len: usize = 4;356 var len: usize = 4;
357 expect(array[len] == 0);357 expect(array[len] == 0);
test/stage1/behavior/cast.zig+1-1
...@@ -226,7 +226,7 @@ fn testCastConstArrayRefToConstSlice() void {...@@ -226,7 +226,7 @@ fn testCastConstArrayRefToConstSlice() void {
226 {226 {
227 const blah = "aoeu".*;227 const blah = "aoeu".*;
228 const const_array_ref = &blah;228 const const_array_ref = &blah;
229 expect(@typeOf(const_array_ref) == *const [4]null u8);229 expect(@typeOf(const_array_ref) == *const [4:0]u8);
230 const slice: []const u8 = const_array_ref;230 const slice: []const u8 = const_array_ref;
231 expect(mem.eql(u8, slice, "aoeu"));231 expect(mem.eql(u8, slice, "aoeu"));
232 }232 }
test/stage1/behavior/misc.zig+2-2
...@@ -362,8 +362,8 @@ test "string concatenation" {...@@ -362,8 +362,8 @@ test "string concatenation" {
362 const a = "OK" ++ " IT " ++ "WORKED";362 const a = "OK" ++ " IT " ++ "WORKED";
363 const b = "OK IT WORKED";363 const b = "OK IT WORKED";
364364
365 comptime expect(@typeOf(a) == *const [12]null u8);365 comptime expect(@typeOf(a) == *const [12:0]u8);
366 comptime expect(@typeOf(b) == *const [12]null u8);366 comptime expect(@typeOf(b) == *const [12:0]u8);
367367
368 const len = mem.len(u8, b);368 const len = mem.len(u8, b);
369 const len_with_null = len + 1;369 const len_with_null = len + 1;
test/stage1/behavior/pointers.zig+1-1
...@@ -205,7 +205,7 @@ test "null terminated pointer" {...@@ -205,7 +205,7 @@ test "null terminated pointer" {
205 const S = struct {205 const S = struct {
206 fn doTheTest() void {206 fn doTheTest() void {
207 var array_with_zero = [_]u8{'h', 'e', 'l', 'l', 'o', 0};207 var array_with_zero = [_]u8{'h', 'e', 'l', 'l', 'o', 0};
208 var zero_ptr: [*]null const u8 = @ptrCast([*]null const u8, &array_with_zero);208 var zero_ptr: [*:0]const u8 = @ptrCast([*:0]const u8, &array_with_zero);
209 var no_zero_ptr: [*]const u8 = zero_ptr;209 var no_zero_ptr: [*]const u8 = zero_ptr;
210 expect(std.mem.eql(u8, std.mem.toSliceConst(u8, no_zero_ptr), "hello"));210 expect(std.mem.eql(u8, std.mem.toSliceConst(u8, no_zero_ptr), "hello"));
211 }211 }
test/stage1/behavior/type.zig+4-4
...@@ -98,21 +98,21 @@ test "Type.Array" {...@@ -98,21 +98,21 @@ test "Type.Array" {
98 .Array = TypeInfo.Array{98 .Array = TypeInfo.Array{
99 .len = 123,99 .len = 123,
100 .child = u8,100 .child = u8,
101 .is_null_terminated = false,101 .sentinel = null,
102 },102 },
103 }));103 }));
104 testing.expect([2]u32 == @Type(TypeInfo{104 testing.expect([2]u32 == @Type(TypeInfo{
105 .Array = TypeInfo.Array{105 .Array = TypeInfo.Array{
106 .len = 2,106 .len = 2,
107 .child = u32,107 .child = u32,
108 .is_null_terminated = false,108 .sentinel = null,
109 },109 },
110 }));110 }));
111 testing.expect([2]null u32 == @Type(TypeInfo{111 testing.expect([2:0]u32 == @Type(TypeInfo{
112 .Array = TypeInfo.Array{112 .Array = TypeInfo.Array{
113 .len = 2,113 .len = 2,
114 .child = u32,114 .child = u32,
115 .is_null_terminated = true,115 .sentinel = &0,
116 },116 },
117 }));117 }));
118 testTypes([_]type{ [1]u8, [30]usize, [7]bool });118 testTypes([_]type{ [1]u8, [30]usize, [7]bool });
test/stage1/behavior/type_info.zig+5-5
...@@ -71,17 +71,17 @@ test "type info: null terminated pointer type info" {...@@ -71,17 +71,17 @@ test "type info: null terminated pointer type info" {
71}71}
7272
73fn testNullTerminatedPtr() void {73fn testNullTerminatedPtr() void {
74 const ptr_info = @typeInfo([*]null u8);74 const ptr_info = @typeInfo([*:0]u8);
75 expect(@as(TypeId, ptr_info) == TypeId.Pointer);75 expect(@as(TypeId, ptr_info) == TypeId.Pointer);
76 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);76 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
77 expect(ptr_info.Pointer.is_const == false);77 expect(ptr_info.Pointer.is_const == false);
78 expect(ptr_info.Pointer.is_volatile == false);78 expect(ptr_info.Pointer.is_volatile == false);
79 expect(ptr_info.Pointer.is_null_terminated == true);79 expect(ptr_info.Pointer.is_null_terminated == true);
8080
81 expect(@typeInfo([]null u8).Pointer.is_null_terminated == true);81 expect(@typeInfo([:0]u8).Pointer.sentinel != null);
82 expect(@typeInfo([10]null u8).Array.is_null_terminated == true);82 expect(@typeInfo([10:0]u8).Array.sentinel != null);
83 expect(@typeInfo([10]null u8).Array.len == 10);83 expect(@typeInfo([10:0]u8).Array.len == 10);
84 expect(@sizeOf([10]null u8) == 11);84 expect(@sizeOf([10:0]u8) == 11);
85}85}
8686
87test "type info: C pointer type info" {87test "type info: C pointer type info" {