authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-25 12:55:45-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-25 12:55:45-04:00
log5eaead6a56ed95c200e249737c4ecf3c7cacf794
tree70fe5c0238d6f1d72fc8504a4aaec710f059db37
parent3306e43984a8b17472ecc4b13a2f2815d6630eef
signature Commit is signed but in an unrecognized format.

implement allowzero pointer attribute

closes #1953 only needed for freestanding targets. also adds safety for `@intToPtr` when the address is zero.

18 files changed, 225 insertions(+), 78 deletions(-)

doc/docgen.zig+1
...@@ -779,6 +779,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok...@@ -779,6 +779,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
779 std.zig.Token.Id.Keyword_use,779 std.zig.Token.Id.Keyword_use,
780 std.zig.Token.Id.Keyword_var,780 std.zig.Token.Id.Keyword_var,
781 std.zig.Token.Id.Keyword_volatile,781 std.zig.Token.Id.Keyword_volatile,
782 std.zig.Token.Id.Keyword_allowzero,
782 std.zig.Token.Id.Keyword_while,783 std.zig.Token.Id.Keyword_while,
783 => {784 => {
784 try out.write("<span class=\"tok-kw\">");785 try out.write("<span class=\"tok-kw\">");
doc/langref.html.in+36-8
...@@ -1721,7 +1721,7 @@ test "comptime @intToPtr" {...@@ -1721,7 +1721,7 @@ test "comptime @intToPtr" {
1721 }1721 }
1722}1722}
1723 {#code_end#}1723 {#code_end#}
1724 {#see_also|Optional Pointers|@intToPtr|@ptrToInt#}1724 {#see_also|Optional Pointers|@intToPtr|@ptrToInt|C Pointers|Pointers to Zero Bit Types#}
1725 {#header_open|volatile#}1725 {#header_open|volatile#}
1726 <p>Loads and stores are assumed to not have side effects. If a given load or store1726 <p>Loads and stores are assumed to not have side effects. If a given load or store
1727 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.1727 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
...@@ -1850,7 +1850,25 @@ fn foo(bytes: []u8) u32 {...@@ -1850,7 +1850,25 @@ fn foo(bytes: []u8) u32 {
1850}1850}
1851 {#code_end#}1851 {#code_end#}
1852 {#header_close#}1852 {#header_close#}
1853 {#see_also|C Pointers|Pointers to Zero Bit Types#}1853
1854 {#header_open|allowzero#}
1855 <p>
1856 This pointer attribute allows a pointer to have address zero. This is only ever needed on the
1857 freestanding OS target, where the address zero is mappable. In this code example, if the pointer
1858 did not have the {#syntax#}allowzero{#endsyntax#} attribute, this would be a
1859 {#link|Pointer Cast Invalid Null#} panic:
1860 </p>
1861 {#code_begin|test|allowzero#}
1862const std = @import("std");
1863const assert = std.debug.assert;
1864
1865test "allowzero" {
1866 var zero: usize = 0;
1867 var ptr = @intToPtr(*allowzero i32, zero);
1868 assert(@ptrToInt(ptr) == 0);
1869}
1870 {#code_end#}
1871 {#header_close#}
1854 {#header_close#}1872 {#header_close#}
18551873
1856 {#header_open|Slices#}1874 {#header_open|Slices#}
...@@ -6635,9 +6653,13 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -6635,9 +6653,13 @@ fn add(a: i32, b: i32) i32 { return a + b; }
6635 {#header_close#}6653 {#header_close#}
66366654
6637 {#header_open|@intToPtr#}6655 {#header_open|@intToPtr#}
6638 <pre>{#syntax#}@intToPtr(comptime DestType: type, int: usize) DestType{#endsyntax#}</pre>6656 <pre>{#syntax#}@intToPtr(comptime DestType: type, address: usize) DestType{#endsyntax#}</pre>
6657 <p>
6658 Converts an integer to a {#link|pointer|Pointers#}. To convert the other way, use {#link|@ptrToInt#}.
6659 </p>
6639 <p>6660 <p>
6640 Converts an integer to a pointer. To convert the other way, use {#link|@ptrToInt#}.6661 If the destination pointer type does not allow address zero and {#syntax#}address{#endsyntax#}
6662 is zero, this invokes safety-checked {#link|Undefined Behavior#}.
6641 </p>6663 </p>
6642 {#header_close#}6664 {#header_close#}
66436665
...@@ -8128,6 +8150,11 @@ fn bar(f: *Foo) void {...@@ -8128,6 +8150,11 @@ fn bar(f: *Foo) void {
8128 {#header_close#}8150 {#header_close#}
81298151
8130 {#header_open|Pointer Cast Invalid Null#}8152 {#header_open|Pointer Cast Invalid Null#}
8153 <p>
8154 This happens when casting a pointer with the address 0 to a pointer which may not have the address 0.
8155 For example, {#link|C Pointers#}, {#link|Optional Pointers#}, and {#link|allowzero#} pointers
8156 allow address zero, but normal {#link|Pointers#} do not.
8157 </p>
8131 <p>At compile-time:</p>8158 <p>At compile-time:</p>
8132 {#code_begin|test_err|null pointer casted to type#}8159 {#code_begin|test_err|null pointer casted to type#}
8133comptime {8160comptime {
...@@ -8988,7 +9015,7 @@ Available libcs:...@@ -8988,7 +9015,7 @@ Available libcs:
8988 <ul>9015 <ul>
8989 <li>Linux x86_64</li>9016 <li>Linux x86_64</li>
8990 <li>Windows x86_64</li>9017 <li>Windows x86_64</li>
8991 <li>MacOS x86_64</li>9018 <li>macOS x86_64</li>
8992 </ul>9019 </ul>
8993 {#header_close#}9020 {#header_close#}
8994 {#header_open|Style Guide#}9021 {#header_open|Style Guide#}
...@@ -9412,8 +9439,8 @@ PrefixOp...@@ -9412,8 +9439,8 @@ PrefixOp
9412PrefixTypeOp9439PrefixTypeOp
9413 &lt;- QUESTIONMARK9440 &lt;- QUESTIONMARK
9414 / KEYWORD_promise MINUSRARROW9441 / KEYWORD_promise MINUSRARROW
9415 / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)*9442 / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
9416 / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)*9443 / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
94179444
9418SuffixOp9445SuffixOp
9419 &lt;- LBRACKET Expr (DOT2 Expr?)? RBRACKET9446 &lt;- LBRACKET Expr (DOT2 Expr?)? RBRACKET
...@@ -9564,6 +9591,7 @@ TILDE &lt;- '~' skip...@@ -9564,6 +9591,7 @@ TILDE &lt;- '~' skip
95649591
9565end_of_word &lt;- ![a-zA-Z0-9_] skip9592end_of_word &lt;- ![a-zA-Z0-9_] skip
9566KEYWORD_align &lt;- 'align' end_of_word9593KEYWORD_align &lt;- 'align' end_of_word
9594KEYWORD_allowzero &lt;- 'allowzero' end_of_word
9567KEYWORD_and &lt;- 'and' end_of_word9595KEYWORD_and &lt;- 'and' end_of_word
9568KEYWORD_anyerror &lt;- 'anyerror' end_of_word9596KEYWORD_anyerror &lt;- 'anyerror' end_of_word
9569KEYWORD_asm &lt;- 'asm' end_of_word9597KEYWORD_asm &lt;- 'asm' end_of_word
...@@ -9614,7 +9642,7 @@ KEYWORD_var &lt;- 'var' end_of_word...@@ -9614,7 +9642,7 @@ KEYWORD_var &lt;- 'var' end_of_word
9614KEYWORD_volatile &lt;- 'volatile' end_of_word9642KEYWORD_volatile &lt;- 'volatile' end_of_word
9615KEYWORD_while &lt;- 'while' end_of_word9643KEYWORD_while &lt;- 'while' end_of_word
96169644
9617keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm9645keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_allowzero / KEYWORD_anyerror / KEYWORD_asm
9618 / KEYWORD_async / KEYWORD_await / KEYWORD_break / KEYWORD_cancel9646 / KEYWORD_async / KEYWORD_await / KEYWORD_break / KEYWORD_cancel
9619 / KEYWORD_catch / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue9647 / KEYWORD_catch / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue
9620 / KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer9648 / KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer
src/all_types.hpp+2-2
...@@ -2668,7 +2668,7 @@ struct IrInstructionPtrType {...@@ -2668,7 +2668,7 @@ struct IrInstructionPtrType {
2668 PtrLen ptr_len;2668 PtrLen ptr_len;
2669 bool is_const;2669 bool is_const;
2670 bool is_volatile;2670 bool is_volatile;
2671 bool allow_zero;2671 bool is_allow_zero;
2672};2672};
26732673
2674struct IrInstructionPromiseType {2674struct IrInstructionPromiseType {
...@@ -2684,7 +2684,7 @@ struct IrInstructionSliceType {...@@ -2684,7 +2684,7 @@ struct IrInstructionSliceType {
2684 IrInstruction *child_type;2684 IrInstruction *child_type;
2685 bool is_const;2685 bool is_const;
2686 bool is_volatile;2686 bool is_volatile;
2687 bool allow_zero;2687 bool is_allow_zero;
2688};2688};
26892689
2690struct IrInstructionGlobalAsm {2690struct IrInstructionGlobalAsm {
src/analyze.cpp+11-13
...@@ -418,11 +418,9 @@ static const char *ptr_len_to_star_str(PtrLen ptr_len) {...@@ -418,11 +418,9 @@ static const char *ptr_len_to_star_str(PtrLen ptr_len) {
418418
419ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,419ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
420 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,420 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
421 uint32_t bit_offset_in_host, uint32_t host_int_bytes)421 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
422{422{
423 // TODO when implementing https://github.com/ziglang/zig/issues/1953423 assert(ptr_len != PtrLenC || allow_zero);
424 // move this to a parameter
425 bool allow_zero = (ptr_len == PtrLenC);
426 assert(!type_is_invalid(child_type));424 assert(!type_is_invalid(child_type));
427 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);425 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
428426
...@@ -505,7 +503,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -505,7 +503,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
505 bit_offset_in_host != 0 || allow_zero)503 bit_offset_in_host != 0 || allow_zero)
506 {504 {
507 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,505 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
508 PtrLenSingle, 0, 0, host_int_bytes);506 PtrLenSingle, 0, 0, host_int_bytes, false);
509 entry->type_ref = peer_type->type_ref;507 entry->type_ref = peer_type->type_ref;
510 entry->di_type = peer_type->di_type;508 entry->di_type = peer_type->di_type;
511 } else {509 } else {
...@@ -548,7 +546,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -548,7 +546,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
548}546}
549547
550ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {548ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
551 return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0);549 return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false);
552}550}
553551
554ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type) {552ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type) {
...@@ -857,7 +855,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -857,7 +855,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
857 ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)855 ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
858 {856 {
859 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,857 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
860 PtrLenUnknown, 0, 0, 0);858 PtrLenUnknown, 0, 0, 0, false);
861 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);859 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
862860
863 slice_type_common_init(g, ptr_type, entry);861 slice_type_common_init(g, ptr_type, entry);
...@@ -881,10 +879,10 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -881,10 +879,10 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
881 {879 {
882 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;880 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
883 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,881 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
884 PtrLenUnknown, 0, 0, 0);882 PtrLenUnknown, 0, 0, 0, false);
885 ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type);883 ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type);
886 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false,884 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false,
887 PtrLenUnknown, 0, 0, 0);885 PtrLenUnknown, 0, 0, 0, false);
888 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);886 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
889887
890 entry->type_ref = peer_slice_type->type_ref;888 entry->type_ref = peer_slice_type->type_ref;
...@@ -1419,7 +1417,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_...@@ -1419,7 +1417,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_
14191417
1420static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) {1418static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) {
1421 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,1419 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1422 PtrLenUnknown, 0, 0, 0);1420 PtrLenUnknown, 0, 0, 0, false);
1423 ZigType *str_type = get_slice_type(g, ptr_type);1421 ZigType *str_type = get_slice_type(g, ptr_type);
1424 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);1422 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
1425 if (type_is_invalid(result_val->type))1423 if (type_is_invalid(result_val->type))
...@@ -5336,7 +5334,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -5336,7 +5334,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
5336 const_val->special = ConstValSpecialStatic;5334 const_val->special = ConstValSpecialStatic;
5337 // TODO make this `[*]null u8` instead of `[*]u8`5335 // TODO make this `[*]null u8` instead of `[*]u8`
5338 const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,5336 const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
5339 PtrLenUnknown, 0, 0, 0);5337 PtrLenUnknown, 0, 0, 0, false);
5340 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;5338 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
5341 const_val->data.x_ptr.data.base_array.array_val = array_val;5339 const_val->data.x_ptr.data.base_array.array_val = array_val;
5342 const_val->data.x_ptr.data.base_array.elem_index = 0;5340 const_val->data.x_ptr.data.base_array.elem_index = 0;
...@@ -5481,7 +5479,7 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr...@@ -5481,7 +5479,7 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
5481 assert(array_val->type->id == ZigTypeIdArray);5479 assert(array_val->type->id == ZigTypeIdArray);
54825480
5483 ZigType *ptr_type = get_pointer_to_type_extra(g, array_val->type->data.array.child_type,5481 ZigType *ptr_type = get_pointer_to_type_extra(g, array_val->type->data.array.child_type,
5484 is_const, false, PtrLenUnknown, 0, 0, 0);5482 is_const, false, PtrLenUnknown, 0, 0, 0, false);
54855483
5486 const_val->special = ConstValSpecialStatic;5484 const_val->special = ConstValSpecialStatic;
5487 const_val->type = get_slice_type(g, ptr_type);5485 const_val->type = get_slice_type(g, ptr_type);
...@@ -5506,7 +5504,7 @@ void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue...@@ -5506,7 +5504,7 @@ void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue
55065504
5507 const_val->special = ConstValSpecialStatic;5505 const_val->special = ConstValSpecialStatic;
5508 const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,5506 const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,
5509 ptr_len, 0, 0, 0);5507 ptr_len, 0, 0, 0, false);
5510 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;5508 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
5511 const_val->data.x_ptr.data.base_array.array_val = array_val;5509 const_val->data.x_ptr.data.base_array.array_val = array_val;
5512 const_val->data.x_ptr.data.base_array.elem_index = elem_index;5510 const_val->data.x_ptr.data.base_array.elem_index = elem_index;
src/analyze.hpp+3-1
...@@ -18,7 +18,9 @@ void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg);...@@ -18,7 +18,9 @@ void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg);
18ZigType *new_type_table_entry(ZigTypeId id);18ZigType *new_type_table_entry(ZigTypeId id);
19ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);19ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
20ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,20ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
21 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);21 bool is_volatile, PtrLen ptr_len,
22 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,
23 bool allow_zero);
22uint64_t type_size(CodeGen *g, ZigType *type_entry);24uint64_t type_size(CodeGen *g, ZigType *type_entry);
23uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);25uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
24ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);26ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
src/codegen.cpp+22-9
...@@ -956,7 +956,7 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {...@@ -956,7 +956,7 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
956 }956 }
957957
958 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,958 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
959 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);959 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
960 ZigType *str_type = get_slice_type(g, u8_ptr_type);960 ZigType *str_type = get_slice_type(g, u8_ptr_type);
961 return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(str_type->type_ref, 0));961 return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(str_type->type_ref, 0));
962}962}
...@@ -1515,7 +1515,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {...@@ -1515,7 +1515,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
15151515
15161516
1517 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,1517 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1518 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);1518 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
1519 ZigType *str_type = get_slice_type(g, u8_ptr_type);1519 ZigType *str_type = get_slice_type(g, u8_ptr_type);
1520 LLVMValueRef global_slice_fields[] = {1520 LLVMValueRef global_slice_fields[] = {
1521 full_buf_ptr,1521 full_buf_ptr,
...@@ -3103,6 +3103,18 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa...@@ -3103,6 +3103,18 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa
3103static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, IrInstructionIntToPtr *instruction) {3103static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, IrInstructionIntToPtr *instruction) {
3104 ZigType *wanted_type = instruction->base.value.type;3104 ZigType *wanted_type = instruction->base.value.type;
3105 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);3105 LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
3106 if (!ptr_allows_addr_zero(wanted_type) && ir_want_runtime_safety(g, &instruction->base)) {
3107 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(target_val));
3108 LLVMValueRef is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, target_val, zero, "");
3109 LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntBad");
3110 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrToIntOk");
3111 LLVMBuildCondBr(g->builder, is_zero_bit, bad_block, ok_block);
3112
3113 LLVMPositionBuilderAtEnd(g->builder, bad_block);
3114 gen_safety_crash(g, PanicMsgIdPtrCastNull);
3115
3116 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3117 }
3106 return LLVMBuildIntToPtr(g->builder, target_val, wanted_type->type_ref, "");3118 return LLVMBuildIntToPtr(g->builder, target_val, wanted_type->type_ref, "");
3107}3119}
31083120
...@@ -3270,7 +3282,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -3270,7 +3282,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
32703282
3271 if (have_init_expr) {3283 if (have_init_expr) {
3272 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,3284 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
3273 PtrLenSingle, var->align_bytes, 0, 0);3285 PtrLenSingle, var->align_bytes, 0, 0, false);
3274 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);3286 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
3275 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);3287 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
3276 } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {3288 } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
...@@ -4160,7 +4172,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {...@@ -4160,7 +4172,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) {
4160 return enum_type->data.enumeration.name_function;4172 return enum_type->data.enumeration.name_function;
41614173
4162 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, false, false,4174 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, false, false,
4163 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);4175 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
4164 ZigType *u8_slice_type = get_slice_type(g, u8_ptr_type);4176 ZigType *u8_slice_type = get_slice_type(g, u8_ptr_type);
4165 ZigType *tag_int_type = enum_type->data.enumeration.tag_int_type;4177 ZigType *tag_int_type = enum_type->data.enumeration.tag_int_type;
41664178
...@@ -4953,7 +4965,7 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable,...@@ -4953,7 +4965,7 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable,
49534965
4954 ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,4966 ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
4955 false, false, PtrLenSingle, field_align_bytes,4967 false, false, PtrLenSingle, field_align_bytes,
4956 (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes);4968 (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes, false);
49574969
4958 gen_assign_raw(g, field_ptr, ptr_type, value);4970 gen_assign_raw(g, field_ptr, ptr_type, value);
4959 }4971 }
...@@ -4969,7 +4981,7 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I...@@ -4969,7 +4981,7 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
4969 uint32_t field_align_bytes = get_abi_alignment(g, type_union_field->type_entry);4981 uint32_t field_align_bytes = get_abi_alignment(g, type_union_field->type_entry);
4970 ZigType *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,4982 ZigType *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,
4971 false, false, PtrLenSingle, field_align_bytes,4983 false, false, PtrLenSingle, field_align_bytes,
4972 0, 0);4984 0, 0, false);
49734985
4974 LLVMValueRef uncasted_union_ptr;4986 LLVMValueRef uncasted_union_ptr;
4975 // Even if safety is off in this block, if the union type has the safety field, we have to populate it4987 // Even if safety is off in this block, if the union type has the safety field, we have to populate it
...@@ -5224,7 +5236,7 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f...@@ -5224,7 +5236,7 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f
5224 LLVMPositionBuilderAtEnd(g->builder, ok_block);5236 LLVMPositionBuilderAtEnd(g->builder, ok_block);
5225 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_payload_index, "");5237 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_payload_index, "");
5226 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, false, false,5238 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, false, false,
5227 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);5239 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
5228 ZigType *slice_type = get_slice_type(g, u8_ptr_type);5240 ZigType *slice_type = get_slice_type(g, u8_ptr_type);
5229 size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;5241 size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
5230 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, payload_ptr, ptr_field_index, "");5242 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, payload_ptr, ptr_field_index, "");
...@@ -6470,7 +6482,7 @@ static void generate_error_name_table(CodeGen *g) {...@@ -6470,7 +6482,7 @@ static void generate_error_name_table(CodeGen *g) {
6470 assert(g->errors_by_index.length > 0);6482 assert(g->errors_by_index.length > 0);
64716483
6472 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,6484 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
6473 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);6485 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
6474 ZigType *str_type = get_slice_type(g, u8_ptr_type);6486 ZigType *str_type = get_slice_type(g, u8_ptr_type);
64756487
6476 LLVMValueRef *values = allocate<LLVMValueRef>(g->errors_by_index.length);6488 LLVMValueRef *values = allocate<LLVMValueRef>(g->errors_by_index.length);
...@@ -7551,6 +7563,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7551,6 +7563,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7551 " is_volatile: bool,\n"7563 " is_volatile: bool,\n"
7552 " alignment: comptime_int,\n"7564 " alignment: comptime_int,\n"
7553 " child: type,\n"7565 " child: type,\n"
7566 " is_allowzero: bool,\n"
7554 "\n"7567 "\n"
7555 " pub const Size = enum {\n"7568 " pub const Size = enum {\n"
7556 " One,\n"7569 " One,\n"
...@@ -8158,7 +8171,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -8158,7 +8171,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
8158 }8171 }
81598172
8160 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,8173 ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
8161 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);8174 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
8162 ZigType *str_type = get_slice_type(g, u8_ptr_type);8175 ZigType *str_type = get_slice_type(g, u8_ptr_type);
8163 ZigType *fn_type = get_test_fn_type(g);8176 ZigType *fn_type = get_test_fn_type(g);
81648177
src/ir.cpp+71-43
...@@ -1348,7 +1348,7 @@ static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_...@@ -1348,7 +1348,7 @@ static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_
13481348
1349static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,1349static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
1350 IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,1350 IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,
1351 IrInstruction *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes)1351 IrInstruction *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero)
1352{1352{
1353 IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node);1353 IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node);
1354 ptr_type_of_instruction->align_value = align_value;1354 ptr_type_of_instruction->align_value = align_value;
...@@ -1358,6 +1358,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1358,6 +1358,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
1358 ptr_type_of_instruction->ptr_len = ptr_len;1358 ptr_type_of_instruction->ptr_len = ptr_len;
1359 ptr_type_of_instruction->bit_offset_start = bit_offset_start;1359 ptr_type_of_instruction->bit_offset_start = bit_offset_start;
1360 ptr_type_of_instruction->host_int_bytes = host_int_bytes;1360 ptr_type_of_instruction->host_int_bytes = host_int_bytes;
1361 ptr_type_of_instruction->is_allow_zero = is_allow_zero;
13611362
1362 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);1363 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
1363 ir_ref_instruction(child_type, irb->current_basic_block);1364 ir_ref_instruction(child_type, irb->current_basic_block);
...@@ -1627,13 +1628,14 @@ static IrInstruction *ir_build_promise_type(IrBuilder *irb, Scope *scope, AstNod...@@ -1627,13 +1628,14 @@ static IrInstruction *ir_build_promise_type(IrBuilder *irb, Scope *scope, AstNod
1627}1628}
16281629
1629static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,1630static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
1630 IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value)1631 IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value, bool is_allow_zero)
1631{1632{
1632 IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node);1633 IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node);
1633 instruction->is_const = is_const;1634 instruction->is_const = is_const;
1634 instruction->is_volatile = is_volatile;1635 instruction->is_volatile = is_volatile;
1635 instruction->child_type = child_type;1636 instruction->child_type = child_type;
1636 instruction->align_value = align_value;1637 instruction->align_value = align_value;
1638 instruction->is_allow_zero = is_allow_zero;
16371639
1638 ir_ref_instruction(child_type, irb->current_basic_block);1640 ir_ref_instruction(child_type, irb->current_basic_block);
1639 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);1641 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
...@@ -5192,6 +5194,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -5192,6 +5194,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
5192 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);5194 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
5193 bool is_const = node->data.pointer_type.is_const;5195 bool is_const = node->data.pointer_type.is_const;
5194 bool is_volatile = node->data.pointer_type.is_volatile;5196 bool is_volatile = node->data.pointer_type.is_volatile;
5197 bool is_allow_zero = node->data.pointer_type.allow_zero_token != nullptr;
5195 AstNode *expr_node = node->data.pointer_type.op_expr;5198 AstNode *expr_node = node->data.pointer_type.op_expr;
5196 AstNode *align_expr = node->data.pointer_type.align_expr;5199 AstNode *align_expr = node->data.pointer_type.align_expr;
51975200
...@@ -5239,7 +5242,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -5239,7 +5242,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
5239 }5242 }
52405243
5241 return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile,5244 return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile,
5242 ptr_len, align_value, bit_offset_start, host_int_bytes);5245 ptr_len, align_value, bit_offset_start, host_int_bytes, is_allow_zero);
5243}5246}
52445247
5245static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,5248static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
...@@ -5826,6 +5829,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5826,6 +5829,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
5826 AstNode *child_type_node = node->data.array_type.child_type;5829 AstNode *child_type_node = node->data.array_type.child_type;
5827 bool is_const = node->data.array_type.is_const;5830 bool is_const = node->data.array_type.is_const;
5828 bool is_volatile = node->data.array_type.is_volatile;5831 bool is_volatile = node->data.array_type.is_volatile;
5832 bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr;
5829 AstNode *align_expr = node->data.array_type.align_expr;5833 AstNode *align_expr = node->data.array_type.align_expr;
58305834
5831 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);5835 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
...@@ -5838,6 +5842,10 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5838,6 +5842,10 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
5838 add_node_error(irb->codegen, node, buf_create_from_str("volatile qualifier invalid on array type"));5842 add_node_error(irb->codegen, node, buf_create_from_str("volatile qualifier invalid on array type"));
5839 return irb->codegen->invalid_instruction;5843 return irb->codegen->invalid_instruction;
5840 }5844 }
5845 if (is_allow_zero) {
5846 add_node_error(irb->codegen, node, buf_create_from_str("allowzero qualifier invalid on array type"));
5847 return irb->codegen->invalid_instruction;
5848 }
5841 if (align_expr != nullptr) {5849 if (align_expr != nullptr) {
5842 add_node_error(irb->codegen, node, buf_create_from_str("align qualifier invalid on array type"));5850 add_node_error(irb->codegen, node, buf_create_from_str("align qualifier invalid on array type"));
5843 return irb->codegen->invalid_instruction;5851 return irb->codegen->invalid_instruction;
...@@ -5866,7 +5874,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5866,7 +5874,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
5866 if (child_type == irb->codegen->invalid_instruction)5874 if (child_type == irb->codegen->invalid_instruction)
5867 return child_type;5875 return child_type;
58685876
5869 return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, align_value);5877 return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, align_value, is_allow_zero);
5870 }5878 }
5871}5879}
58725880
...@@ -7760,7 +7768,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7760,7 +7768,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7760 if (type_has_bits(return_type)) {7768 if (type_has_bits(return_type)) {
7761 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7769 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7762 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7770 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7763 false, false, PtrLenUnknown, 0, 0, 0));7771 false, false, PtrLenUnknown, 0, 0, 0, false));
7764 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);7772 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
7765 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,7773 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7766 result_ptr, false);7774 result_ptr, false);
...@@ -7814,7 +7822,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7814,7 +7822,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7814 IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);7822 IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
7815 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7823 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7816 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7824 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7817 false, false, PtrLenUnknown, 0, 0, 0));7825 false, false, PtrLenUnknown, 0, 0, 0, false));
7818 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,7826 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7819 coro_mem_ptr_maybe, false);7827 coro_mem_ptr_maybe, false);
7820 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);7828 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
...@@ -9818,7 +9826,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9818,7 +9826,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
9818 ZigType *ptr_type = get_pointer_to_type_extra(9826 ZigType *ptr_type = get_pointer_to_type_extra(
9819 ira->codegen, prev_inst->value.type->data.array.child_type,9827 ira->codegen, prev_inst->value.type->data.array.child_type,
9820 true, false, PtrLenUnknown,9828 true, false, PtrLenUnknown,
9821 0, 0, 0);9829 0, 0, 0, false);
9822 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);9830 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
9823 if (err_set_type != nullptr) {9831 if (err_set_type != nullptr) {
9824 return get_error_union_type(ira->codegen, err_set_type, slice_type);9832 return get_error_union_type(ira->codegen, err_set_type, slice_type);
...@@ -10243,7 +10251,7 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio...@@ -10243,7 +10251,7 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
10243 ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile, uint32_t ptr_align)10251 ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile, uint32_t ptr_align)
10244{10252{
10245 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type,10253 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type,
10246 ptr_is_const, ptr_is_volatile, PtrLenSingle, ptr_align, 0, 0);10254 ptr_is_const, ptr_is_volatile, PtrLenSingle, ptr_align, 0, 0, false);
10247 IrInstruction *const_instr = ir_const(ira, instruction, ptr_type);10255 IrInstruction *const_instr = ir_const(ira, instruction, ptr_type);
10248 ConstExprValue *const_val = &const_instr->value;10256 ConstExprValue *const_val = &const_instr->value;
10249 const_val->data.x_ptr.special = ConstPtrSpecialRef;10257 const_val->data.x_ptr.special = ConstPtrSpecialRef;
...@@ -10576,7 +10584,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi...@@ -10576,7 +10584,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
10576 }10584 }
1057710585
10578 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,10586 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
10579 is_const, is_volatile, PtrLenSingle, 0, 0, 0);10587 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
10580 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,10588 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
10581 source_instruction->source_node, value, is_const, is_volatile);10589 source_instruction->source_node, value, is_const, is_volatile);
10582 new_instruction->value.type = ptr_type;10590 new_instruction->value.type = ptr_type;
...@@ -11983,7 +11991,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {...@@ -11983,7 +11991,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
11983 return nullptr;11991 return nullptr;
1198411992
11985 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,11993 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
11986 true, false, PtrLenUnknown, 0, 0, 0);11994 true, false, PtrLenUnknown, 0, 0, 0, false);
11987 ZigType *str_type = get_slice_type(ira->codegen, ptr_type);11995 ZigType *str_type = get_slice_type(ira->codegen, ptr_type);
11988 IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type);11996 IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type);
11989 if (type_is_invalid(casted_value->value.type))11997 if (type_is_invalid(casted_value->value.type))
...@@ -13154,7 +13162,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -13154,7 +13162,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
13154 out_array_val = out_val;13162 out_array_val = out_val;
13155 } else if (is_slice(op1_type) || is_slice(op2_type)) {13163 } else if (is_slice(op1_type) || is_slice(op2_type)) {
13156 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,13164 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
13157 true, false, PtrLenUnknown, 0, 0, 0);13165 true, false, PtrLenUnknown, 0, 0, 0, false);
13158 result->value.type = get_slice_type(ira->codegen, ptr_type);13166 result->value.type = get_slice_type(ira->codegen, ptr_type);
13159 out_array_val = create_const_vals(1);13167 out_array_val = create_const_vals(1);
13160 out_array_val->special = ConstValSpecialStatic;13168 out_array_val->special = ConstValSpecialStatic;
...@@ -13175,7 +13183,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -13175,7 +13183,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
13175 new_len += 1; // null byte13183 new_len += 1; // null byte
1317613184
13177 // TODO make this `[*]null T` instead of `[*]T`13185 // TODO make this `[*]null T` instead of `[*]T`
13178 result->value.type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0);13186 result->value.type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0, false);
1317913187
13180 out_array_val = create_const_vals(1);13188 out_array_val = create_const_vals(1);
13181 out_array_val->special = ConstValSpecialStatic;13189 out_array_val->special = ConstValSpecialStatic;
...@@ -14033,7 +14041,7 @@ no_mem_slot:...@@ -14033,7 +14041,7 @@ no_mem_slot:
14033 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,14041 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
14034 instruction->scope, instruction->source_node, var);14042 instruction->scope, instruction->source_node, var);
14035 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type,14043 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type,
14036 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);14044 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0, false);
1403714045
14038 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);14046 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
14039 var_ptr_instruction->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack;14047 var_ptr_instruction->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack;
...@@ -14328,7 +14336,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14328,7 +14336,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14328 IrInstruction *casted_new_stack = nullptr;14336 IrInstruction *casted_new_stack = nullptr;
14329 if (call_instruction->new_stack != nullptr) {14337 if (call_instruction->new_stack != nullptr) {
14330 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,14338 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
14331 false, false, PtrLenUnknown, 0, 0, 0);14339 false, false, PtrLenUnknown, 0, 0, 0, false);
14332 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);14340 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
14333 IrInstruction *new_stack = call_instruction->new_stack->child;14341 IrInstruction *new_stack = call_instruction->new_stack->child;
14334 if (type_is_invalid(new_stack->value.type))14342 if (type_is_invalid(new_stack->value.type))
...@@ -15262,7 +15270,8 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali...@@ -15262,7 +15270,8 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali
15262 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,15270 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
15263 ptr_type->data.pointer.ptr_len,15271 ptr_type->data.pointer.ptr_len,
15264 new_align,15272 new_align,
15265 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes);15273 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
15274 ptr_type->data.pointer.allow_zero);
15266}15275}
1526715276
15268static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) {15277static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) {
...@@ -15279,7 +15288,8 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {...@@ -15279,7 +15288,8 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
15279 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,15288 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
15280 ptr_len,15289 ptr_len,
15281 ptr_type->data.pointer.explicit_alignment,15290 ptr_type->data.pointer.explicit_alignment,
15282 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes);15291 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
15292 ptr_type->data.pointer.allow_zero);
15283}15293}
1528415294
15285static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {15295static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {
...@@ -15330,7 +15340,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -15330,7 +15340,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
15330 return_type = get_pointer_to_type_extra(ira->codegen, child_type,15340 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
15331 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,15341 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
15332 elem_ptr_instruction->ptr_len,15342 elem_ptr_instruction->ptr_len,
15333 ptr_type->data.pointer.explicit_alignment, 0, 0);15343 ptr_type->data.pointer.explicit_alignment, 0, 0, false);
15334 } else {15344 } else {
15335 uint64_t elem_val_scalar;15345 uint64_t elem_val_scalar;
15336 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))15346 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
...@@ -15342,7 +15352,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -15342,7 +15352,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
15342 return_type = get_pointer_to_type_extra(ira->codegen, child_type,15352 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
15343 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,15353 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
15344 elem_ptr_instruction->ptr_len,15354 elem_ptr_instruction->ptr_len,
15345 1, (uint32_t)bit_offset, ptr_type->data.pointer.host_int_bytes);15355 1, (uint32_t)bit_offset, ptr_type->data.pointer.host_int_bytes, false);
15346 }15356 }
15347 } else if (array_type->id == ZigTypeIdPointer) {15357 } else if (array_type->id == ZigTypeIdPointer) {
15348 if (array_type->data.pointer.ptr_len == PtrLenSingle) {15358 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
...@@ -15693,7 +15703,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -15693,7 +15703,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
15693 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,15703 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
15694 is_const, is_volatile, PtrLenSingle, align_bytes,15704 is_const, is_volatile, PtrLenSingle, align_bytes,
15695 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),15705 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
15696 (uint32_t)host_int_bytes_for_result_type);15706 (uint32_t)host_int_bytes_for_result_type, false);
15697 IrInstruction *result = ir_const(ira, source_instr, ptr_type);15707 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
15698 ConstExprValue *const_val = &result->value;15708 ConstExprValue *const_val = &result->value;
15699 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;15709 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
...@@ -15709,7 +15719,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -15709,7 +15719,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
15709 PtrLenSingle,15719 PtrLenSingle,
15710 align_bytes,15720 align_bytes,
15711 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),15721 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
15712 host_int_bytes_for_result_type);15722 host_int_bytes_for_result_type, false);
15713 return result;15723 return result;
15714 } else {15724 } else {
15715 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,15725 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
...@@ -15748,7 +15758,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -15748,7 +15758,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1574815758
15749 ZigType *field_type = field->type_entry;15759 ZigType *field_type = field->type_entry;
15750 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,15760 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
15751 is_const, is_volatile, PtrLenSingle, 0, 0, 0);15761 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
1575215762
15753 IrInstruction *result = ir_const(ira, source_instr, ptr_type);15763 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
15754 ConstExprValue *const_val = &result->value;15764 ConstExprValue *const_val = &result->value;
...@@ -15761,7 +15771,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -15761,7 +15771,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1576115771
15762 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);15772 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
15763 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,15773 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
15764 PtrLenSingle, 0, 0, 0);15774 PtrLenSingle, 0, 0, 0, false);
15765 return result;15775 return result;
15766 } else {15776 } else {
15767 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,15777 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
...@@ -16480,6 +16490,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -16480,6 +16490,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1648016490
16481 bool is_const = slice_type_instruction->is_const;16491 bool is_const = slice_type_instruction->is_const;
16482 bool is_volatile = slice_type_instruction->is_volatile;16492 bool is_volatile = slice_type_instruction->is_volatile;
16493 bool is_allow_zero = slice_type_instruction->is_allow_zero;
1648316494
16484 switch (child_type->id) {16495 switch (child_type->id) {
16485 case ZigTypeIdInvalid: // handled above16496 case ZigTypeIdInvalid: // handled above
...@@ -16516,7 +16527,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -16516,7 +16527,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
16516 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))16527 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
16517 return ira->codegen->invalid_instruction;16528 return ira->codegen->invalid_instruction;
16518 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,16529 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
16519 is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0);16530 is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0, is_allow_zero);
16520 ZigType *result_type = get_slice_type(ira->codegen, slice_ptr_type);16531 ZigType *result_type = get_slice_type(ira->codegen, slice_ptr_type);
16521 return ir_const_type(ira, &slice_type_instruction->base, result_type);16532 return ir_const_type(ira, &slice_type_instruction->base, result_type);
16522 }16533 }
...@@ -16749,7 +16760,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr...@@ -16749,7 +16760,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
1674916760
16750 ZigType *child_type = type_entry->data.maybe.child_type;16761 ZigType *child_type = type_entry->data.maybe.child_type;
16751 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,16762 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
16752 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);16763 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);
1675316764
16754 if (instr_is_comptime(base_ptr)) {16765 if (instr_is_comptime(base_ptr)) {
16755 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);16766 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
...@@ -17668,7 +17679,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct...@@ -17668,7 +17679,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
17668 return ira->codegen->invalid_instruction;17679 return ira->codegen->invalid_instruction;
1766917680
17670 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,17681 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
17671 true, false, PtrLenUnknown, 0, 0, 0);17682 true, false, PtrLenUnknown, 0, 0, 0, false);
17672 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);17683 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
17673 if (casted_value->value.special == ConstValSpecialStatic) {17684 if (casted_value->value.special == ConstValSpecialStatic) {
17674 ErrorTableEntry *err = casted_value->value.data.x_err_set;17685 ErrorTableEntry *err = casted_value->value.data.x_err_set;
...@@ -17713,7 +17724,7 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns...@@ -17713,7 +17724,7 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
17713 ZigType *u8_ptr_type = get_pointer_to_type_extra(17724 ZigType *u8_ptr_type = get_pointer_to_type_extra(
17714 ira->codegen, ira->codegen->builtin_types.entry_u8,17725 ira->codegen, ira->codegen->builtin_types.entry_u8,
17715 true, false, PtrLenUnknown,17726 true, false, PtrLenUnknown,
17716 0, 0, 0);17727 0, 0, 0, false);
17717 result->value.type = get_slice_type(ira->codegen, u8_ptr_type);17728 result->value.type = get_slice_type(ira->codegen, u8_ptr_type);
17718 return result;17729 return result;
17719}17730}
...@@ -17767,7 +17778,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,...@@ -17767,7 +17778,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
17767 field_ptr->value.type->data.pointer.is_const,17778 field_ptr->value.type->data.pointer.is_const,
17768 field_ptr->value.type->data.pointer.is_volatile,17779 field_ptr->value.type->data.pointer.is_volatile,
17769 PtrLenSingle,17780 PtrLenSingle,
17770 field_ptr_align, 0, 0);17781 field_ptr_align, 0, 0, false);
17771 IrInstruction *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type);17782 IrInstruction *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type);
17772 if (type_is_invalid(casted_field_ptr->value.type))17783 if (type_is_invalid(casted_field_ptr->value.type))
17773 return ira->codegen->invalid_instruction;17784 return ira->codegen->invalid_instruction;
...@@ -17776,7 +17787,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,...@@ -17776,7 +17787,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
17776 casted_field_ptr->value.type->data.pointer.is_const,17787 casted_field_ptr->value.type->data.pointer.is_const,
17777 casted_field_ptr->value.type->data.pointer.is_volatile,17788 casted_field_ptr->value.type->data.pointer.is_volatile,
17778 PtrLenSingle,17789 PtrLenSingle,
17779 parent_ptr_align, 0, 0);17790 parent_ptr_align, 0, 0, false);
1778017791
17781 if (instr_is_comptime(casted_field_ptr)) {17792 if (instr_is_comptime(casted_field_ptr)) {
17782 ConstExprValue *field_ptr_val = ir_resolve_const(ira, casted_field_ptr, UndefBad);17793 ConstExprValue *field_ptr_val = ir_resolve_const(ira, casted_field_ptr, UndefBad);
...@@ -18112,7 +18123,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,...@@ -18112,7 +18123,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
18112 ZigType *u8_ptr = get_pointer_to_type_extra(18123 ZigType *u8_ptr = get_pointer_to_type_extra(
18113 ira->codegen, ira->codegen->builtin_types.entry_u8,18124 ira->codegen, ira->codegen->builtin_types.entry_u8,
18114 true, false, PtrLenUnknown,18125 true, false, PtrLenUnknown,
18115 0, 0, 0);18126 0, 0, 0, false);
18116 fn_def_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));18127 fn_def_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
18117 if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {18128 if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {
18118 fn_def_fields[6].data.x_optional = create_const_vals(1);18129 fn_def_fields[6].data.x_optional = create_const_vals(1);
...@@ -18216,7 +18227,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -18216,7 +18227,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
18216 result->special = ConstValSpecialStatic;18227 result->special = ConstValSpecialStatic;
18217 result->type = type_info_pointer_type;18228 result->type = type_info_pointer_type;
1821818229
18219 ConstExprValue *fields = create_const_vals(5);18230 ConstExprValue *fields = create_const_vals(6);
18220 result->data.x_struct.fields = fields;18231 result->data.x_struct.fields = fields;
1822118232
18222 // size: Size18233 // size: Size
...@@ -18247,6 +18258,11 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -18247,6 +18258,11 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
18247 fields[4].special = ConstValSpecialStatic;18258 fields[4].special = ConstValSpecialStatic;
18248 fields[4].type = ira->codegen->builtin_types.entry_type;18259 fields[4].type = ira->codegen->builtin_types.entry_type;
18249 fields[4].data.x_type = attrs_type->data.pointer.child_type;18260 fields[4].data.x_type = attrs_type->data.pointer.child_type;
18261 // is_allowzero: bool
18262 ensure_field_index(result->type, "is_allowzero", 5);
18263 fields[5].special = ConstValSpecialStatic;
18264 fields[5].type = ira->codegen->builtin_types.entry_bool;
18265 fields[5].data.x_bool = attrs_type->data.pointer.allow_zero;
1825018266
18251 return result;18267 return result;
18252};18268};
...@@ -19473,12 +19489,12 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru...@@ -19473,12 +19489,12 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
1947319489
19474 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,19490 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
19475 src_ptr_const, src_ptr_volatile, PtrLenUnknown,19491 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
19476 src_ptr_align, 0, 0);19492 src_ptr_align, 0, 0, false);
19477 ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);19493 ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
1947819494
19479 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,19495 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
19480 src_ptr_const, src_ptr_volatile, PtrLenUnknown,19496 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
19481 src_ptr_align, 0, 0);19497 src_ptr_align, 0, 0, false);
19482 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);19498 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
1948319499
19484 IrInstruction *casted_value = ir_implicit_cast(ira, target, u8_slice);19500 IrInstruction *casted_value = ir_implicit_cast(ira, target, u8_slice);
...@@ -19545,7 +19561,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct...@@ -19545,7 +19561,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
1954519561
19546 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,19562 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
19547 src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,19563 src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,
19548 alignment, 0, 0);19564 alignment, 0, 0, false);
19549 ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);19565 ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
1955019566
19551 if (instr_is_comptime(target)) {19567 if (instr_is_comptime(target)) {
...@@ -19773,7 +19789,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio...@@ -19773,7 +19789,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
19773 dest_align = get_abi_alignment(ira->codegen, u8);19789 dest_align = get_abi_alignment(ira->codegen, u8);
19774 }19790 }
19775 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,19791 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
19776 PtrLenUnknown, dest_align, 0, 0);19792 PtrLenUnknown, dest_align, 0, 0, false);
1977719793
19778 IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr);19794 IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr);
19779 if (type_is_invalid(casted_dest_ptr->value.type))19795 if (type_is_invalid(casted_dest_ptr->value.type))
...@@ -19895,9 +19911,9 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -19895,9 +19911,9 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
1989519911
19896 ZigType *usize = ira->codegen->builtin_types.entry_usize;19912 ZigType *usize = ira->codegen->builtin_types.entry_usize;
19897 ZigType *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,19913 ZigType *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
19898 PtrLenUnknown, dest_align, 0, 0);19914 PtrLenUnknown, dest_align, 0, 0, false);
19899 ZigType *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile,19915 ZigType *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile,
19900 PtrLenUnknown, src_align, 0, 0);19916 PtrLenUnknown, src_align, 0, 0, false);
1990119917
19902 IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut);19918 IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut);
19903 if (type_is_invalid(casted_dest_ptr->value.type))19919 if (type_is_invalid(casted_dest_ptr->value.type))
...@@ -20061,7 +20077,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -20061,7 +20077,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
20061 ptr_ptr_type->data.pointer.is_const || is_comptime_const,20077 ptr_ptr_type->data.pointer.is_const || is_comptime_const,
20062 ptr_ptr_type->data.pointer.is_volatile,20078 ptr_ptr_type->data.pointer.is_volatile,
20063 PtrLenUnknown,20079 PtrLenUnknown,
20064 ptr_ptr_type->data.pointer.explicit_alignment, 0, 0);20080 ptr_ptr_type->data.pointer.explicit_alignment, 0, 0, false);
20065 return_type = get_slice_type(ira->codegen, slice_ptr_type);20081 return_type = get_slice_type(ira->codegen, slice_ptr_type);
20066 } else if (array_type->id == ZigTypeIdPointer) {20082 } else if (array_type->id == ZigTypeIdPointer) {
20067 if (array_type->data.pointer.ptr_len == PtrLenSingle) {20083 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
...@@ -20071,7 +20087,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -20071,7 +20087,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
20071 main_type->data.pointer.child_type,20087 main_type->data.pointer.child_type,
20072 array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,20088 array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
20073 PtrLenUnknown,20089 PtrLenUnknown,
20074 array_type->data.pointer.explicit_alignment, 0, 0);20090 array_type->data.pointer.explicit_alignment, 0, 0, false);
20075 return_type = get_slice_type(ira->codegen, slice_ptr_type);20091 return_type = get_slice_type(ira->codegen, slice_ptr_type);
20076 } else {20092 } else {
20077 ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer"));20093 ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer"));
...@@ -20586,7 +20602,7 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr...@@ -20586,7 +20602,7 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
20586 expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type,20602 expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type,
20587 false, result_ptr->value.type->data.pointer.is_volatile,20603 false, result_ptr->value.type->data.pointer.is_volatile,
20588 PtrLenSingle,20604 PtrLenSingle,
20589 alignment, 0, 0);20605 alignment, 0, 0, false);
20590 } else {20606 } else {
20591 expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false);20607 expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false);
20592 }20608 }
...@@ -20753,7 +20769,7 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -20753,7 +20769,7 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
2075320769
20754 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,20770 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
20755 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,20771 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
20756 PtrLenSingle, 0, 0, 0);20772 PtrLenSingle, 0, 0, 0, false);
20757 if (instr_is_comptime(value)) {20773 if (instr_is_comptime(value)) {
20758 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);20774 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
20759 if (!ptr_val)20775 if (!ptr_val)
...@@ -21125,7 +21141,7 @@ static IrInstruction *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstruction...@@ -21125,7 +21141,7 @@ static IrInstruction *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstruction
21125 }21141 }
2112621142
21127 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,21143 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
21128 true, false, PtrLenUnknown, 0, 0, 0);21144 true, false, PtrLenUnknown, 0, 0, 0, false);
21129 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);21145 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
21130 IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type);21146 IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type);
21131 if (type_is_invalid(casted_msg->value.type))21147 if (type_is_invalid(casted_msg->value.type))
...@@ -21794,10 +21810,17 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc...@@ -21794,10 +21810,17 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc
21794 if (!val)21810 if (!val)
21795 return ira->codegen->invalid_instruction;21811 return ira->codegen->invalid_instruction;
2179621812
21813 uint64_t addr = bigint_as_unsigned(&val->data.x_bigint);
21814 if (!ptr_allows_addr_zero(ptr_type) && addr == 0) {
21815 ir_add_error(ira, source_instr,
21816 buf_sprintf("pointer type '%s' does not allow address zero", buf_ptr(&ptr_type->name)));
21817 return ira->codegen->invalid_instruction;
21818 }
21819
21797 IrInstruction *result = ir_const(ira, source_instr, ptr_type);21820 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
21798 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;21821 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
21799 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;21822 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
21800 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);21823 result->value.data.x_ptr.data.hard_coded_addr.addr = addr;
21801 return result;21824 return result;
21802 }21825 }
2180321826
...@@ -21951,6 +21974,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -21951,6 +21974,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
21951 } else if (child_type->id == ZigTypeIdOpaque) {21974 } else if (child_type->id == ZigTypeIdOpaque) {
21952 ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types"));21975 ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types"));
21953 return ira->codegen->invalid_instruction;21976 return ira->codegen->invalid_instruction;
21977 } else if (instruction->is_allow_zero) {
21978 ir_add_error(ira, &instruction->base, buf_sprintf("C pointers always allow address zero"));
21979 return ira->codegen->invalid_instruction;
21954 }21980 }
21955 }21981 }
2195621982
...@@ -21969,10 +21995,12 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -21969,10 +21995,12 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
21969 align_bytes = 0;21995 align_bytes = 0;
21970 }21996 }
2197121997
21998 bool allow_zero = instruction->is_allow_zero || instruction->ptr_len == PtrLenC;
21999
21972 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,22000 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
21973 instruction->is_const, instruction->is_volatile,22001 instruction->is_const, instruction->is_volatile,
21974 instruction->ptr_len, align_bytes,22002 instruction->ptr_len, align_bytes,
21975 instruction->bit_offset_start, instruction->host_int_bytes);22003 instruction->bit_offset_start, instruction->host_int_bytes, allow_zero);
21976 return ir_const_type(ira, &instruction->base, result_type);22004 return ir_const_type(ira, &instruction->base, result_type);
21977}22005}
2197822006
src/parser.cpp+12-1
...@@ -2530,6 +2530,12 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {...@@ -2530,6 +2530,12 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
2530 if (array != nullptr) {2530 if (array != nullptr) {
2531 assert(array->type == NodeTypeArrayType);2531 assert(array->type == NodeTypeArrayType);
2532 while (true) {2532 while (true) {
2533 Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
2534 if (allowzero_token != nullptr) {
2535 array->data.array_type.allow_zero_token = allowzero_token;
2536 continue;
2537 }
2538
2533 AstNode *align_expr = ast_parse_byte_align(pc);2539 AstNode *align_expr = ast_parse_byte_align(pc);
2534 if (align_expr != nullptr) {2540 if (align_expr != nullptr) {
2535 array->data.array_type.align_expr = align_expr;2541 array->data.array_type.align_expr = align_expr;
...@@ -2545,7 +2551,6 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {...@@ -2545,7 +2551,6 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
2545 array->data.array_type.is_volatile = true;2551 array->data.array_type.is_volatile = true;
2546 continue;2552 continue;
2547 }2553 }
2548
2549 break;2554 break;
2550 }2555 }
25512556
...@@ -2560,6 +2565,12 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {...@@ -2560,6 +2565,12 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
2560 if (child == nullptr)2565 if (child == nullptr)
2561 child = ptr;2566 child = ptr;
2562 while (true) {2567 while (true) {
2568 Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
2569 if (allowzero_token != nullptr) {
2570 child->data.pointer_type.allow_zero_token = allowzero_token;
2571 continue;
2572 }
2573
2563 if (eat_token_if(pc, TokenIdKeywordAlign) != nullptr) {2574 if (eat_token_if(pc, TokenIdKeywordAlign) != nullptr) {
2564 expect_token(pc, TokenIdLParen);2575 expect_token(pc, TokenIdLParen);
2565 AstNode *align_expr = ast_parse_expr(pc);2576 AstNode *align_expr = ast_parse_expr(pc);
src/tokenizer.cpp+2
...@@ -107,6 +107,7 @@ struct ZigKeyword {...@@ -107,6 +107,7 @@ struct ZigKeyword {
107107
108static const struct ZigKeyword zig_keywords[] = {108static const struct ZigKeyword zig_keywords[] = {
109 {"align", TokenIdKeywordAlign},109 {"align", TokenIdKeywordAlign},
110 {"allowzero", TokenIdKeywordAllowZero},
110 {"and", TokenIdKeywordAnd},111 {"and", TokenIdKeywordAnd},
111 {"anyerror", TokenIdKeywordAnyerror},112 {"anyerror", TokenIdKeywordAnyerror},
112 {"asm", TokenIdKeywordAsm},113 {"asm", TokenIdKeywordAsm},
...@@ -1495,6 +1496,7 @@ const char * token_name(TokenId id) {...@@ -1495,6 +1496,7 @@ const char * token_name(TokenId id) {
1495 case TokenIdIntLiteral: return "IntLiteral";1496 case TokenIdIntLiteral: return "IntLiteral";
1496 case TokenIdKeywordAsync: return "async";1497 case TokenIdKeywordAsync: return "async";
1497 case TokenIdKeywordAnyerror: return "anyerror";1498 case TokenIdKeywordAnyerror: return "anyerror";
1499 case TokenIdKeywordAllowZero: return "allowzero";
1498 case TokenIdKeywordAwait: return "await";1500 case TokenIdKeywordAwait: return "await";
1499 case TokenIdKeywordResume: return "resume";1501 case TokenIdKeywordResume: return "resume";
1500 case TokenIdKeywordSuspend: return "suspend";1502 case TokenIdKeywordSuspend: return "suspend";
src/tokenizer.hpp+2-1
...@@ -50,6 +50,7 @@ enum TokenId {...@@ -50,6 +50,7 @@ enum TokenId {
50 TokenIdFloatLiteral,50 TokenIdFloatLiteral,
51 TokenIdIntLiteral,51 TokenIdIntLiteral,
52 TokenIdKeywordAlign,52 TokenIdKeywordAlign,
53 TokenIdKeywordAllowZero,
53 TokenIdKeywordAnd,54 TokenIdKeywordAnd,
54 TokenIdKeywordAnyerror,55 TokenIdKeywordAnyerror,
55 TokenIdKeywordAsm,56 TokenIdKeywordAsm,
...@@ -73,6 +74,7 @@ enum TokenId {...@@ -73,6 +74,7 @@ enum TokenId {
73 TokenIdKeywordFor,74 TokenIdKeywordFor,
74 TokenIdKeywordIf,75 TokenIdKeywordIf,
75 TokenIdKeywordInline,76 TokenIdKeywordInline,
77 TokenIdKeywordLinkSection,
76 TokenIdKeywordNakedCC,78 TokenIdKeywordNakedCC,
77 TokenIdKeywordNoAlias,79 TokenIdKeywordNoAlias,
78 TokenIdKeywordNull,80 TokenIdKeywordNull,
...@@ -83,7 +85,6 @@ enum TokenId {...@@ -83,7 +85,6 @@ enum TokenId {
83 TokenIdKeywordPub,85 TokenIdKeywordPub,
84 TokenIdKeywordResume,86 TokenIdKeywordResume,
85 TokenIdKeywordReturn,87 TokenIdKeywordReturn,
86 TokenIdKeywordLinkSection,
87 TokenIdKeywordStdcallCC,88 TokenIdKeywordStdcallCC,
88 TokenIdKeywordStruct,89 TokenIdKeywordStruct,
89 TokenIdKeywordSuspend,90 TokenIdKeywordSuspend,
std/zig/ast.zig+5
...@@ -125,6 +125,7 @@ pub const Error = union(enum) {...@@ -125,6 +125,7 @@ pub const Error = union(enum) {
125 ExtraAlignQualifier: ExtraAlignQualifier,125 ExtraAlignQualifier: ExtraAlignQualifier,
126 ExtraConstQualifier: ExtraConstQualifier,126 ExtraConstQualifier: ExtraConstQualifier,
127 ExtraVolatileQualifier: ExtraVolatileQualifier,127 ExtraVolatileQualifier: ExtraVolatileQualifier,
128 ExtraAllowZeroQualifier: ExtraAllowZeroQualifier,
128 ExpectedPrimaryExpr: ExpectedPrimaryExpr,129 ExpectedPrimaryExpr: ExpectedPrimaryExpr,
129 ExpectedToken: ExpectedToken,130 ExpectedToken: ExpectedToken,
130 ExpectedCommaOrEnd: ExpectedCommaOrEnd,131 ExpectedCommaOrEnd: ExpectedCommaOrEnd,
...@@ -149,6 +150,7 @@ pub const Error = union(enum) {...@@ -149,6 +150,7 @@ pub const Error = union(enum) {
149 @TagType(Error).ExtraAlignQualifier => |*x| return x.render(tokens, stream),150 @TagType(Error).ExtraAlignQualifier => |*x| return x.render(tokens, stream),
150 @TagType(Error).ExtraConstQualifier => |*x| return x.render(tokens, stream),151 @TagType(Error).ExtraConstQualifier => |*x| return x.render(tokens, stream),
151 @TagType(Error).ExtraVolatileQualifier => |*x| return x.render(tokens, stream),152 @TagType(Error).ExtraVolatileQualifier => |*x| return x.render(tokens, stream),
153 @TagType(Error).ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream),
152 @TagType(Error).ExpectedPrimaryExpr => |*x| return x.render(tokens, stream),154 @TagType(Error).ExpectedPrimaryExpr => |*x| return x.render(tokens, stream),
153 @TagType(Error).ExpectedToken => |*x| return x.render(tokens, stream),155 @TagType(Error).ExpectedToken => |*x| return x.render(tokens, stream),
154 @TagType(Error).ExpectedCommaOrEnd => |*x| return x.render(tokens, stream),156 @TagType(Error).ExpectedCommaOrEnd => |*x| return x.render(tokens, stream),
...@@ -175,6 +177,7 @@ pub const Error = union(enum) {...@@ -175,6 +177,7 @@ pub const Error = union(enum) {
175 @TagType(Error).ExtraAlignQualifier => |x| return x.token,177 @TagType(Error).ExtraAlignQualifier => |x| return x.token,
176 @TagType(Error).ExtraConstQualifier => |x| return x.token,178 @TagType(Error).ExtraConstQualifier => |x| return x.token,
177 @TagType(Error).ExtraVolatileQualifier => |x| return x.token,179 @TagType(Error).ExtraVolatileQualifier => |x| return x.token,
180 @TagType(Error).ExtraAllowZeroQualifier => |x| return x.token,
178 @TagType(Error).ExpectedPrimaryExpr => |x| return x.token,181 @TagType(Error).ExpectedPrimaryExpr => |x| return x.token,
179 @TagType(Error).ExpectedToken => |x| return x.token,182 @TagType(Error).ExpectedToken => |x| return x.token,
180 @TagType(Error).ExpectedCommaOrEnd => |x| return x.token,183 @TagType(Error).ExpectedCommaOrEnd => |x| return x.token,
...@@ -198,6 +201,7 @@ pub const Error = union(enum) {...@@ -198,6 +201,7 @@ pub const Error = union(enum) {
198 pub const ExtraAlignQualifier = SimpleError("Extra align qualifier");201 pub const ExtraAlignQualifier = SimpleError("Extra align qualifier");
199 pub const ExtraConstQualifier = SimpleError("Extra const qualifier");202 pub const ExtraConstQualifier = SimpleError("Extra const qualifier");
200 pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier");203 pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier");
204 pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier");
201205
202 pub const ExpectedCall = struct {206 pub const ExpectedCall = struct {
203 node: *Node,207 node: *Node,
...@@ -1540,6 +1544,7 @@ pub const Node = struct {...@@ -1540,6 +1544,7 @@ pub const Node = struct {
1540 };1544 };
15411545
1542 pub const PtrInfo = struct {1546 pub const PtrInfo = struct {
1547 allowzero_token: ?TokenIndex,
1543 align_info: ?Align,1548 align_info: ?Align,
1544 const_token: ?TokenIndex,1549 const_token: ?TokenIndex,
1545 volatile_token: ?TokenIndex,1550 volatile_token: ?TokenIndex,
std/zig/parse.zig+11
...@@ -1688,6 +1688,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1688,6 +1688,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1688 .align_info = null,1688 .align_info = null,
1689 .const_token = null,1689 .const_token = null,
1690 .volatile_token = null,1690 .volatile_token = null,
1691 .allowzero_token = null,
1691 },1692 },
1692 };1693 };
1693 stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;1694 stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
...@@ -1743,6 +1744,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1743,6 +1744,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1743 addr_of_info.volatile_token = token_index;1744 addr_of_info.volatile_token = token_index;
1744 continue;1745 continue;
1745 },1746 },
1747 Token.Id.Keyword_allowzero => {
1748 stack.append(state) catch unreachable;
1749 if (addr_of_info.allowzero_token != null) {
1750 ((try tree.errors.addOne())).* = Error{ .ExtraAllowZeroQualifier = Error.ExtraAllowZeroQualifier{ .token = token_index } };
1751 return tree;
1752 }
1753 addr_of_info.allowzero_token = token_index;
1754 continue;
1755 },
1746 else => {1756 else => {
1747 prevToken(&tok_it, &tree);1757 prevToken(&tok_it, &tree);
1748 continue;1758 continue;
...@@ -3552,6 +3562,7 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {...@@ -3552,6 +3562,7 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
3552 .align_info = null,3562 .align_info = null,
3553 .const_token = null,3563 .const_token = null,
3554 .volatile_token = null,3564 .volatile_token = null,
3565 .allowzero_token = null,
3555 },3566 },
3556 },3567 },
3557 Token.Id.QuestionMark => ast.Node.PrefixOp.Op{ .OptionalType = void{} },3568 Token.Id.QuestionMark => ast.Node.PrefixOp.Op{ .OptionalType = void{} },
std/zig/parser_test.zig+7
...@@ -1,3 +1,10 @@...@@ -1,3 +1,10 @@
1test "zig fmt: allowzero pointer" {
2 try testCanonical(
3 \\const T = [*]allowzero const u8;
4 \\
5 );
6}
7
1test "zig fmt: enum literal" {8test "zig fmt: enum literal" {
2 try testCanonical(9 try testCanonical(
3 \\const x = .hi;10 \\const x = .hi;
std/zig/render.zig+6
...@@ -379,6 +379,9 @@ fn renderExpression(...@@ -379,6 +379,9 @@ fn renderExpression(
379 else => usize(0),379 else => usize(0),
380 };380 };
381 try renderTokenOffset(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None, star_offset); // *381 try renderTokenOffset(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None, star_offset); // *
382 if (ptr_info.allowzero_token) |allowzero_token| {
383 try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero
384 }
382 if (ptr_info.align_info) |align_info| {385 if (ptr_info.align_info) |align_info| {
383 const lparen_token = tree.prevToken(align_info.node.firstToken());386 const lparen_token = tree.prevToken(align_info.node.firstToken());
384 const align_token = tree.prevToken(lparen_token);387 const align_token = tree.prevToken(lparen_token);
...@@ -416,6 +419,9 @@ fn renderExpression(...@@ -416,6 +419,9 @@ fn renderExpression(
416 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [419 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
417 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, start_col, Space.None); // ]420 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, start_col, Space.None); // ]
418421
422 if (ptr_info.allowzero_token) |allowzero_token| {
423 try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero
424 }
419 if (ptr_info.align_info) |align_info| {425 if (ptr_info.align_info) |align_info| {
420 const lparen_token = tree.prevToken(align_info.node.firstToken());426 const lparen_token = tree.prevToken(align_info.node.firstToken());
421 const align_token = tree.prevToken(lparen_token);427 const align_token = tree.prevToken(lparen_token);
std/zig/tokenizer.zig+2
...@@ -13,6 +13,7 @@ pub const Token = struct {...@@ -13,6 +13,7 @@ pub const Token = struct {
1313
14 pub const keywords = []Keyword{14 pub const keywords = []Keyword{
15 Keyword{ .bytes = "align", .id = Id.Keyword_align },15 Keyword{ .bytes = "align", .id = Id.Keyword_align },
16 Keyword{ .bytes = "allowzero", .id = Id.Keyword_allowzero },
16 Keyword{ .bytes = "and", .id = Id.Keyword_and },17 Keyword{ .bytes = "and", .id = Id.Keyword_and },
17 Keyword{ .bytes = "anyerror", .id = Id.Keyword_anyerror },18 Keyword{ .bytes = "anyerror", .id = Id.Keyword_anyerror },
18 Keyword{ .bytes = "asm", .id = Id.Keyword_asm },19 Keyword{ .bytes = "asm", .id = Id.Keyword_asm },
...@@ -143,6 +144,7 @@ pub const Token = struct {...@@ -143,6 +144,7 @@ pub const Token = struct {
143 BracketStarCBracket,144 BracketStarCBracket,
144 ShebangLine,145 ShebangLine,
145 Keyword_align,146 Keyword_align,
147 Keyword_allowzero,
146 Keyword_and,148 Keyword_and,
147 Keyword_anyerror,149 Keyword_anyerror,
148 Keyword_asm,150 Keyword_asm,
test/compile_errors.zig+9
...@@ -2,6 +2,15 @@ const tests = @import("tests.zig");...@@ -2,6 +2,15 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "@ptrToInt 0 to non optional pointer",
7 \\export fn entry() void {
8 \\ var b = @intToPtr(*i32, 0);
9 \\}
10 ,
11 "tmp.zig:2:13: error: pointer type '*i32' does not allow address zero",
12 );
13
5 cases.add(14 cases.add(
6 "cast enum literal to enum but it doesn't match",15 "cast enum literal to enum but it doesn't match",
7 \\const Foo = enum {16 \\const Foo = enum {
test/runtime_safety.zig+10
...@@ -1,6 +1,16 @@...@@ -1,6 +1,16 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompareOutputContext) void {3pub fn addCases(cases: *tests.CompareOutputContext) void {
4 cases.addRuntimeSafety("@ptrToInt address zero to non-optional pointer",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);
7 \\}
8 \\pub fn main() void {
9 \\ var zero: usize = 0;
10 \\ var b = @intToPtr(*i32, zero);
11 \\}
12 );
13
4 cases.addRuntimeSafety("pointer casting null to non-optional pointer",14 cases.addRuntimeSafety("pointer casting null to non-optional pointer",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {15 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);16 \\ @import("std").os.exit(126);
test/stage1/behavior/pointers.zig+13
...@@ -137,3 +137,16 @@ test "compare equality of optional and non-optional pointer" {...@@ -137,3 +137,16 @@ test "compare equality of optional and non-optional pointer" {
137 expect(a == b);137 expect(a == b);
138 expect(b == a);138 expect(b == a);
139}139}
140
141test "allowzero pointer and slice" {
142 var ptr = @intToPtr([*]allowzero i32, 0);
143 var opt_ptr: ?[*]allowzero i32 = ptr;
144 expect(opt_ptr != null);
145 expect(@ptrToInt(ptr) == 0);
146 var slice = ptr[0..10];
147 expect(@typeOf(slice) == []allowzero i32);
148 expect(@ptrToInt(&slice[5]) == 20);
149
150 expect(@typeInfo(@typeOf(ptr)).Pointer.is_allowzero);
151 expect(@typeInfo(@typeOf(slice)).Pointer.is_allowzero);
152}