authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-01-29 21:47:26-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-01-29 22:30:30-05:00
log581edd643fb18a66c472f77e2f8cd3f4cea524a2
treea03f6a3ade952729456b94584f21d4beb51a4802
parent9c328b42916d463465b134457c7f13b5c65da406
signaturelock-open Commit is signed but in an unrecognized format.

backport copy elision changes

This commit contains everything from the copy-elision-2 branch that does not have to do with copy elision directly, but is generally useful for master branch. * All const values know their parents, when applicable, not just structs and unions. * Null pointers in const values are represented explicitly, rather than as a HardCodedAddr value of 0. * Rename "maybe" to "optional" in various code locations. * Separate DeclVarSrc and DeclVarGen * Separate PtrCastSrc and PtrCastGen * Separate CmpxchgSrc and CmpxchgGen * Represent optional error set as an integer, using the 0 value. In a const value, it uses nullptr. * Introduce type_has_one_possible_value and use it where applicable. * Fix debug builds not setting memory to 0xaa when storing undefined. * Separate the type of a variable from the const value of a variable. * Use copy_const_val where appropriate. * Rearrange structs to pack data more efficiently. * Move test/cases/* to test/behavior/* * Use `std.debug.assertOrPanic` in behavior tests instead of `std.debug.assert`. * Fix outdated slice syntax in docs.

181 files changed, 10595 insertions(+), 9692 deletions(-)

build.zig+2-3
...@@ -104,7 +104,7 @@ pub fn build(b: *Builder) !void {...@@ -104,7 +104,7 @@ pub fn build(b: *Builder) !void {
104 }104 }
105 const modes = chosen_modes[0..chosen_mode_index];105 const modes = chosen_modes[0..chosen_mode_index];
106106
107 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes));107 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes));
108108
109 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));109 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));
110110
...@@ -299,8 +299,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {...@@ -299,8 +299,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
299 } else if (exe.target.isFreeBSD()) {299 } else if (exe.target.isFreeBSD()) {
300 try addCxxKnownPath(b, ctx, exe, "libc++.a", null);300 try addCxxKnownPath(b, ctx, exe, "libc++.a", null);
301 exe.linkSystemLibrary("pthread");301 exe.linkSystemLibrary("pthread");
302 }302 } else if (exe.target.isDarwin()) {
303 else if (exe.target.isDarwin()) {
304 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {303 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
305 // Compiler is GCC.304 // Compiler is GCC.
306 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);305 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
doc/langref.html.in+7-6
...@@ -4327,7 +4327,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {...@@ -4327,7 +4327,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
4327 <p>4327 <p>
4328 For example, if we were to introduce another function to the above snippet:4328 For example, if we were to introduce another function to the above snippet:
4329 </p>4329 </p>
4330 {#code_begin|test_err|unable to evaluate constant expression#}4330 {#code_begin|test_err|values of type 'type' must be comptime known#}
4331fn max(comptime T: type, a: T, b: T) T {4331fn max(comptime T: type, a: T, b: T) T {
4332 return if (a > b) a else b;4332 return if (a > b) a else b;
4333}4333}
...@@ -5905,13 +5905,13 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5905,13 +5905,13 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5905 This function is a low level intrinsic with no safety mechanisms. Most code5905 This function is a low level intrinsic with no safety mechanisms. Most code
5906 should not use this function, instead using something like this:5906 should not use this function, instead using something like this:
5907 </p>5907 </p>
5908 <pre>{#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>5908 <pre>{#syntax#}for (source[0..byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>
5909 <p>5909 <p>
5910 The optimizer is intelligent enough to turn the above snippet into a memcpy.5910 The optimizer is intelligent enough to turn the above snippet into a memcpy.
5911 </p>5911 </p>
5912 <p>There is also a standard library function for this:</p>5912 <p>There is also a standard library function for this:</p>
5913 <pre>{#syntax#}const mem = @import("std").mem;5913 <pre>{#syntax#}const mem = @import("std").mem;
5914mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>5914mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}</pre>
5915 {#header_close#}5915 {#header_close#}
59165916
5917 {#header_open|@memset#}5917 {#header_open|@memset#}
...@@ -5923,7 +5923,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>...@@ -5923,7 +5923,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
5923 This function is a low level intrinsic with no safety mechanisms. Most5923 This function is a low level intrinsic with no safety mechanisms. Most
5924 code should not use this function, instead using something like this:5924 code should not use this function, instead using something like this:
5925 </p>5925 </p>
5926 <pre>{#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}</pre>5926 <pre>{#syntax#}for (dest[0..byte_count]) |*b| b.* = c;{#endsyntax#}</pre>
5927 <p>5927 <p>
5928 The optimizer is intelligent enough to turn the above snippet into a memset.5928 The optimizer is intelligent enough to turn the above snippet into a memset.
5929 </p>5929 </p>
...@@ -6592,9 +6592,10 @@ pub const TypeInfo = union(TypeId) {...@@ -6592,9 +6592,10 @@ pub const TypeInfo = union(TypeId) {
6592 {#header_close#}6592 {#header_close#}
65936593
6594 {#header_open|@typeName#}6594 {#header_open|@typeName#}
6595 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>6595 <pre>{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}</pre>
6596 <p>6596 <p>
6597 This function returns the string representation of a type.6597 This function returns the string representation of a type, as
6598 an array. It is equivalent to a string literal of the type name.
6598 </p>6599 </p>
65996600
6600 {#header_close#}6601 {#header_close#}
src/all_types.hpp+115-50
...@@ -56,9 +56,6 @@ struct IrExecutable {...@@ -56,9 +56,6 @@ struct IrExecutable {
56 size_t next_debug_id;56 size_t next_debug_id;
57 size_t *backward_branch_count;57 size_t *backward_branch_count;
58 size_t backward_branch_quota;58 size_t backward_branch_quota;
59 bool invalid;
60 bool is_inline;
61 bool is_generic_instantiation;
62 ZigFn *fn_entry;59 ZigFn *fn_entry;
63 Buf *c_import_buf;60 Buf *c_import_buf;
64 AstNode *source_node;61 AstNode *source_node;
...@@ -78,6 +75,10 @@ struct IrExecutable {...@@ -78,6 +75,10 @@ struct IrExecutable {
78 IrBasicBlock *coro_suspend_block;75 IrBasicBlock *coro_suspend_block;
79 IrBasicBlock *coro_final_cleanup_block;76 IrBasicBlock *coro_final_cleanup_block;
80 ZigVar *coro_allocator_var;77 ZigVar *coro_allocator_var;
78
79 bool invalid;
80 bool is_inline;
81 bool is_generic_instantiation;
81};82};
8283
83enum OutType {84enum OutType {
...@@ -90,6 +91,9 @@ enum OutType {...@@ -90,6 +91,9 @@ enum OutType {
90enum ConstParentId {91enum ConstParentId {
91 ConstParentIdNone,92 ConstParentIdNone,
92 ConstParentIdStruct,93 ConstParentIdStruct,
94 ConstParentIdErrUnionCode,
95 ConstParentIdErrUnionPayload,
96 ConstParentIdOptionalPayload,
93 ConstParentIdArray,97 ConstParentIdArray,
94 ConstParentIdUnion,98 ConstParentIdUnion,
95 ConstParentIdScalar,99 ConstParentIdScalar,
...@@ -107,6 +111,15 @@ struct ConstParent {...@@ -107,6 +111,15 @@ struct ConstParent {
107 ConstExprValue *struct_val;111 ConstExprValue *struct_val;
108 size_t field_index;112 size_t field_index;
109 } p_struct;113 } p_struct;
114 struct {
115 ConstExprValue *err_union_val;
116 } p_err_union_code;
117 struct {
118 ConstExprValue *err_union_val;
119 } p_err_union_payload;
120 struct {
121 ConstExprValue *optional_val;
122 } p_optional_payload;
110 struct {123 struct {
111 ConstExprValue *union_val;124 ConstExprValue *union_val;
112 } p_union;125 } p_union;
...@@ -118,13 +131,11 @@ struct ConstParent {...@@ -118,13 +131,11 @@ struct ConstParent {
118131
119struct ConstStructValue {132struct ConstStructValue {
120 ConstExprValue *fields;133 ConstExprValue *fields;
121 ConstParent parent;
122};134};
123135
124struct ConstUnionValue {136struct ConstUnionValue {
125 BigInt tag;137 BigInt tag;
126 ConstExprValue *payload;138 ConstExprValue *payload;
127 ConstParent parent;
128};139};
129140
130enum ConstArraySpecial {141enum ConstArraySpecial {
...@@ -138,7 +149,6 @@ struct ConstArrayValue {...@@ -138,7 +149,6 @@ struct ConstArrayValue {
138 union {149 union {
139 struct {150 struct {
140 ConstExprValue *elements;151 ConstExprValue *elements;
141 ConstParent parent;
142 } s_none;152 } s_none;
143 Buf *s_buf;153 Buf *s_buf;
144 } data;154 } data;
...@@ -153,19 +163,29 @@ enum ConstPtrSpecial {...@@ -153,19 +163,29 @@ enum ConstPtrSpecial {
153 ConstPtrSpecialBaseArray,163 ConstPtrSpecialBaseArray,
154 // The pointer points to a field in an underlying struct.164 // The pointer points to a field in an underlying struct.
155 ConstPtrSpecialBaseStruct,165 ConstPtrSpecialBaseStruct,
166 // The pointer points to the error set field of an error union
167 ConstPtrSpecialBaseErrorUnionCode,
168 // The pointer points to the payload field of an error union
169 ConstPtrSpecialBaseErrorUnionPayload,
170 // The pointer points to the payload field of an optional
171 ConstPtrSpecialBaseOptionalPayload,
156 // This means that we did a compile-time pointer reinterpret and we cannot172 // This means that we did a compile-time pointer reinterpret and we cannot
157 // understand the value of pointee at compile time. However, we will still173 // understand the value of pointee at compile time. However, we will still
158 // emit a binary with a compile time known address.174 // emit a binary with a compile time known address.
159 // In this case index is the numeric address value.175 // In this case index is the numeric address value.
160 // We also use this for null pointer. We need the data layout for ConstCastOnly == true
161 // types to be the same, so all optionals of pointer types use x_ptr
162 // instead of x_optional
163 ConstPtrSpecialHardCodedAddr,176 ConstPtrSpecialHardCodedAddr,
164 // This means that the pointer represents memory of assigning to _.177 // This means that the pointer represents memory of assigning to _.
165 // That is, storing discards the data, and loading is invalid.178 // That is, storing discards the data, and loading is invalid.
166 ConstPtrSpecialDiscard,179 ConstPtrSpecialDiscard,
167 // This is actually a function.180 // This is actually a function.
168 ConstPtrSpecialFunction,181 ConstPtrSpecialFunction,
182 // This means the pointer is null. This is only allowed when the type is ?*T.
183 // We use this instead of ConstPtrSpecialHardCodedAddr because often we check
184 // for that value to avoid doing comptime work.
185 // We need the data layout for ConstCastOnly == true
186 // types to be the same, so all optionals of pointer types use x_ptr
187 // instead of x_optional.
188 ConstPtrSpecialNull,
169};189};
170190
171enum ConstPtrMut {191enum ConstPtrMut {
...@@ -199,6 +219,15 @@ struct ConstPtrValue {...@@ -199,6 +219,15 @@ struct ConstPtrValue {
199 ConstExprValue *struct_val;219 ConstExprValue *struct_val;
200 size_t field_index;220 size_t field_index;
201 } base_struct;221 } base_struct;
222 struct {
223 ConstExprValue *err_union_val;
224 } base_err_union_code;
225 struct {
226 ConstExprValue *err_union_val;
227 } base_err_union_payload;
228 struct {
229 ConstExprValue *optional_val;
230 } base_optional_payload;
202 struct {231 struct {
203 uint64_t addr;232 uint64_t addr;
204 } hard_coded_addr;233 } hard_coded_addr;
...@@ -209,7 +238,7 @@ struct ConstPtrValue {...@@ -209,7 +238,7 @@ struct ConstPtrValue {
209};238};
210239
211struct ConstErrValue {240struct ConstErrValue {
212 ErrorTableEntry *err;241 ConstExprValue *error_set;
213 ConstExprValue *payload;242 ConstExprValue *payload;
214};243};
215244
...@@ -265,6 +294,7 @@ struct ConstGlobalRefs {...@@ -265,6 +294,7 @@ struct ConstGlobalRefs {
265struct ConstExprValue {294struct ConstExprValue {
266 ZigType *type;295 ZigType *type;
267 ConstValSpecial special;296 ConstValSpecial special;
297 ConstParent parent;
268 ConstGlobalRefs *global_refs;298 ConstGlobalRefs *global_refs;
269299
270 union {300 union {
...@@ -433,7 +463,7 @@ enum NodeType {...@@ -433,7 +463,7 @@ enum NodeType {
433 NodeTypeArrayType,463 NodeTypeArrayType,
434 NodeTypeErrorType,464 NodeTypeErrorType,
435 NodeTypeIfErrorExpr,465 NodeTypeIfErrorExpr,
436 NodeTypeTestExpr,466 NodeTypeIfOptional,
437 NodeTypeErrorSetDecl,467 NodeTypeErrorSetDecl,
438 NodeTypeCancel,468 NodeTypeCancel,
439 NodeTypeResume,469 NodeTypeResume,
...@@ -677,7 +707,7 @@ struct AstNodeUse {...@@ -677,7 +707,7 @@ struct AstNodeUse {
677 AstNode *expr;707 AstNode *expr;
678708
679 TldResolution resolution;709 TldResolution resolution;
680 IrInstruction *value;710 ConstExprValue *value;
681};711};
682712
683struct AstNodeIfBoolExpr {713struct AstNodeIfBoolExpr {
...@@ -1610,7 +1640,7 @@ struct CodeGen {...@@ -1610,7 +1640,7 @@ struct CodeGen {
1610 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;1640 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
1611 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;1641 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
1612 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;1642 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
1613 HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;1643 HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
1614 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;1644 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
1615 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;1645 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
1616 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;1646 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
...@@ -1802,10 +1832,9 @@ enum VarLinkage {...@@ -1802,10 +1832,9 @@ enum VarLinkage {
18021832
1803struct ZigVar {1833struct ZigVar {
1804 Buf name;1834 Buf name;
1805 ConstExprValue *value;1835 ConstExprValue *const_value;
1836 ZigType *var_type;
1806 LLVMValueRef value_ref;1837 LLVMValueRef value_ref;
1807 bool src_is_const;
1808 bool gen_is_const;
1809 IrInstruction *is_comptime;1838 IrInstruction *is_comptime;
1810 // which node is the declaration of the variable1839 // which node is the declaration of the variable
1811 AstNode *decl_node;1840 AstNode *decl_node;
...@@ -1815,17 +1844,21 @@ struct ZigVar {...@@ -1815,17 +1844,21 @@ struct ZigVar {
1815 Scope *parent_scope;1844 Scope *parent_scope;
1816 Scope *child_scope;1845 Scope *child_scope;
1817 LLVMValueRef param_value_ref;1846 LLVMValueRef param_value_ref;
1818 bool shadowable;
1819 size_t mem_slot_index;1847 size_t mem_slot_index;
1820 IrExecutable *owner_exec;1848 IrExecutable *owner_exec;
1821 size_t ref_count;1849 size_t ref_count;
1822 VarLinkage linkage;
1823 uint32_t align_bytes;
18241850
1825 // In an inline loop, multiple variables may be created,1851 // In an inline loop, multiple variables may be created,
1826 // In this case, a reference to a variable should follow1852 // In this case, a reference to a variable should follow
1827 // this pointer to the redefined variable.1853 // this pointer to the redefined variable.
1828 ZigVar *next_var;1854 ZigVar *next_var;
1855
1856 uint32_t align_bytes;
1857 VarLinkage linkage;
1858
1859 bool shadowable;
1860 bool src_is_const;
1861 bool gen_is_const;
1829};1862};
18301863
1831struct ErrorTableEntry {1864struct ErrorTableEntry {
...@@ -1891,10 +1924,11 @@ struct ScopeBlock {...@@ -1891,10 +1924,11 @@ struct ScopeBlock {
1891 ZigList<IrInstruction *> *incoming_values;1924 ZigList<IrInstruction *> *incoming_values;
1892 ZigList<IrBasicBlock *> *incoming_blocks;1925 ZigList<IrBasicBlock *> *incoming_blocks;
18931926
1894 bool safety_off;
1895 AstNode *safety_set_node;1927 AstNode *safety_set_node;
1896 bool fast_math_on;
1897 AstNode *fast_math_set_node;1928 AstNode *fast_math_set_node;
1929
1930 bool safety_off;
1931 bool fast_math_on;
1898};1932};
18991933
1900// This scope is created from every defer expression.1934// This scope is created from every defer expression.
...@@ -2030,8 +2064,19 @@ struct IrBasicBlock {...@@ -2030,8 +2064,19 @@ struct IrBasicBlock {
2030 IrInstruction *must_be_comptime_source_instr;2064 IrInstruction *must_be_comptime_source_instr;
2031};2065};
20322066
2067// These instructions are in transition to having "pass 1" instructions
2068// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
2069// and pass 2 are suffixed with Gen.
2070// Once all instructions are separated in this way, they'll have different
2071// base types for better type safety.
2072// Src instructions are generated by ir_gen_* functions in ir.cpp from AST.
2073// ir_analyze_* functions consume Src instructions and produce Gen instructions.
2074// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
2075// Src instructions do not have type information; Gen instructions do.
2033enum IrInstructionId {2076enum IrInstructionId {
2034 IrInstructionIdInvalid,2077 IrInstructionIdInvalid,
2078 IrInstructionIdDeclVarSrc,
2079 IrInstructionIdDeclVarGen,
2035 IrInstructionIdBr,2080 IrInstructionIdBr,
2036 IrInstructionIdCondBr,2081 IrInstructionIdCondBr,
2037 IrInstructionIdSwitchBr,2082 IrInstructionIdSwitchBr,
...@@ -2040,7 +2085,6 @@ enum IrInstructionId {...@@ -2040,7 +2085,6 @@ enum IrInstructionId {
2040 IrInstructionIdPhi,2085 IrInstructionIdPhi,
2041 IrInstructionIdUnOp,2086 IrInstructionIdUnOp,
2042 IrInstructionIdBinOp,2087 IrInstructionIdBinOp,
2043 IrInstructionIdDeclVar,
2044 IrInstructionIdLoadPtr,2088 IrInstructionIdLoadPtr,
2045 IrInstructionIdStorePtr,2089 IrInstructionIdStorePtr,
2046 IrInstructionIdFieldPtr,2090 IrInstructionIdFieldPtr,
...@@ -2069,7 +2113,7 @@ enum IrInstructionId {...@@ -2069,7 +2113,7 @@ enum IrInstructionId {
2069 IrInstructionIdAsm,2113 IrInstructionIdAsm,
2070 IrInstructionIdSizeOf,2114 IrInstructionIdSizeOf,
2071 IrInstructionIdTestNonNull,2115 IrInstructionIdTestNonNull,
2072 IrInstructionIdUnwrapOptional,2116 IrInstructionIdOptionalUnwrapPtr,
2073 IrInstructionIdOptionalWrap,2117 IrInstructionIdOptionalWrap,
2074 IrInstructionIdUnionTag,2118 IrInstructionIdUnionTag,
2075 IrInstructionIdClz,2119 IrInstructionIdClz,
...@@ -2085,7 +2129,8 @@ enum IrInstructionId {...@@ -2085,7 +2129,8 @@ enum IrInstructionId {
2085 IrInstructionIdCompileLog,2129 IrInstructionIdCompileLog,
2086 IrInstructionIdErrName,2130 IrInstructionIdErrName,
2087 IrInstructionIdEmbedFile,2131 IrInstructionIdEmbedFile,
2088 IrInstructionIdCmpxchg,2132 IrInstructionIdCmpxchgSrc,
2133 IrInstructionIdCmpxchgGen,
2089 IrInstructionIdFence,2134 IrInstructionIdFence,
2090 IrInstructionIdTruncate,2135 IrInstructionIdTruncate,
2091 IrInstructionIdIntCast,2136 IrInstructionIdIntCast,
...@@ -2114,7 +2159,8 @@ enum IrInstructionId {...@@ -2114,7 +2159,8 @@ enum IrInstructionId {
2114 IrInstructionIdErrWrapPayload,2159 IrInstructionIdErrWrapPayload,
2115 IrInstructionIdFnProto,2160 IrInstructionIdFnProto,
2116 IrInstructionIdTestComptime,2161 IrInstructionIdTestComptime,
2117 IrInstructionIdPtrCast,2162 IrInstructionIdPtrCastSrc,
2163 IrInstructionIdPtrCastGen,
2118 IrInstructionIdBitCast,2164 IrInstructionIdBitCast,
2119 IrInstructionIdWidenOrShorten,2165 IrInstructionIdWidenOrShorten,
2120 IrInstructionIdIntToPtr,2166 IrInstructionIdIntToPtr,
...@@ -2194,6 +2240,22 @@ struct IrInstruction {...@@ -2194,6 +2240,22 @@ struct IrInstruction {
2194 bool is_gen;2240 bool is_gen;
2195};2241};
21962242
2243struct IrInstructionDeclVarSrc {
2244 IrInstruction base;
2245
2246 ZigVar *var;
2247 IrInstruction *var_type;
2248 IrInstruction *align_value;
2249 IrInstruction *init_value;
2250};
2251
2252struct IrInstructionDeclVarGen {
2253 IrInstruction base;
2254
2255 ZigVar *var;
2256 IrInstruction *init_value;
2257};
2258
2197struct IrInstructionCondBr {2259struct IrInstructionCondBr {
2198 IrInstruction base;2260 IrInstruction base;
21992261
...@@ -2302,20 +2364,11 @@ struct IrInstructionBinOp {...@@ -2302,20 +2364,11 @@ struct IrInstructionBinOp {
2302 IrInstruction base;2364 IrInstruction base;
23032365
2304 IrInstruction *op1;2366 IrInstruction *op1;
2305 IrBinOp op_id;
2306 IrInstruction *op2;2367 IrInstruction *op2;
2368 IrBinOp op_id;
2307 bool safety_check_on;2369 bool safety_check_on;
2308};2370};
23092371
2310struct IrInstructionDeclVar {
2311 IrInstruction base;
2312
2313 ZigVar *var;
2314 IrInstruction *var_type;
2315 IrInstruction *align_value;
2316 IrInstruction *init_value;
2317};
2318
2319struct IrInstructionLoadPtr {2372struct IrInstructionLoadPtr {
2320 IrInstruction base;2373 IrInstruction base;
23212374
...@@ -2335,7 +2388,6 @@ struct IrInstructionFieldPtr {...@@ -2335,7 +2388,6 @@ struct IrInstructionFieldPtr {
2335 IrInstruction *container_ptr;2388 IrInstruction *container_ptr;
2336 Buf *field_name_buffer;2389 Buf *field_name_buffer;
2337 IrInstruction *field_name_expr;2390 IrInstruction *field_name_expr;
2338 bool is_const;
2339};2391};
23402392
2341struct IrInstructionStructFieldPtr {2393struct IrInstructionStructFieldPtr {
...@@ -2378,13 +2430,13 @@ struct IrInstructionCall {...@@ -2378,13 +2430,13 @@ struct IrInstructionCall {
2378 ZigFn *fn_entry;2430 ZigFn *fn_entry;
2379 size_t arg_count;2431 size_t arg_count;
2380 IrInstruction **args;2432 IrInstruction **args;
2381 bool is_comptime;
2382 LLVMValueRef tmp_ptr;2433 LLVMValueRef tmp_ptr;
2383 FnInline fn_inline;
2384 bool is_async;
23852434
2386 IrInstruction *async_allocator;2435 IrInstruction *async_allocator;
2387 IrInstruction *new_stack;2436 IrInstruction *new_stack;
2437 FnInline fn_inline;
2438 bool is_async;
2439 bool is_comptime;
2388};2440};
23892441
2390struct IrInstructionConst {2442struct IrInstructionConst {
...@@ -2527,9 +2579,9 @@ struct IrInstructionSliceType {...@@ -2527,9 +2579,9 @@ struct IrInstructionSliceType {
2527 IrInstruction base;2579 IrInstruction base;
25282580
2529 IrInstruction *align_value;2581 IrInstruction *align_value;
2582 IrInstruction *child_type;
2530 bool is_const;2583 bool is_const;
2531 bool is_volatile;2584 bool is_volatile;
2532 IrInstruction *child_type;
2533};2585};
25342586
2535struct IrInstructionAsm {2587struct IrInstructionAsm {
...@@ -2557,10 +2609,12 @@ struct IrInstructionTestNonNull {...@@ -2557,10 +2609,12 @@ struct IrInstructionTestNonNull {
2557 IrInstruction *value;2609 IrInstruction *value;
2558};2610};
25592611
2560struct IrInstructionUnwrapOptional {2612// Takes a pointer to an optional value, returns a pointer
2613// to the payload.
2614struct IrInstructionOptionalUnwrapPtr {
2561 IrInstruction base;2615 IrInstruction base;
25622616
2563 IrInstruction *value;2617 IrInstruction *base_ptr;
2564 bool safety_check_on;2618 bool safety_check_on;
2565};2619};
25662620
...@@ -2651,7 +2705,7 @@ struct IrInstructionEmbedFile {...@@ -2651,7 +2705,7 @@ struct IrInstructionEmbedFile {
2651 IrInstruction *name;2705 IrInstruction *name;
2652};2706};
26532707
2654struct IrInstructionCmpxchg {2708struct IrInstructionCmpxchgSrc {
2655 IrInstruction base;2709 IrInstruction base;
26562710
2657 IrInstruction *type_value;2711 IrInstruction *type_value;
...@@ -2661,14 +2715,19 @@ struct IrInstructionCmpxchg {...@@ -2661,14 +2715,19 @@ struct IrInstructionCmpxchg {
2661 IrInstruction *success_order_value;2715 IrInstruction *success_order_value;
2662 IrInstruction *failure_order_value;2716 IrInstruction *failure_order_value;
26632717
2664 // if this instruction gets to runtime then we know these values:
2665 ZigType *type;
2666 AtomicOrder success_order;
2667 AtomicOrder failure_order;
2668
2669 bool is_weak;2718 bool is_weak;
2719};
26702720
2721struct IrInstructionCmpxchgGen {
2722 IrInstruction base;
2723
2724 IrInstruction *ptr;
2725 IrInstruction *cmp_value;
2726 IrInstruction *new_value;
2671 LLVMValueRef tmp_ptr;2727 LLVMValueRef tmp_ptr;
2728 AtomicOrder success_order;
2729 AtomicOrder failure_order;
2730 bool is_weak;
2672};2731};
26732732
2674struct IrInstructionFence {2733struct IrInstructionFence {
...@@ -2851,7 +2910,7 @@ struct IrInstructionTestErr {...@@ -2851,7 +2910,7 @@ struct IrInstructionTestErr {
2851struct IrInstructionUnwrapErrCode {2910struct IrInstructionUnwrapErrCode {
2852 IrInstruction base;2911 IrInstruction base;
28532912
2854 IrInstruction *value;2913 IrInstruction *err_union;
2855};2914};
28562915
2857struct IrInstructionUnwrapErrPayload {2916struct IrInstructionUnwrapErrPayload {
...@@ -2899,13 +2958,19 @@ struct IrInstructionTestComptime {...@@ -2899,13 +2958,19 @@ struct IrInstructionTestComptime {
2899 IrInstruction *value;2958 IrInstruction *value;
2900};2959};
29012960
2902struct IrInstructionPtrCast {2961struct IrInstructionPtrCastSrc {
2903 IrInstruction base;2962 IrInstruction base;
29042963
2905 IrInstruction *dest_type;2964 IrInstruction *dest_type;
2906 IrInstruction *ptr;2965 IrInstruction *ptr;
2907};2966};
29082967
2968struct IrInstructionPtrCastGen {
2969 IrInstruction base;
2970
2971 IrInstruction *ptr;
2972};
2973
2909struct IrInstructionBitCast {2974struct IrInstructionBitCast {
2910 IrInstruction base;2975 IrInstruction base;
29112976
src/analyze.cpp+213-84
...@@ -570,7 +570,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {...@@ -570,7 +570,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
570 if (child_type->zero_bits) {570 if (child_type->zero_bits) {
571 entry->type_ref = LLVMInt1Type();571 entry->type_ref = LLVMInt1Type();
572 entry->di_type = g->builtin_types.entry_bool->di_type;572 entry->di_type = g->builtin_types.entry_bool->di_type;
573 } else if (type_is_codegen_pointer(child_type)) {573 } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
574 assert(child_type->di_type);574 assert(child_type->di_type);
575 // this is an optimization but also is necessary for calling C575 // this is an optimization but also is necessary for calling C
576 // functions where all pointers are maybe pointers576 // functions where all pointers are maybe pointers
...@@ -1278,7 +1278,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind...@@ -1278,7 +1278,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
1278 return entry;1278 return entry;
1279}1279}
12801280
1281static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {1281static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
1282 Buf *type_name)
1283{
1282 size_t backward_branch_count = 0;1284 size_t backward_branch_count = 0;
1283 return ir_eval_const_value(g, scope, node, type_entry,1285 return ir_eval_const_value(g, scope, node, type_entry,
1284 &backward_branch_count, default_backward_branch_quota,1286 &backward_branch_count, default_backward_branch_quota,
...@@ -1286,12 +1288,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod...@@ -1286,12 +1288,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod
1286}1288}
12871289
1288ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {1290ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
1289 IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);1291 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
1290 if (result->value.type->id == ZigTypeIdInvalid)1292 if (type_is_invalid(result->type))
1291 return g->builtin_types.entry_invalid;1293 return g->builtin_types.entry_invalid;
12921294
1293 assert(result->value.special != ConstValSpecialRuntime);1295 assert(result->special != ConstValSpecialRuntime);
1294 return result->value.data.x_type;1296 return result->data.x_type;
1295}1297}
12961298
1297ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {1299ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
...@@ -1342,11 +1344,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou...@@ -1342,11 +1344,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
1342}1344}
13431345
1344static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {1346static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
1345 IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);1347 ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
1346 if (type_is_invalid(align_result->value.type))1348 if (type_is_invalid(align_result->type))
1347 return false;1349 return false;
13481350
1349 uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint);1351 uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint);
1350 if (align_bytes == 0) {1352 if (align_bytes == 0) {
1351 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));1353 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
1352 return false;1354 return false;
...@@ -1364,12 +1366,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **...@@ -1364,12 +1366,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
1364 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,1366 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1365 PtrLenUnknown, 0, 0, 0);1367 PtrLenUnknown, 0, 0, 0);
1366 ZigType *str_type = get_slice_type(g, ptr_type);1368 ZigType *str_type = get_slice_type(g, ptr_type);
1367 IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);1369 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
1368 if (type_is_invalid(instr->value.type))1370 if (type_is_invalid(result_val->type))
1369 return false;1371 return false;
13701372
1371 ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index];1373 ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index];
1372 ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index];1374 ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index];
13731375
1374 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);1376 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
1375 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;1377 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
...@@ -2504,20 +2506,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2504,20 +2506,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2504 // In this first pass we resolve explicit tag values.2506 // In this first pass we resolve explicit tag values.
2505 // In a second pass we will fill in the unspecified ones.2507 // In a second pass we will fill in the unspecified ones.
2506 if (tag_value != nullptr) {2508 if (tag_value != nullptr) {
2507 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);2509 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2508 if (result_inst->value.type->id == ZigTypeIdInvalid) {2510 if (type_is_invalid(result->type)) {
2509 enum_type->data.enumeration.is_invalid = true;2511 enum_type->data.enumeration.is_invalid = true;
2510 continue;2512 continue;
2511 }2513 }
2512 assert(result_inst->value.special != ConstValSpecialRuntime);2514 assert(result->special != ConstValSpecialRuntime);
2513 assert(result_inst->value.type->id == ZigTypeIdInt ||2515 assert(result->type->id == ZigTypeIdInt ||
2514 result_inst->value.type->id == ZigTypeIdComptimeInt);2516 result->type->id == ZigTypeIdComptimeInt);
2515 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);2517 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
2516 if (entry == nullptr) {2518 if (entry == nullptr) {
2517 bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);2519 bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
2518 } else {2520 } else {
2519 Buf *val_buf = buf_alloc();2521 Buf *val_buf = buf_alloc();
2520 bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);2522 bigint_append_buf(val_buf, &result->data.x_bigint, 10);
25212523
2522 ErrorMsg *msg = add_node_error(g, tag_value,2524 ErrorMsg *msg = add_node_error(g, tag_value,
2523 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));2525 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
...@@ -2944,19 +2946,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2944,19 +2946,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2944 // In a second pass we will fill in the unspecified ones.2946 // In a second pass we will fill in the unspecified ones.
2945 if (tag_value != nullptr) {2947 if (tag_value != nullptr) {
2946 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;2948 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
2947 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);2949 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2948 if (result_inst->value.type->id == ZigTypeIdInvalid) {2950 if (type_is_invalid(result->type)) {
2949 union_type->data.unionation.is_invalid = true;2951 union_type->data.unionation.is_invalid = true;
2950 continue;2952 continue;
2951 }2953 }
2952 assert(result_inst->value.special != ConstValSpecialRuntime);2954 assert(result->special != ConstValSpecialRuntime);
2953 assert(result_inst->value.type->id == ZigTypeIdInt);2955 assert(result->type->id == ZigTypeIdInt);
2954 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);2956 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
2955 if (entry == nullptr) {2957 if (entry == nullptr) {
2956 bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint);2958 bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint);
2957 } else {2959 } else {
2958 Buf *val_buf = buf_alloc();2960 Buf *val_buf = buf_alloc();
2959 bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);2961 bigint_append_buf(val_buf, &result->data.x_bigint, 10);
29602962
2961 ErrorMsg *msg = add_node_error(g, tag_value,2963 ErrorMsg *msg = add_node_error(g, tag_value,
2962 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));2964 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
...@@ -3419,7 +3421,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {...@@ -3419,7 +3421,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
3419 resolve_top_level_decl(g, tld, false, tld->source_node);3421 resolve_top_level_decl(g, tld, false, tld->source_node);
3420 assert(tld->id == TldIdVar);3422 assert(tld->id == TldIdVar);
3421 TldVar *tld_var = (TldVar *)tld;3423 TldVar *tld_var = (TldVar *)tld;
3422 tld_var->var->value = value;3424 tld_var->var->const_value = value;
3425 tld_var->var->var_type = value->type;
3423 tld_var->var->align_bytes = get_abi_alignment(g, value->type);3426 tld_var->var->align_bytes = get_abi_alignment(g, value->type);
3424}3427}
34253428
...@@ -3513,7 +3516,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3513,7 +3516,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3513 case NodeTypeArrayType:3516 case NodeTypeArrayType:
3514 case NodeTypeErrorType:3517 case NodeTypeErrorType:
3515 case NodeTypeIfErrorExpr:3518 case NodeTypeIfErrorExpr:
3516 case NodeTypeTestExpr:3519 case NodeTypeIfOptional:
3517 case NodeTypeErrorSetDecl:3520 case NodeTypeErrorSetDecl:
3518 case NodeTypeCancel:3521 case NodeTypeCancel:
3519 case NodeTypeResume:3522 case NodeTypeResume:
...@@ -3582,13 +3585,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry...@@ -3582,13 +3585,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
3582// Set name to nullptr to make the variable anonymous (not visible to programmer).3585// Set name to nullptr to make the variable anonymous (not visible to programmer).
3583// TODO merge with definition of add_local_var in ir.cpp3586// TODO merge with definition of add_local_var in ir.cpp
3584ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,3587ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
3585 bool is_const, ConstExprValue *value, Tld *src_tld)3588 bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type)
3586{3589{
3587 Error err;3590 Error err;
3588 assert(value);3591 assert(const_value != nullptr);
3592 assert(var_type != nullptr);
35893593
3590 ZigVar *variable_entry = allocate<ZigVar>(1);3594 ZigVar *variable_entry = allocate<ZigVar>(1);
3591 variable_entry->value = value;3595 variable_entry->const_value = const_value;
3596 variable_entry->var_type = var_type;
3592 variable_entry->parent_scope = parent_scope;3597 variable_entry->parent_scope = parent_scope;
3593 variable_entry->shadowable = false;3598 variable_entry->shadowable = false;
3594 variable_entry->mem_slot_index = SIZE_MAX;3599 variable_entry->mem_slot_index = SIZE_MAX;
...@@ -3597,23 +3602,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf...@@ -3597,23 +3602,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
3597 assert(name);3602 assert(name);
3598 buf_init_from_buf(&variable_entry->name, name);3603 buf_init_from_buf(&variable_entry->name, name);
35993604
3600 if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {3605 if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
3601 variable_entry->value->type = g->builtin_types.entry_invalid;3606 variable_entry->var_type = g->builtin_types.entry_invalid;
3602 } else {3607 } else {
3603 variable_entry->align_bytes = get_abi_alignment(g, value->type);3608 variable_entry->align_bytes = get_abi_alignment(g, var_type);
36043609
3605 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);3610 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
3606 if (existing_var && !existing_var->shadowable) {3611 if (existing_var && !existing_var->shadowable) {
3607 ErrorMsg *msg = add_node_error(g, source_node,3612 ErrorMsg *msg = add_node_error(g, source_node,
3608 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));3613 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3609 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));3614 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3610 variable_entry->value->type = g->builtin_types.entry_invalid;3615 variable_entry->var_type = g->builtin_types.entry_invalid;
3611 } else {3616 } else {
3612 ZigType *type;3617 ZigType *type;
3613 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {3618 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
3614 add_node_error(g, source_node,3619 add_node_error(g, source_node,
3615 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));3620 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
3616 variable_entry->value->type = g->builtin_types.entry_invalid;3621 variable_entry->var_type = g->builtin_types.entry_invalid;
3617 } else {3622 } else {
3618 Scope *search_scope = nullptr;3623 Scope *search_scope = nullptr;
3619 if (src_tld == nullptr) {3624 if (src_tld == nullptr) {
...@@ -3627,7 +3632,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf...@@ -3627,7 +3632,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
3627 ErrorMsg *msg = add_node_error(g, source_node,3632 ErrorMsg *msg = add_node_error(g, source_node,
3628 buf_sprintf("redefinition of '%s'", buf_ptr(name)));3633 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
3629 add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));3634 add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
3630 variable_entry->value->type = g->builtin_types.entry_invalid;3635 variable_entry->var_type = g->builtin_types.entry_invalid;
3631 }3636 }
3632 }3637 }
3633 }3638 }
...@@ -3677,7 +3682,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3677,7 +3682,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3677 linkage = VarLinkageInternal;3682 linkage = VarLinkageInternal;
3678 }3683 }
36793684
3680 IrInstruction *init_value = nullptr;3685 ConstExprValue *init_value = nullptr;
36813686
3682 // TODO more validation for types that can't be used for export/extern variables3687 // TODO more validation for types that can't be used for export/extern variables
3683 ZigType *implicit_type = nullptr;3688 ZigType *implicit_type = nullptr;
...@@ -3686,7 +3691,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3686,7 +3691,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3686 } else if (var_decl->expr) {3691 } else if (var_decl->expr) {
3687 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);3692 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
3688 assert(init_value);3693 assert(init_value);
3689 implicit_type = init_value->value.type;3694 implicit_type = init_value->type;
36903695
3691 if (implicit_type->id == ZigTypeIdUnreachable) {3696 if (implicit_type->id == ZigTypeIdUnreachable) {
3692 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));3697 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
...@@ -3704,7 +3709,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3704,7 +3709,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3704 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));3709 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
3705 implicit_type = g->builtin_types.entry_invalid;3710 implicit_type = g->builtin_types.entry_invalid;
3706 }3711 }
3707 assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime);3712 assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
3708 } else if (linkage != VarLinkageExternal) {3713 } else if (linkage != VarLinkageExternal) {
3709 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));3714 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
3710 implicit_type = g->builtin_types.entry_invalid;3715 implicit_type = g->builtin_types.entry_invalid;
...@@ -3713,19 +3718,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3713,19 +3718,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3713 ZigType *type = explicit_type ? explicit_type : implicit_type;3718 ZigType *type = explicit_type ? explicit_type : implicit_type;
3714 assert(type != nullptr); // should have been caught by the parser3719 assert(type != nullptr); // should have been caught by the parser
37153720
3716 ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);3721 ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type);
37173722
3718 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,3723 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
3719 is_const, init_val, &tld_var->base);3724 is_const, init_val, &tld_var->base, type);
3720 tld_var->var->linkage = linkage;3725 tld_var->var->linkage = linkage;
37213726
3722 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {3727 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
3723 tld_var->var->value->type = g->builtin_types.entry_invalid;3728 tld_var->var->var_type = g->builtin_types.entry_invalid;
3724 }3729 }
37253730
3726 if (var_decl->align_expr != nullptr) {3731 if (var_decl->align_expr != nullptr) {
3727 if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {3732 if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {
3728 tld_var->var->value->type = g->builtin_types.entry_invalid;3733 tld_var->var->var_type = g->builtin_types.entry_invalid;
3729 }3734 }
3730 }3735 }
37313736
...@@ -4090,7 +4095,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {...@@ -4090,7 +4095,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
4090 }4095 }
40914096
4092 ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,4097 ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
4093 param_name, true, create_const_runtime(param_type), nullptr);4098 param_name, true, create_const_runtime(param_type), nullptr, param_type);
4094 var->src_arg_index = i;4099 var->src_arg_index = i;
4095 fn_table_entry->child_scope = var->child_scope;4100 fn_table_entry->child_scope = var->child_scope;
4096 var->shadowable = var->shadowable || is_var_args;4101 var->shadowable = var->shadowable || is_var_args;
...@@ -4228,18 +4233,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *...@@ -4228,18 +4233,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
4228 preview_use_decl(g, src_use_node);4233 preview_use_decl(g, src_use_node);
4229 }4234 }
42304235
4231 IrInstruction *use_target_value = src_use_node->data.use.value;4236 ConstExprValue *use_target_value = src_use_node->data.use.value;
4232 if (use_target_value->value.type->id == ZigTypeIdInvalid) {4237 if (type_is_invalid(use_target_value->type)) {
4233 dst_use_node->owner->any_imports_failed = true;4238 dst_use_node->owner->any_imports_failed = true;
4234 return;4239 return;
4235 }4240 }
42364241
4237 dst_use_node->data.use.resolution = TldResolutionOk;4242 dst_use_node->data.use.resolution = TldResolutionOk;
42384243
4239 ConstExprValue *const_val = &use_target_value->value;4244 assert(use_target_value->special != ConstValSpecialRuntime);
4240 assert(const_val->special != ConstValSpecialRuntime);
42414245
4242 ImportTableEntry *target_import = const_val->data.x_import;4246 ImportTableEntry *target_import = use_target_value->data.x_import;
4243 assert(target_import);4247 assert(target_import);
42444248
4245 if (target_import->any_imports_failed) {4249 if (target_import->any_imports_failed) {
...@@ -4302,10 +4306,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {...@@ -4302,10 +4306,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
4302 }4306 }
43034307
4304 node->data.use.resolution = TldResolutionResolving;4308 node->data.use.resolution = TldResolutionResolving;
4305 IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base,4309 ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base,
4306 node->data.use.expr, g->builtin_types.entry_namespace, nullptr);4310 node->data.use.expr, g->builtin_types.entry_namespace, nullptr);
43074311
4308 if (result->value.type->id == ZigTypeIdInvalid)4312 if (type_is_invalid(result->type))
4309 node->owner->any_imports_failed = true;4313 node->owner->any_imports_failed = true;
43104314
4311 node->data.use.value = result;4315 node->data.use.value = result;
...@@ -4486,7 +4490,8 @@ bool handle_is_ptr(ZigType *type_entry) {...@@ -4486,7 +4490,8 @@ bool handle_is_ptr(ZigType *type_entry) {
4486 return type_has_bits(type_entry->data.error_union.payload_type);4490 return type_has_bits(type_entry->data.error_union.payload_type);
4487 case ZigTypeIdOptional:4491 case ZigTypeIdOptional:
4488 return type_has_bits(type_entry->data.maybe.child_type) &&4492 return type_has_bits(type_entry->data.maybe.child_type) &&
4489 !type_is_codegen_pointer(type_entry->data.maybe.child_type);4493 !type_is_codegen_pointer(type_entry->data.maybe.child_type) &&
4494 type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet;
4490 case ZigTypeIdUnion:4495 case ZigTypeIdUnion:
4491 assert(type_entry->data.unionation.zero_bits_known);4496 assert(type_entry->data.unionation.zero_bits_known);
4492 if (type_entry->data.unionation.gen_field_count == 0)4497 if (type_entry->data.unionation.gen_field_count == 0)
...@@ -4732,6 +4737,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {...@@ -4732,6 +4737,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
4732 return true;4737 return true;
4733}4738}
47344739
4740static uint32_t hash_const_val_error_set(ConstExprValue *const_val) {
4741 assert(const_val->data.x_err_set != nullptr);
4742 return const_val->data.x_err_set->value ^ 2630160122;
4743}
4744
4735static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {4745static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4736 uint32_t hash_val = 0;4746 uint32_t hash_val = 0;
4737 switch (const_val->data.x_ptr.mut) {4747 switch (const_val->data.x_ptr.mut) {
...@@ -4763,6 +4773,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {...@@ -4763,6 +4773,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4763 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);4773 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
4764 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);4774 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
4765 return hash_val;4775 return hash_val;
4776 case ConstPtrSpecialBaseErrorUnionCode:
4777 hash_val += (uint32_t)2994743799;
4778 hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val);
4779 return hash_val;
4780 case ConstPtrSpecialBaseErrorUnionPayload:
4781 hash_val += (uint32_t)3456080131;
4782 hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val);
4783 return hash_val;
4784 case ConstPtrSpecialBaseOptionalPayload:
4785 hash_val += (uint32_t)3163140517;
4786 hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val);
4787 return hash_val;
4766 case ConstPtrSpecialHardCodedAddr:4788 case ConstPtrSpecialHardCodedAddr:
4767 hash_val += (uint32_t)4048518294;4789 hash_val += (uint32_t)4048518294;
4768 hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);4790 hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);
...@@ -4774,6 +4796,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {...@@ -4774,6 +4796,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4774 hash_val += (uint32_t)2590901619;4796 hash_val += (uint32_t)2590901619;
4775 hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);4797 hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
4776 return hash_val;4798 return hash_val;
4799 case ConstPtrSpecialNull:
4800 hash_val += (uint32_t)1486246455;
4801 return hash_val;
4777 }4802 }
4778 zig_unreachable();4803 zig_unreachable();
4779}4804}
...@@ -4872,7 +4897,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -4872,7 +4897,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
4872 return 2709806591;4897 return 2709806591;
4873 case ZigTypeIdOptional:4898 case ZigTypeIdOptional:
4874 if (get_codegen_ptr_type(const_val->type) != nullptr) {4899 if (get_codegen_ptr_type(const_val->type) != nullptr) {
4875 return hash_const_val(const_val) * 1992916303;4900 return hash_const_val_ptr(const_val) * 1992916303;
4901 } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
4902 return hash_const_val_error_set(const_val) * 3147031929;
4876 } else {4903 } else {
4877 if (const_val->data.x_optional) {4904 if (const_val->data.x_optional) {
4878 return hash_const_val(const_val->data.x_optional) * 1992916303;4905 return hash_const_val(const_val->data.x_optional) * 1992916303;
...@@ -4884,8 +4911,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -4884,8 +4911,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
4884 // TODO better hashing algorithm4911 // TODO better hashing algorithm
4885 return 3415065496;4912 return 3415065496;
4886 case ZigTypeIdErrorSet:4913 case ZigTypeIdErrorSet:
4887 assert(const_val->data.x_err_set != nullptr);4914 return hash_const_val_error_set(const_val);
4888 return const_val->data.x_err_set->value ^ 2630160122;
4889 case ZigTypeIdNamespace:4915 case ZigTypeIdNamespace:
4890 return hash_ptr(const_val->data.x_import);4916 return hash_ptr(const_val->data.x_import);
4891 case ZigTypeIdBoundFn:4917 case ZigTypeIdBoundFn:
...@@ -4987,7 +5013,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {...@@ -4987,7 +5013,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
4987 return can_mutate_comptime_var_state(value->data.x_optional);5013 return can_mutate_comptime_var_state(value->data.x_optional);
49885014
4989 case ZigTypeIdErrorUnion:5015 case ZigTypeIdErrorUnion:
4990 if (value->data.x_err_union.err != nullptr)5016 if (value->data.x_err_union.error_set->data.x_err_set != nullptr)
4991 return false;5017 return false;
4992 assert(value->data.x_err_union.payload != nullptr);5018 assert(value->data.x_err_union.payload != nullptr);
4993 return can_mutate_comptime_var_state(value->data.x_err_union.payload);5019 return can_mutate_comptime_var_state(value->data.x_err_union.payload);
...@@ -5048,9 +5074,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {...@@ -5048,9 +5074,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
5048 while (scope) {5074 while (scope) {
5049 if (scope->id == ScopeIdVarDecl) {5075 if (scope->id == ScopeIdVarDecl) {
5050 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;5076 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5051 if (type_is_invalid(var_scope->var->value->type))5077 if (type_is_invalid(var_scope->var->var_type))
5052 return false;5078 return false;
5053 if (can_mutate_comptime_var_state(var_scope->var->value))5079 if (can_mutate_comptime_var_state(var_scope->var->const_value))
5054 return false;5080 return false;
5055 } else if (scope->id == ScopeIdFnDef) {5081 } else if (scope->id == ScopeIdFnDef) {
5056 return true;5082 return true;
...@@ -5068,7 +5094,7 @@ uint32_t fn_eval_hash(Scope* scope) {...@@ -5068,7 +5094,7 @@ uint32_t fn_eval_hash(Scope* scope) {
5068 while (scope) {5094 while (scope) {
5069 if (scope->id == ScopeIdVarDecl) {5095 if (scope->id == ScopeIdVarDecl) {
5070 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;5096 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5071 result += hash_const_val(var_scope->var->value);5097 result += hash_const_val(var_scope->var->const_value);
5072 } else if (scope->id == ScopeIdFnDef) {5098 } else if (scope->id == ScopeIdFnDef) {
5073 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;5099 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
5074 result += hash_ptr(fn_scope->fn_entry);5100 result += hash_ptr(fn_scope->fn_entry);
...@@ -5092,10 +5118,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {...@@ -5092,10 +5118,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {
5092 if (a->id == ScopeIdVarDecl) {5118 if (a->id == ScopeIdVarDecl) {
5093 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;5119 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
5094 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;5120 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
5095 if (a_var_scope->var->value->type != b_var_scope->var->value->type)5121 if (a_var_scope->var->var_type != b_var_scope->var->var_type)
5096 return false;
5097 if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
5098 return false;5122 return false;
5123 if (a_var_scope->var->var_type == a_var_scope->var->const_value->type &&
5124 b_var_scope->var->var_type == b_var_scope->var->const_value->type)
5125 {
5126 if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value))
5127 return false;
5128 } else {
5129 zig_panic("TODO comptime ptr reinterpret for fn_eval_eql");
5130 }
5099 } else if (a->id == ScopeIdFnDef) {5131 } else if (a->id == ScopeIdFnDef) {
5100 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;5132 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
5101 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;5133 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
...@@ -5113,6 +5145,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {...@@ -5113,6 +5145,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
5113 return false;5145 return false;
5114}5146}
51155147
5148// Whether the type has bits at runtime.
5116bool type_has_bits(ZigType *type_entry) {5149bool type_has_bits(ZigType *type_entry) {
5117 assert(type_entry);5150 assert(type_entry);
5118 assert(!type_is_invalid(type_entry));5151 assert(!type_is_invalid(type_entry));
...@@ -5120,6 +5153,65 @@ bool type_has_bits(ZigType *type_entry) {...@@ -5120,6 +5153,65 @@ bool type_has_bits(ZigType *type_entry) {
5120 return !type_entry->zero_bits;5153 return !type_entry->zero_bits;
5121}5154}
51225155
5156// Whether you can infer the value based solely on the type.
5157OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
5158 assert(type_entry != nullptr);
5159 Error err;
5160 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
5161 return OnePossibleValueInvalid;
5162 switch (type_entry->id) {
5163 case ZigTypeIdInvalid:
5164 zig_unreachable();
5165 case ZigTypeIdOpaque:
5166 case ZigTypeIdComptimeFloat:
5167 case ZigTypeIdComptimeInt:
5168 case ZigTypeIdMetaType:
5169 case ZigTypeIdNamespace:
5170 case ZigTypeIdBoundFn:
5171 case ZigTypeIdArgTuple:
5172 case ZigTypeIdOptional:
5173 case ZigTypeIdFn:
5174 case ZigTypeIdBool:
5175 case ZigTypeIdFloat:
5176 case ZigTypeIdPromise:
5177 case ZigTypeIdErrorUnion:
5178 return OnePossibleValueNo;
5179 case ZigTypeIdUndefined:
5180 case ZigTypeIdNull:
5181 case ZigTypeIdVoid:
5182 case ZigTypeIdUnreachable:
5183 return OnePossibleValueYes;
5184 case ZigTypeIdArray:
5185 if (type_entry->data.array.len == 0)
5186 return OnePossibleValueYes;
5187 return type_has_one_possible_value(g, type_entry->data.array.child_type);
5188 case ZigTypeIdStruct:
5189 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
5190 TypeStructField *field = &type_entry->data.structure.fields[i];
5191 switch (type_has_one_possible_value(g, field->type_entry)) {
5192 case OnePossibleValueInvalid:
5193 return OnePossibleValueInvalid;
5194 case OnePossibleValueNo:
5195 return OnePossibleValueNo;
5196 case OnePossibleValueYes:
5197 continue;
5198 }
5199 }
5200 return OnePossibleValueYes;
5201 case ZigTypeIdErrorSet:
5202 case ZigTypeIdEnum:
5203 case ZigTypeIdInt:
5204 return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
5205 case ZigTypeIdPointer:
5206 return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
5207 case ZigTypeIdUnion:
5208 if (type_entry->data.unionation.src_field_count > 1)
5209 return OnePossibleValueNo;
5210 return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry);
5211 }
5212 zig_unreachable();
5213}
5214
5123ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {5215ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
5124 Error err;5216 Error err;
5125 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))5217 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
...@@ -5574,6 +5666,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {...@@ -5574,6 +5666,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
5574 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)5666 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
5575 return false;5667 return false;
5576 return true;5668 return true;
5669 case ConstPtrSpecialBaseErrorUnionCode:
5670 if (a->data.x_ptr.data.base_err_union_code.err_union_val !=
5671 b->data.x_ptr.data.base_err_union_code.err_union_val &&
5672 a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs !=
5673 b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs)
5674 {
5675 return false;
5676 }
5677 return true;
5678 case ConstPtrSpecialBaseErrorUnionPayload:
5679 if (a->data.x_ptr.data.base_err_union_payload.err_union_val !=
5680 b->data.x_ptr.data.base_err_union_payload.err_union_val &&
5681 a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs !=
5682 b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs)
5683 {
5684 return false;
5685 }
5686 return true;
5687 case ConstPtrSpecialBaseOptionalPayload:
5688 if (a->data.x_ptr.data.base_optional_payload.optional_val !=
5689 b->data.x_ptr.data.base_optional_payload.optional_val &&
5690 a->data.x_ptr.data.base_optional_payload.optional_val->global_refs !=
5691 b->data.x_ptr.data.base_optional_payload.optional_val->global_refs)
5692 {
5693 return false;
5694 }
5695 return true;
5577 case ConstPtrSpecialHardCodedAddr:5696 case ConstPtrSpecialHardCodedAddr:
5578 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)5697 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
5579 return false;5698 return false;
...@@ -5582,6 +5701,8 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {...@@ -5582,6 +5701,8 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
5582 return true;5701 return true;
5583 case ConstPtrSpecialFunction:5702 case ConstPtrSpecialFunction:
5584 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;5703 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
5704 case ConstPtrSpecialNull:
5705 return true;
5585 }5706 }
5586 zig_unreachable();5707 zig_unreachable();
5587}5708}
...@@ -5750,7 +5871,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v...@@ -5750,7 +5871,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v
5750 }5871 }
5751}5872}
57525873
5753void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {5874static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
5754 assert(type_entry->id == ZigTypeIdPointer);5875 assert(type_entry->id == ZigTypeIdPointer);
57555876
5756 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {5877 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
...@@ -5763,6 +5884,9 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy...@@ -5763,6 +5884,9 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
5763 zig_unreachable();5884 zig_unreachable();
5764 case ConstPtrSpecialRef:5885 case ConstPtrSpecialRef:
5765 case ConstPtrSpecialBaseStruct:5886 case ConstPtrSpecialBaseStruct:
5887 case ConstPtrSpecialBaseErrorUnionCode:
5888 case ConstPtrSpecialBaseErrorUnionPayload:
5889 case ConstPtrSpecialBaseOptionalPayload:
5766 buf_appendf(buf, "*");5890 buf_appendf(buf, "*");
5767 // TODO we need a source node for const_ptr_pointee because it can generate compile errors5891 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
5768 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));5892 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
...@@ -5790,10 +5914,21 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy...@@ -5790,10 +5914,21 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
5790 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));5914 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
5791 return;5915 return;
5792 }5916 }
5917 case ConstPtrSpecialNull:
5918 buf_append_str(buf, "null");
5919 return;
5793 }5920 }
5794 zig_unreachable();5921 zig_unreachable();
5795}5922}
57965923
5924static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
5925 if (const_val->data.x_err_set == nullptr) {
5926 buf_append_str(buf, "null");
5927 } else {
5928 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
5929 }
5930}
5931
5797void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {5932void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5798 switch (const_val->special) {5933 switch (const_val->special) {
5799 case ConstValSpecialRuntime:5934 case ConstValSpecialRuntime:
...@@ -5921,6 +6056,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5921,6 +6056,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5921 {6056 {
5922 if (get_codegen_ptr_type(const_val->type) != nullptr)6057 if (get_codegen_ptr_type(const_val->type) != nullptr)
5923 return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);6058 return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
6059 if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet)
6060 return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type);
5924 if (const_val->data.x_optional) {6061 if (const_val->data.x_optional) {
5925 render_const_value(g, buf, const_val->data.x_optional);6062 render_const_value(g, buf, const_val->data.x_optional);
5926 } else {6063 } else {
...@@ -5958,11 +6095,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5958,11 +6095,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5958 case ZigTypeIdErrorUnion:6095 case ZigTypeIdErrorUnion:
5959 {6096 {
5960 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));6097 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
5961 if (const_val->data.x_err_union.err == nullptr) {6098 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6099 if (err_set == nullptr) {
5962 render_const_value(g, buf, const_val->data.x_err_union.payload);6100 render_const_value(g, buf, const_val->data.x_err_union.payload);
5963 } else {6101 } else {
5964 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),6102 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
5965 buf_ptr(&const_val->data.x_err_union.err->name));6103 buf_ptr(&err_set->name));
5966 }6104 }
5967 buf_appendf(buf, ")");6105 buf_appendf(buf, ")");
5968 return;6106 return;
...@@ -5977,10 +6115,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5977,10 +6115,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5977 return;6115 return;
5978 }6116 }
5979 case ZigTypeIdErrorSet:6117 case ZigTypeIdErrorSet:
5980 {6118 return render_const_val_err_set(g, buf, const_val, type_entry);
5981 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
5982 return;
5983 }
5984 case ZigTypeIdArgTuple:6119 case ZigTypeIdArgTuple:
5985 {6120 {
5986 buf_appendf(buf, "(args value)");6121 buf_appendf(buf, "(args value)");
...@@ -6172,6 +6307,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {...@@ -6172,6 +6307,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
6172// Canonicalize the array value as ConstArraySpecialNone6307// Canonicalize the array value as ConstArraySpecialNone
6173void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {6308void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6174 assert(const_val->type->id == ZigTypeIdArray);6309 assert(const_val->type->id == ZigTypeIdArray);
6310 if (const_val->special == ConstValSpecialUndef) {
6311 const_val->special = ConstValSpecialStatic;
6312 const_val->data.x_array.special = ConstArraySpecialUndef;
6313 }
6175 switch (const_val->data.x_array.special) {6314 switch (const_val->data.x_array.special) {
6176 case ConstArraySpecialNone:6315 case ConstArraySpecialNone:
6177 return;6316 return;
...@@ -6215,17 +6354,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {...@@ -6215,17 +6354,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6215}6354}
62166355
6217ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {6356ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
6218 assert(value->type);6357 return &value->parent;
6219 ZigType *type_entry = value->type;
6220 if (type_entry->id == ZigTypeIdArray) {
6221 expand_undef_array(g, value);
6222 return &value->data.x_array.data.s_none.parent;
6223 } else if (type_entry->id == ZigTypeIdStruct) {
6224 return &value->data.x_struct.parent;
6225 } else if (type_entry->id == ZigTypeIdUnion) {
6226 return &value->data.x_union.parent;
6227 }
6228 return nullptr;
6229}6358}
62306359
6231static const ZigTypeId all_type_ids[] = {6360static const ZigTypeId all_type_ids[] = {
...@@ -6453,7 +6582,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {...@@ -6453,7 +6582,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
6453 resolve_top_level_decl(codegen, tld, false, nullptr);6582 resolve_top_level_decl(codegen, tld, false, nullptr);
6454 assert(tld->id == TldIdVar);6583 assert(tld->id == TldIdVar);
6455 TldVar *tld_var = (TldVar *)tld;6584 TldVar *tld_var = (TldVar *)tld;
6456 ConstExprValue *var_value = tld_var->var->value;6585 ConstExprValue *var_value = tld_var->var->const_value;
6457 assert(var_value != nullptr);6586 assert(var_value != nullptr);
6458 return var_value;6587 return var_value;
6459}6588}
src/analyze.hpp+8-1
...@@ -81,7 +81,7 @@ ZigFn *scope_fn_entry(Scope *scope);...@@ -81,7 +81,7 @@ ZigFn *scope_fn_entry(Scope *scope);
81ImportTableEntry *get_scope_import(Scope *scope);81ImportTableEntry *get_scope_import(Scope *scope);
82void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);82void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
83ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,83ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
84 bool is_const, ConstExprValue *init_value, Tld *src_tld);84 bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type);
85ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);85ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
86ZigFn *create_fn(CodeGen *g, AstNode *proto_node);86ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
87ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);87ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
...@@ -222,6 +222,13 @@ enum ReqCompTime {...@@ -222,6 +222,13 @@ enum ReqCompTime {
222};222};
223ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);223ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
224224
225enum OnePossibleValue {
226 OnePossibleValueInvalid,
227 OnePossibleValueNo,
228 OnePossibleValueYes,
229};
230OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
231
225Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,232Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
226 ConstExprValue *const_val, ZigType *wanted_type);233 ConstExprValue *const_val, ZigType *wanted_type);
227234
src/ast_render.cpp+4-4
...@@ -233,8 +233,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -233,8 +233,8 @@ static const char *node_type_str(NodeType node_type) {
233 return "ErrorType";233 return "ErrorType";
234 case NodeTypeIfErrorExpr:234 case NodeTypeIfErrorExpr:
235 return "IfErrorExpr";235 return "IfErrorExpr";
236 case NodeTypeTestExpr:236 case NodeTypeIfOptional:
237 return "TestExpr";237 return "IfOptional";
238 case NodeTypeErrorSetDecl:238 case NodeTypeErrorSetDecl:
239 return "ErrorSetDecl";239 return "ErrorSetDecl";
240 case NodeTypeCancel:240 case NodeTypeCancel:
...@@ -387,7 +387,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {...@@ -387,7 +387,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
387 if (node->data.if_err_expr.else_node)387 if (node->data.if_err_expr.else_node)
388 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);388 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
389 return node->data.if_err_expr.then_node->type == NodeTypeBlock;389 return node->data.if_err_expr.then_node->type == NodeTypeBlock;
390 case NodeTypeTestExpr:390 case NodeTypeIfOptional:
391 if (node->data.test_expr.else_node)391 if (node->data.test_expr.else_node)
392 return statement_terminates_without_semicolon(node->data.test_expr.else_node);392 return statement_terminates_without_semicolon(node->data.test_expr.else_node);
393 return node->data.test_expr.then_node->type == NodeTypeBlock;393 return node->data.test_expr.then_node->type == NodeTypeBlock;
...@@ -974,7 +974,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -974,7 +974,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
974 }974 }
975 break;975 break;
976 }976 }
977 case NodeTypeTestExpr:977 case NodeTypeIfOptional:
978 {978 {
979 fprintf(ar->f, "if (");979 fprintf(ar->f, "if (");
980 render_node_grouped(ar, node->data.test_expr.target_node);980 render_node_grouped(ar, node->data.test_expr.target_node);
src/codegen.cpp+285-100
...@@ -313,6 +313,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *...@@ -313,6 +313,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *
313static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);313static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
314static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);314static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);
315static void generate_error_name_table(CodeGen *g);315static void generate_error_name_table(CodeGen *g);
316static bool value_is_all_undef(ConstExprValue *const_val);
317static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);
316318
317static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {319static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
318 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));320 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
...@@ -461,6 +463,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag...@@ -461,6 +463,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag
461 }463 }
462}464}
463465
466static bool cc_want_sret_attr(CallingConvention cc) {
467 switch (cc) {
468 case CallingConventionNaked:
469 zig_unreachable();
470 case CallingConventionC:
471 case CallingConventionCold:
472 case CallingConventionStdcall:
473 return true;
474 case CallingConventionAsync:
475 case CallingConventionUnspecified:
476 return false;
477 }
478 zig_unreachable();
479}
480
464static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {481static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
465 if (fn_table_entry->llvm_value)482 if (fn_table_entry->llvm_value)
466 return fn_table_entry->llvm_value;483 return fn_table_entry->llvm_value;
...@@ -598,9 +615,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -598,9 +615,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
598 } else if (type_is_codegen_pointer(return_type)) {615 } else if (type_is_codegen_pointer(return_type)) {
599 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");616 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
600 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {617 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
601 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
602 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");618 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
603 if (cc == CallingConventionC) {619 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
620 if (cc_want_sret_attr(cc)) {
604 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");621 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
605 }622 }
606 init_gen_i = 1;623 init_gen_i = 1;
...@@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {...@@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
2200 assert(variable);2217 assert(variable);
2201 assert(variable->value_ref);2218 assert(variable->value_ref);
22022219
2203 if (!handle_is_ptr(variable->value->type)) {2220 if (!handle_is_ptr(variable->var_type)) {
2204 clear_debug_source_node(g);2221 clear_debug_source_node(g);
2205 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref,2222 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index),
2206 variable->align_bytes, false);2223 variable->value_ref, variable->align_bytes, false);
2207 }2224 }
22082225
2209 if (variable->decl_node) {2226 if (variable->decl_node) {
...@@ -2961,7 +2978,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -2961,7 +2978,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2961}2978}
29622979
2963static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,2980static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
2964 IrInstructionPtrCast *instruction)2981 IrInstructionPtrCastGen *instruction)
2965{2982{
2966 ZigType *wanted_type = instruction->base.value.type;2983 ZigType *wanted_type = instruction->base.value.type;
2967 if (!type_has_bits(wanted_type)) {2984 if (!type_has_bits(wanted_type)) {
...@@ -3149,11 +3166,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI...@@ -3149,11 +3166,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
3149}3166}
31503167
3151static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,3168static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
3152 IrInstructionDeclVar *decl_var_instruction)3169 IrInstructionDeclVarGen *decl_var_instruction)
3153{3170{
3154 ZigVar *var = decl_var_instruction->var;3171 ZigVar *var = decl_var_instruction->var;
31553172
3156 if (!type_has_bits(var->value->type))3173 if (!type_has_bits(var->var_type))
3157 return nullptr;3174 return nullptr;
31583175
3159 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)3176 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
...@@ -3161,34 +3178,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -3161,34 +3178,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
31613178
3162 IrInstruction *init_value = decl_var_instruction->init_value;3179 IrInstruction *init_value = decl_var_instruction->init_value;
31633180
3164 bool have_init_expr = false;3181 bool have_init_expr = !value_is_all_undef(&init_value->value);
3165
3166 ConstExprValue *const_val = &init_value->value;
3167 if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
3168 have_init_expr = true;
31693182
3170 if (have_init_expr) {3183 if (have_init_expr) {
3171 assert(var->value->type == init_value->value.type);3184 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
3172 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
3173 PtrLenSingle, var->align_bytes, 0, 0);3185 PtrLenSingle, var->align_bytes, 0, 0);
3174 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);3186 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
3175 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);3187 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
3176 } else {3188 } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
3177 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);3189 uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
3178 if (want_safe) {3190 gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
3179 ZigType *usize = g->builtin_types.entry_usize;
3180 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref);
3181 assert(size_bytes > 0);
3182
3183 assert(var->align_bytes > 0);
3184
3185 // memset uninitialized memory to 0xa
3186 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3187 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
3188 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, "");
3189 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3190 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false);
3191 }
3192 }3191 }
31933192
3194 gen_var_debug_decl(g, var);3193 gen_var_debug_decl(g, var);
...@@ -3225,21 +3224,75 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3225,21 +3224,75 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
3225 return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");3224 return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
3226}3225}
32273226
3228static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {3227static bool value_is_all_undef(ConstExprValue *const_val) {
3229 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);3228 switch (const_val->special) {
3230 LLVMValueRef value = ir_llvm_value(g, instruction->value);3229 case ConstValSpecialRuntime:
3230 return false;
3231 case ConstValSpecialUndef:
3232 return true;
3233 case ConstValSpecialStatic:
3234 if (const_val->type->id == ZigTypeIdStruct) {
3235 for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) {
3236 if (!value_is_all_undef(&const_val->data.x_struct.fields[i]))
3237 return false;
3238 }
3239 return true;
3240 } else if (const_val->type->id == ZigTypeIdArray) {
3241 switch (const_val->data.x_array.special) {
3242 case ConstArraySpecialUndef:
3243 return true;
3244 case ConstArraySpecialBuf:
3245 return false;
3246 case ConstArraySpecialNone:
3247 for (size_t i = 0; i < const_val->type->data.array.len; i += 1) {
3248 if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i]))
3249 return false;
3250 }
3251 return true;
3252 }
3253 zig_unreachable();
3254 } else {
3255 return false;
3256 }
3257 }
3258 zig_unreachable();
3259}
32313260
3232 assert(instruction->ptr->value.type->id == ZigTypeIdPointer);3261static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
3233 ZigType *ptr_type = instruction->ptr->value.type;3262 assert(type_has_bits(value_type));
3263 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);
3264 assert(size_bytes > 0);
3265 assert(ptr_align_bytes > 0);
3266 // memset uninitialized memory to 0xaa
3267 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3268 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
3269 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
3270 ZigType *usize = g->builtin_types.entry_usize;
3271 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3272 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
3273}
32343274
3235 gen_assign_raw(g, ptr, ptr_type, value);3275static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
3276 ZigType *ptr_type = instruction->ptr->value.type;
3277 assert(ptr_type->id == ZigTypeIdPointer);
3278 if (!type_has_bits(ptr_type))
3279 return nullptr;
32363280
3281 bool have_init_expr = !value_is_all_undef(&instruction->value->value);
3282 if (have_init_expr) {
3283 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3284 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3285 gen_assign_raw(g, ptr, ptr_type, value);
3286 } else if (ir_want_runtime_safety(g, &instruction->base)) {
3287 gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
3288 ir_llvm_value(g, instruction->ptr));
3289 }
3237 return nullptr;3290 return nullptr;
3238}3291}
32393292
3240static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {3293static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
3241 ZigVar *var = instruction->var;3294 ZigVar *var = instruction->var;
3242 if (type_has_bits(var->value->type)) {3295 if (type_has_bits(var->var_type)) {
3243 assert(var->value_ref);3296 assert(var->value_ref);
3244 return var->value_ref;3297 return var->value_ref;
3245 } else {3298 } else {
...@@ -3553,7 +3606,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab...@@ -3553,7 +3606,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
3553 LLVMPositionBuilderAtEnd(g->builder, ok_block);3606 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3554 }3607 }
35553608
3556 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, "");3609 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
3610 union_type->data.unionation.gen_union_index, "");
3557 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");3611 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
3558 return bitcasted_union_field_ptr;3612 return bitcasted_union_field_ptr;
3559}3613}
...@@ -3715,8 +3769,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR...@@ -3715,8 +3769,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
3715 if (child_type->zero_bits) {3769 if (child_type->zero_bits) {
3716 return maybe_handle;3770 return maybe_handle;
3717 } else {3771 } else {
3718 bool maybe_is_ptr = type_is_codegen_pointer(child_type);3772 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3719 if (maybe_is_ptr) {3773 if (is_scalar) {
3720 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");3774 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
3721 } else {3775 } else {
3722 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");3776 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
...@@ -3731,17 +3785,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable...@@ -3731,17 +3785,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
3731 return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));3785 return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));
3732}3786}
37333787
3734static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,3788static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
3735 IrInstructionUnwrapOptional *instruction)3789 IrInstructionOptionalUnwrapPtr *instruction)
3736{3790{
3737 ZigType *ptr_type = instruction->value->value.type;3791 ZigType *ptr_type = instruction->base_ptr->value.type;
3738 assert(ptr_type->id == ZigTypeIdPointer);3792 assert(ptr_type->id == ZigTypeIdPointer);
3739 ZigType *maybe_type = ptr_type->data.pointer.child_type;3793 ZigType *maybe_type = ptr_type->data.pointer.child_type;
3740 assert(maybe_type->id == ZigTypeIdOptional);3794 assert(maybe_type->id == ZigTypeIdOptional);
3741 ZigType *child_type = maybe_type->data.maybe.child_type;3795 ZigType *child_type = maybe_type->data.maybe.child_type;
3742 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);3796 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
3743 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
3744 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {3797 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
3798 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
3745 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);3799 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
3746 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");3800 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
3747 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");3801 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
...@@ -3755,8 +3809,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,...@@ -3755,8 +3809,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
3755 if (child_type->zero_bits) {3809 if (child_type->zero_bits) {
3756 return nullptr;3810 return nullptr;
3757 } else {3811 } else {
3758 bool maybe_is_ptr = type_is_codegen_pointer(child_type);3812 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3759 if (maybe_is_ptr) {3813 if (is_scalar) {
3760 return maybe_ptr;3814 return maybe_ptr;
3761 } else {3815 } else {
3762 LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);3816 LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
...@@ -4174,7 +4228,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)...@@ -4174,7 +4228,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)
4174 zig_unreachable();4228 zig_unreachable();
4175}4229}
41764230
4177static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {4231static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) {
4178 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);4232 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
4179 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);4233 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
4180 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);4234 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
...@@ -4189,18 +4243,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn...@@ -4189,18 +4243,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
4189 assert(maybe_type->id == ZigTypeIdOptional);4243 assert(maybe_type->id == ZigTypeIdOptional);
4190 ZigType *child_type = maybe_type->data.maybe.child_type;4244 ZigType *child_type = maybe_type->data.maybe.child_type;
41914245
4192 if (type_is_codegen_pointer(child_type)) {4246 if (!handle_is_ptr(maybe_type)) {
4193 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");4247 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
4194 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");4248 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
4195 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");4249 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");
4196 }4250 }
41974251
4198 assert(instruction->tmp_ptr != nullptr);4252 assert(instruction->tmp_ptr != nullptr);
4199 assert(type_has_bits(instruction->type));4253 assert(type_has_bits(child_type));
42004254
4201 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");4255 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
4202 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");4256 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
4203 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val);4257 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
42044258
4205 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");4259 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
4206 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");4260 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
...@@ -4351,6 +4405,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst...@@ -4351,6 +4405,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
4351 assert(array_type->data.structure.is_slice);4405 assert(array_type->data.structure.is_slice);
4352 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);4406 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
4353 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);4407 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
4408 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
43544409
4355 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;4410 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
4356 assert(ptr_index != SIZE_MAX);4411 assert(ptr_index != SIZE_MAX);
...@@ -4540,12 +4595,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI...@@ -4540,12 +4595,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
4540 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");4595 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
4541}4596}
45424597
4543static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {4598static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
4544 ZigType *ptr_type = instruction->value->value.type;4599 IrInstructionUnwrapErrCode *instruction)
4600{
4601 ZigType *ptr_type = instruction->err_union->value.type;
4545 assert(ptr_type->id == ZigTypeIdPointer);4602 assert(ptr_type->id == ZigTypeIdPointer);
4546 ZigType *err_union_type = ptr_type->data.pointer.child_type;4603 ZigType *err_union_type = ptr_type->data.pointer.child_type;
4547 ZigType *payload_type = err_union_type->data.error_union.payload_type;4604 ZigType *payload_type = err_union_type->data.error_union.payload_type;
4548 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);4605 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union);
4549 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);4606 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
45504607
4551 if (type_has_bits(payload_type)) {4608 if (type_has_bits(payload_type)) {
...@@ -4556,7 +4613,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab...@@ -4556,7 +4613,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
4556 }4613 }
4557}4614}
45584615
4559static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {4616static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
4617 IrInstructionUnwrapErrPayload *instruction)
4618{
4619 bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&
4620 g->errors_by_index.length > 1;
4621 if (!want_safety && !type_has_bits(instruction->base.value.type))
4622 return nullptr;
4560 ZigType *ptr_type = instruction->value->value.type;4623 ZigType *ptr_type = instruction->value->value.type;
4561 assert(ptr_type->id == ZigTypeIdPointer);4624 assert(ptr_type->id == ZigTypeIdPointer);
4562 ZigType *err_union_type = ptr_type->data.pointer.child_type;4625 ZigType *err_union_type = ptr_type->data.pointer.child_type;
...@@ -4568,7 +4631,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu...@@ -4568,7 +4631,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
4568 return err_union_handle;4631 return err_union_handle;
4569 }4632 }
45704633
4571 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {4634 if (want_safety) {
4572 LLVMValueRef err_val;4635 LLVMValueRef err_val;
4573 if (type_has_bits(payload_type)) {4636 if (type_has_bits(payload_type)) {
4574 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");4637 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
...@@ -4607,7 +4670,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I...@@ -4607,7 +4670,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
4607 }4670 }
46084671
4609 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);4672 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
4610 if (type_is_codegen_pointer(child_type)) {4673 if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
4611 return payload_val;4674 return payload_val;
4612 }4675 }
46134676
...@@ -5184,12 +5247,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5184,12 +5247,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5184 case IrInstructionIdToBytes:5247 case IrInstructionIdToBytes:
5185 case IrInstructionIdEnumToInt:5248 case IrInstructionIdEnumToInt:
5186 case IrInstructionIdCheckRuntimeScope:5249 case IrInstructionIdCheckRuntimeScope:
5250 case IrInstructionIdDeclVarSrc:
5251 case IrInstructionIdPtrCastSrc:
5252 case IrInstructionIdCmpxchgSrc:
5187 zig_unreachable();5253 zig_unreachable();
51885254
5255 case IrInstructionIdDeclVarGen:
5256 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
5189 case IrInstructionIdReturn:5257 case IrInstructionIdReturn:
5190 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);5258 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
5191 case IrInstructionIdDeclVar:
5192 return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
5193 case IrInstructionIdBinOp:5259 case IrInstructionIdBinOp:
5194 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);5260 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
5195 case IrInstructionIdCast:5261 case IrInstructionIdCast:
...@@ -5220,8 +5286,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5220,8 +5286,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5220 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);5286 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
5221 case IrInstructionIdTestNonNull:5287 case IrInstructionIdTestNonNull:
5222 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);5288 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
5223 case IrInstructionIdUnwrapOptional:5289 case IrInstructionIdOptionalUnwrapPtr:
5224 return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);5290 return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction);
5225 case IrInstructionIdClz:5291 case IrInstructionIdClz:
5226 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);5292 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
5227 case IrInstructionIdCtz:5293 case IrInstructionIdCtz:
...@@ -5236,8 +5302,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5236,8 +5302,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5236 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);5302 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
5237 case IrInstructionIdErrName:5303 case IrInstructionIdErrName:
5238 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);5304 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
5239 case IrInstructionIdCmpxchg:5305 case IrInstructionIdCmpxchgGen:
5240 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction);5306 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction);
5241 case IrInstructionIdFence:5307 case IrInstructionIdFence:
5242 return ir_render_fence(g, executable, (IrInstructionFence *)instruction);5308 return ir_render_fence(g, executable, (IrInstructionFence *)instruction);
5243 case IrInstructionIdTruncate:5309 case IrInstructionIdTruncate:
...@@ -5278,8 +5344,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5278,8 +5344,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5278 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);5344 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
5279 case IrInstructionIdUnionInit:5345 case IrInstructionIdUnionInit:
5280 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);5346 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
5281 case IrInstructionIdPtrCast:5347 case IrInstructionIdPtrCastGen:
5282 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);5348 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
5283 case IrInstructionIdBitCast:5349 case IrInstructionIdBitCast:
5284 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);5350 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
5285 case IrInstructionIdWidenOrShorten:5351 case IrInstructionIdWidenOrShorten:
...@@ -5377,6 +5443,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {...@@ -5377,6 +5443,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
5377static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);5443static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
5378static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);5444static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
5379static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);5445static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
5446static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
5447static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
5448static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val);
53805449
5381static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {5450static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
5382 switch (parent->id) {5451 switch (parent->id) {
...@@ -5387,6 +5456,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent...@@ -5387,6 +5456,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
5387 case ConstParentIdStruct:5456 case ConstParentIdStruct:
5388 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,5457 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
5389 parent->data.p_struct.field_index);5458 parent->data.p_struct.field_index);
5459 case ConstParentIdErrUnionCode:
5460 return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val);
5461 case ConstParentIdErrUnionPayload:
5462 return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val);
5463 case ConstParentIdOptionalPayload:
5464 return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val);
5390 case ConstParentIdArray:5465 case ConstParentIdArray:
5391 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,5466 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
5392 parent->data.p_array.elem_index);5467 parent->data.p_array.elem_index);
...@@ -5402,7 +5477,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent...@@ -5402,7 +5477,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
54025477
5403static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {5478static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
5404 expand_undef_array(g, array_const_val);5479 expand_undef_array(g, array_const_val);
5405 ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent;5480 ConstParent *parent = &array_const_val->parent;
5406 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);5481 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
54075482
5408 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));5483 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
...@@ -5427,7 +5502,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar...@@ -5427,7 +5502,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
5427}5502}
54285503
5429static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {5504static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
5430 ConstParent *parent = &struct_const_val->data.x_struct.parent;5505 ConstParent *parent = &struct_const_val->parent;
5431 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);5506 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
54325507
5433 ZigType *u32 = g->builtin_types.entry_u32;5508 ZigType *u32 = g->builtin_types.entry_u32;
...@@ -5438,8 +5513,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s...@@ -5438,8 +5513,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
5438 return LLVMConstInBoundsGEP(base_ptr, indices, 2);5513 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5439}5514}
54405515
5516static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
5517 ConstParent *parent = &err_union_const_val->parent;
5518 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
5519
5520 ZigType *u32 = g->builtin_types.entry_u32;
5521 LLVMValueRef indices[] = {
5522 LLVMConstNull(u32->type_ref),
5523 LLVMConstInt(u32->type_ref, err_union_err_index, false),
5524 };
5525 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5526}
5527
5528static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
5529 ConstParent *parent = &err_union_const_val->parent;
5530 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
5531
5532 ZigType *u32 = g->builtin_types.entry_u32;
5533 LLVMValueRef indices[] = {
5534 LLVMConstNull(u32->type_ref),
5535 LLVMConstInt(u32->type_ref, err_union_payload_index, false),
5536 };
5537 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5538}
5539
5540static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) {
5541 ConstParent *parent = &optional_const_val->parent;
5542 LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent);
5543
5544 ZigType *u32 = g->builtin_types.entry_u32;
5545 LLVMValueRef indices[] = {
5546 LLVMConstNull(u32->type_ref),
5547 LLVMConstInt(u32->type_ref, maybe_child_index, false),
5548 };
5549 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5550}
5551
5441static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {5552static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {
5442 ConstParent *parent = &union_const_val->data.x_union.parent;5553 ConstParent *parent = &union_const_val->parent;
5443 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);5554 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
54445555
5445 ZigType *u32 = g->builtin_types.entry_u32;5556 ZigType *u32 = g->builtin_types.entry_u32;
...@@ -5609,6 +5720,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con...@@ -5609,6 +5720,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
5609 render_const_val_global(g, const_val, "");5720 render_const_val_global(g, const_val, "");
5610 return ptr_val;5721 return ptr_val;
5611 }5722 }
5723 case ConstPtrSpecialBaseErrorUnionCode:
5724 {
5725 render_const_val_global(g, const_val, name);
5726 ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val;
5727 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
5728 if (err_union_const_val->type->zero_bits) {
5729 // make this a null pointer
5730 ZigType *usize = g->builtin_types.entry_usize;
5731 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5732 const_val->type->type_ref);
5733 render_const_val_global(g, const_val, "");
5734 return const_val->global_refs->llvm_value;
5735 }
5736 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val);
5737 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5738 const_val->global_refs->llvm_value = ptr_val;
5739 render_const_val_global(g, const_val, "");
5740 return ptr_val;
5741 }
5742 case ConstPtrSpecialBaseErrorUnionPayload:
5743 {
5744 render_const_val_global(g, const_val, name);
5745 ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val;
5746 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
5747 if (err_union_const_val->type->zero_bits) {
5748 // make this a null pointer
5749 ZigType *usize = g->builtin_types.entry_usize;
5750 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5751 const_val->type->type_ref);
5752 render_const_val_global(g, const_val, "");
5753 return const_val->global_refs->llvm_value;
5754 }
5755 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val);
5756 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5757 const_val->global_refs->llvm_value = ptr_val;
5758 render_const_val_global(g, const_val, "");
5759 return ptr_val;
5760 }
5761 case ConstPtrSpecialBaseOptionalPayload:
5762 {
5763 render_const_val_global(g, const_val, name);
5764 ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val;
5765 assert(optional_const_val->type->id == ZigTypeIdOptional);
5766 if (optional_const_val->type->zero_bits) {
5767 // make this a null pointer
5768 ZigType *usize = g->builtin_types.entry_usize;
5769 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5770 const_val->type->type_ref);
5771 render_const_val_global(g, const_val, "");
5772 return const_val->global_refs->llvm_value;
5773 }
5774 LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val);
5775 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5776 const_val->global_refs->llvm_value = ptr_val;
5777 render_const_val_global(g, const_val, "");
5778 return ptr_val;
5779 }
5612 case ConstPtrSpecialHardCodedAddr:5780 case ConstPtrSpecialHardCodedAddr:
5613 {5781 {
5614 render_const_val_global(g, const_val, name);5782 render_const_val_global(g, const_val, name);
...@@ -5621,10 +5789,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con...@@ -5621,10 +5789,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
5621 }5789 }
5622 case ConstPtrSpecialFunction:5790 case ConstPtrSpecialFunction:
5623 return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);5791 return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
5792 case ConstPtrSpecialNull:
5793 return LLVMConstNull(const_val->type->type_ref);
5624 }5794 }
5625 zig_unreachable();5795 zig_unreachable();
5626}5796}
56275797
5798static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) {
5799 uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value;
5800 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false);
5801}
5802
5628static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {5803static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
5629 Error err;5804 Error err;
56305805
...@@ -5644,9 +5819,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5644,9 +5819,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5644 case ZigTypeIdInt:5819 case ZigTypeIdInt:
5645 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);5820 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
5646 case ZigTypeIdErrorSet:5821 case ZigTypeIdErrorSet:
5647 assert(const_val->data.x_err_set != nullptr);5822 return gen_const_val_err_set(g, const_val, name);
5648 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
5649 const_val->data.x_err_set->value, false);
5650 case ZigTypeIdFloat:5823 case ZigTypeIdFloat:
5651 switch (type_entry->data.floating.bit_count) {5824 switch (type_entry->data.floating.bit_count) {
5652 case 16:5825 case 16:
...@@ -5680,6 +5853,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5680,6 +5853,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5680 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);5853 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
5681 } else if (type_is_codegen_pointer(child_type)) {5854 } else if (type_is_codegen_pointer(child_type)) {
5682 return gen_const_val_ptr(g, const_val, name);5855 return gen_const_val_ptr(g, const_val, name);
5856 } else if (child_type->id == ZigTypeIdErrorSet) {
5857 return gen_const_val_err_set(g, const_val, name);
5683 } else {5858 } else {
5684 LLVMValueRef child_val;5859 LLVMValueRef child_val;
5685 LLVMValueRef maybe_val;5860 LLVMValueRef maybe_val;
...@@ -5914,7 +6089,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5914,7 +6089,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5914 ZigType *err_set_type = type_entry->data.error_union.err_set_type;6089 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
5915 if (!type_has_bits(payload_type)) {6090 if (!type_has_bits(payload_type)) {
5916 assert(type_has_bits(err_set_type));6091 assert(type_has_bits(err_set_type));
5917 uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;6092 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6093 uint64_t value = (err_set == nullptr) ? 0 : err_set->value;
5918 return LLVMConstInt(g->err_tag_type->type_ref, value, false);6094 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
5919 } else if (!type_has_bits(err_set_type)) {6095 } else if (!type_has_bits(err_set_type)) {
5920 assert(type_has_bits(payload_type));6096 assert(type_has_bits(payload_type));
...@@ -5923,8 +6099,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5923,8 +6099,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5923 LLVMValueRef err_tag_value;6099 LLVMValueRef err_tag_value;
5924 LLVMValueRef err_payload_value;6100 LLVMValueRef err_payload_value;
5925 bool make_unnamed_struct;6101 bool make_unnamed_struct;
5926 if (const_val->data.x_err_union.err) {6102 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
5927 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);6103 if (err_set != nullptr) {
6104 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false);
5928 err_payload_value = LLVMConstNull(payload_type->type_ref);6105 err_payload_value = LLVMConstNull(payload_type->type_ref);
5929 make_unnamed_struct = false;6106 make_unnamed_struct = false;
5930 } else {6107 } else {
...@@ -6130,10 +6307,13 @@ static void do_code_gen(CodeGen *g) {...@@ -6130,10 +6307,13 @@ static void do_code_gen(CodeGen *g) {
6130 TldVar *tld_var = g->global_vars.at(i);6307 TldVar *tld_var = g->global_vars.at(i);
6131 ZigVar *var = tld_var->var;6308 ZigVar *var = tld_var->var;
61326309
6133 if (var->value->type->id == ZigTypeIdComptimeFloat) {6310 if (var->var_type->id == ZigTypeIdComptimeFloat) {
6134 // Generate debug info for it but that's it.6311 // Generate debug info for it but that's it.
6135 ConstExprValue *const_val = var->value;6312 ConstExprValue *const_val = var->const_value;
6136 assert(const_val->special != ConstValSpecialRuntime);6313 assert(const_val->special != ConstValSpecialRuntime);
6314 if (const_val->type != var->var_type) {
6315 zig_panic("TODO debug info for var with ptr casted value");
6316 }
6137 ZigType *var_type = g->builtin_types.entry_f128;6317 ZigType *var_type = g->builtin_types.entry_f128;
6138 ConstExprValue coerced_value;6318 ConstExprValue coerced_value;
6139 coerced_value.special = ConstValSpecialStatic;6319 coerced_value.special = ConstValSpecialStatic;
...@@ -6144,10 +6324,13 @@ static void do_code_gen(CodeGen *g) {...@@ -6144,10 +6324,13 @@ static void do_code_gen(CodeGen *g) {
6144 continue;6324 continue;
6145 }6325 }
61466326
6147 if (var->value->type->id == ZigTypeIdComptimeInt) {6327 if (var->var_type->id == ZigTypeIdComptimeInt) {
6148 // Generate debug info for it but that's it.6328 // Generate debug info for it but that's it.
6149 ConstExprValue *const_val = var->value;6329 ConstExprValue *const_val = var->const_value;
6150 assert(const_val->special != ConstValSpecialRuntime);6330 assert(const_val->special != ConstValSpecialRuntime);
6331 if (const_val->type != var->var_type) {
6332 zig_panic("TODO debug info for var with ptr casted value");
6333 }
6151 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);6334 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
6152 if (bits_needed < 8) {6335 if (bits_needed < 8) {
6153 bits_needed = 8;6336 bits_needed = 8;
...@@ -6158,7 +6341,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6158,7 +6341,7 @@ static void do_code_gen(CodeGen *g) {
6158 continue;6341 continue;
6159 }6342 }
61606343
6161 if (!type_has_bits(var->value->type))6344 if (!type_has_bits(var->var_type))
6162 continue;6345 continue;
61636346
6164 assert(var->decl_node);6347 assert(var->decl_node);
...@@ -6167,9 +6350,9 @@ static void do_code_gen(CodeGen *g) {...@@ -6167,9 +6350,9 @@ static void do_code_gen(CodeGen *g) {
6167 if (var->linkage == VarLinkageExternal) {6350 if (var->linkage == VarLinkageExternal) {
6168 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));6351 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
6169 if (existing_llvm_var) {6352 if (existing_llvm_var) {
6170 global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0));6353 global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0));
6171 } else {6354 } else {
6172 global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name));6355 global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
6173 // TODO debug info for the extern variable6356 // TODO debug info for the extern variable
61746357
6175 LLVMSetLinkage(global_value, LLVMExternalLinkage);6358 LLVMSetLinkage(global_value, LLVMExternalLinkage);
...@@ -6180,9 +6363,9 @@ static void do_code_gen(CodeGen *g) {...@@ -6180,9 +6363,9 @@ static void do_code_gen(CodeGen *g) {
6180 } else {6363 } else {
6181 bool exported = (var->linkage == VarLinkageExport);6364 bool exported = (var->linkage == VarLinkageExport);
6182 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));6365 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
6183 render_const_val(g, var->value, mangled_name);6366 render_const_val(g, var->const_value, mangled_name);
6184 render_const_val_global(g, var->value, mangled_name);6367 render_const_val_global(g, var->const_value, mangled_name);
6185 global_value = var->value->global_refs->llvm_global;6368 global_value = var->const_value->global_refs->llvm_global;
61866369
6187 if (exported) {6370 if (exported) {
6188 LLVMSetLinkage(global_value, LLVMExternalLinkage);6371 LLVMSetLinkage(global_value, LLVMExternalLinkage);
...@@ -6194,8 +6377,10 @@ static void do_code_gen(CodeGen *g) {...@@ -6194,8 +6377,10 @@ static void do_code_gen(CodeGen *g) {
6194 LLVMSetAlignment(global_value, var->align_bytes);6377 LLVMSetAlignment(global_value, var->align_bytes);
61956378
6196 // TODO debug info for function pointers6379 // TODO debug info for function pointers
6197 if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) {6380 // Here we use const_value->type because that's the type of the llvm global,
6198 gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);6381 // which we const ptr cast upon use to whatever it needs to be.
6382 if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) {
6383 gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type);
6199 }6384 }
62006385
6201 LLVMSetGlobalConstant(global_value, var->gen_is_const);6386 LLVMSetGlobalConstant(global_value, var->gen_is_const);
...@@ -6281,8 +6466,8 @@ static void do_code_gen(CodeGen *g) {...@@ -6281,8 +6466,8 @@ static void do_code_gen(CodeGen *g) {
6281 } else if (instruction->id == IrInstructionIdErrWrapCode) {6466 } else if (instruction->id == IrInstructionIdErrWrapCode) {
6282 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;6467 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
6283 slot = &err_wrap_code_instruction->tmp_ptr;6468 slot = &err_wrap_code_instruction->tmp_ptr;
6284 } else if (instruction->id == IrInstructionIdCmpxchg) {6469 } else if (instruction->id == IrInstructionIdCmpxchgGen) {
6285 IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction;6470 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
6286 slot = &cmpxchg_instruction->tmp_ptr;6471 slot = &cmpxchg_instruction->tmp_ptr;
6287 } else {6472 } else {
6288 zig_unreachable();6473 zig_unreachable();
...@@ -6304,12 +6489,12 @@ static void do_code_gen(CodeGen *g) {...@@ -6304,12 +6489,12 @@ static void do_code_gen(CodeGen *g) {
6304 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {6489 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
6305 ZigVar *var = fn_table_entry->variable_list.at(var_i);6490 ZigVar *var = fn_table_entry->variable_list.at(var_i);
63066491
6307 if (!type_has_bits(var->value->type)) {6492 if (!type_has_bits(var->var_type)) {
6308 continue;6493 continue;
6309 }6494 }
6310 if (ir_get_var_is_comptime(var))6495 if (ir_get_var_is_comptime(var))
6311 continue;6496 continue;
6312 switch (type_requires_comptime(g, var->value->type)) {6497 switch (type_requires_comptime(g, var->var_type)) {
6313 case ReqCompTimeInvalid:6498 case ReqCompTimeInvalid:
6314 zig_unreachable();6499 zig_unreachable();
6315 case ReqCompTimeYes:6500 case ReqCompTimeYes:
...@@ -6319,11 +6504,11 @@ static void do_code_gen(CodeGen *g) {...@@ -6319,11 +6504,11 @@ static void do_code_gen(CodeGen *g) {
6319 }6504 }
63206505
6321 if (var->src_arg_index == SIZE_MAX) {6506 if (var->src_arg_index == SIZE_MAX) {
6322 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);6507 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
63236508
6324 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),6509 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
6325 buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),6510 buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),
6326 var->value->type->di_type, !g->strip_debug_symbols, 0);6511 var->var_type->di_type, !g->strip_debug_symbols, 0);
63276512
6328 } else if (is_c_abi) {6513 } else if (is_c_abi) {
6329 fn_walk_var.data.vars.var = var;6514 fn_walk_var.data.vars.var = var;
...@@ -6333,16 +6518,16 @@ static void do_code_gen(CodeGen *g) {...@@ -6333,16 +6518,16 @@ static void do_code_gen(CodeGen *g) {
6333 ZigType *gen_type;6518 ZigType *gen_type;
6334 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];6519 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
63356520
6336 if (handle_is_ptr(var->value->type)) {6521 if (handle_is_ptr(var->var_type)) {
6337 if (gen_info->is_byval) {6522 if (gen_info->is_byval) {
6338 gen_type = var->value->type;6523 gen_type = var->var_type;
6339 } else {6524 } else {
6340 gen_type = gen_info->type;6525 gen_type = gen_info->type;
6341 }6526 }
6342 var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);6527 var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);
6343 } else {6528 } else {
6344 gen_type = var->value->type;6529 gen_type = var->var_type;
6345 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);6530 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
6346 }6531 }
6347 if (var->decl_node) {6532 if (var->decl_node) {
6348 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),6533 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
...@@ -7458,9 +7643,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -7458,9 +7643,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
7458 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];7643 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
7459 this_val->special = ConstValSpecialStatic;7644 this_val->special = ConstValSpecialStatic;
7460 this_val->type = struct_type;7645 this_val->type = struct_type;
7461 this_val->data.x_struct.parent.id = ConstParentIdArray;7646 this_val->parent.id = ConstParentIdArray;
7462 this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;7647 this_val->parent.data.p_array.array_val = test_fn_array;
7463 this_val->data.x_struct.parent.data.p_array.elem_index = i;7648 this_val->parent.data.p_array.elem_index = i;
7464 this_val->data.x_struct.fields = create_const_vals(2);7649 this_val->data.x_struct.fields = create_const_vals(2);
74657650
7466 ConstExprValue *name_field = &this_val->data.x_struct.fields[0];7651 ConstExprValue *name_field = &this_val->data.x_struct.fields[0];
src/ir.cpp+827-644
...@@ -167,6 +167,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -167,6 +167,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
167 ZigType *dest_type, IrInstruction *dest_type_src);167 ZigType *dest_type, IrInstruction *dest_type_src);
168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
170171
171static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {172static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
172 assert(get_src_ptr_type(const_val->type) != nullptr);173 assert(get_src_ptr_type(const_val->type) != nullptr);
...@@ -178,15 +179,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -178,15 +179,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
178 case ConstPtrSpecialRef:179 case ConstPtrSpecialRef:
179 result = const_val->data.x_ptr.data.ref.pointee;180 result = const_val->data.x_ptr.data.ref.pointee;
180 break;181 break;
181 case ConstPtrSpecialBaseArray:182 case ConstPtrSpecialBaseArray: {
182 expand_undef_array(g, const_val->data.x_ptr.data.base_array.array_val);183 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
183 result = &const_val->data.x_ptr.data.base_array.array_val->data.x_array.data.s_none.elements[184 expand_undef_array(g, array_val);
184 const_val->data.x_ptr.data.base_array.elem_index];185 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
185 break;186 break;
187 }
186 case ConstPtrSpecialBaseStruct:188 case ConstPtrSpecialBaseStruct:
187 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[189 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
188 const_val->data.x_ptr.data.base_struct.field_index];190 const_val->data.x_ptr.data.base_struct.field_index];
189 break;191 break;
192 case ConstPtrSpecialBaseErrorUnionCode:
193 result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;
194 break;
195 case ConstPtrSpecialBaseErrorUnionPayload:
196 result = const_val->data.x_ptr.data.base_err_union_payload.err_union_val->data.x_err_union.payload;
197 break;
198 case ConstPtrSpecialBaseOptionalPayload:
199 result = const_val->data.x_ptr.data.base_optional_payload.optional_val->data.x_optional;
200 break;
201 case ConstPtrSpecialNull:
202 result = const_val;
203 break;
190 case ConstPtrSpecialHardCodedAddr:204 case ConstPtrSpecialHardCodedAddr:
191 zig_unreachable();205 zig_unreachable();
192 case ConstPtrSpecialDiscard:206 case ConstPtrSpecialDiscard:
...@@ -198,6 +212,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -198,6 +212,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
198 return result;212 return result;
199}213}
200214
215static bool is_opt_err_set(ZigType *ty) {
216 return ty->id == ZigTypeIdErrorSet ||
217 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
218}
219
201static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {220static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
202 if (a == b)221 if (a == b)
203 return true;222 return true;
...@@ -208,15 +227,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {...@@ -208,15 +227,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
208 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)227 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
209 return true;228 return true;
210229
211 return false;230 if (is_opt_err_set(a) && is_opt_err_set(b))
212}231 return true;
213232
214ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {233 return false;
215 ConstExprValue *result = const_ptr_pointee_unchecked(g, const_val);
216 if (const_val->type->id == ZigTypeIdPointer) {
217 assert(types_have_same_zig_comptime_repr(const_val->type->data.pointer.child_type, result->type));
218 }
219 return result;
220}234}
221235
222static bool ir_should_inline(IrExecutable *exec, Scope *scope) {236static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
...@@ -305,6 +319,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {...@@ -305,6 +319,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
305 return new_bb;319 return new_bb;
306}320}
307321
322static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarSrc *) {
323 return IrInstructionIdDeclVarSrc;
324}
325
326static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarGen *) {
327 return IrInstructionIdDeclVarGen;
328}
329
308static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {330static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
309 return IrInstructionIdCondBr;331 return IrInstructionIdCondBr;
310}332}
...@@ -337,10 +359,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {...@@ -337,10 +359,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
337 return IrInstructionIdBinOp;359 return IrInstructionIdBinOp;
338}360}
339361
340static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) {
341 return IrInstructionIdDeclVar;
342}
343
344static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {362static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {
345 return IrInstructionIdExport;363 return IrInstructionIdExport;
346}364}
...@@ -449,8 +467,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {...@@ -449,8 +467,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {
449 return IrInstructionIdTestNonNull;467 return IrInstructionIdTestNonNull;
450}468}
451469
452static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) {470static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) {
453 return IrInstructionIdUnwrapOptional;471 return IrInstructionIdOptionalUnwrapPtr;
454}472}
455473
456static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {474static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {
...@@ -517,8 +535,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {...@@ -517,8 +535,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
517 return IrInstructionIdEmbedFile;535 return IrInstructionIdEmbedFile;
518}536}
519537
520static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) {538static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) {
521 return IrInstructionIdCmpxchg;539 return IrInstructionIdCmpxchgSrc;
540}
541
542static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) {
543 return IrInstructionIdCmpxchgGen;
522}544}
523545
524static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {546static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {
...@@ -649,8 +671,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)...@@ -649,8 +671,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
649 return IrInstructionIdTestComptime;671 return IrInstructionIdTestComptime;
650}672}
651673
652static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {674static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) {
653 return IrInstructionIdPtrCast;675 return IrInstructionIdPtrCastSrc;
676}
677
678static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
679 return IrInstructionIdPtrCastGen;
654}680}
655681
656static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {682static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
...@@ -915,7 +941,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so...@@ -915,7 +941,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
915 ir_ref_instruction(condition, irb->current_basic_block);941 ir_ref_instruction(condition, irb->current_basic_block);
916 ir_ref_bb(then_block);942 ir_ref_bb(then_block);
917 ir_ref_bb(else_block);943 ir_ref_bb(else_block);
918 if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block);944 if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block);
919945
920 return &cond_br_instruction->base;946 return &cond_br_instruction->base;
921}947}
...@@ -931,16 +957,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -931,16 +957,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
931 return &return_instruction->base;957 return &return_instruction->base;
932}958}
933959
934static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node,
935 ZigType *type_entry)
936{
937 assert(type_entry);
938 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node);
939 const_instruction->base.value.type = type_entry;
940 const_instruction->base.value.special = ConstValSpecialStatic;
941 return &const_instruction->base;
942}
943
944static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {960static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
945 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);961 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
946 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;962 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
...@@ -1188,14 +1204,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -1188,14 +1204,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
1188 call_instruction->async_allocator = async_allocator;1204 call_instruction->async_allocator = async_allocator;
1189 call_instruction->new_stack = new_stack;1205 call_instruction->new_stack = new_stack;
11901206
1191 if (fn_ref)1207 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
1192 ir_ref_instruction(fn_ref, irb->current_basic_block);
1193 for (size_t i = 0; i < arg_count; i += 1)1208 for (size_t i = 0; i < arg_count; i += 1)
1194 ir_ref_instruction(args[i], irb->current_basic_block);1209 ir_ref_instruction(args[i], irb->current_basic_block);
1195 if (async_allocator)1210 if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block);
1196 ir_ref_instruction(async_allocator, irb->current_basic_block);1211 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
1197 if (new_stack != nullptr)
1198 ir_ref_instruction(new_stack, irb->current_basic_block);
11991212
1200 return &call_instruction->base;1213 return &call_instruction->base;
1201}1214}
...@@ -1280,7 +1293,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,...@@ -1280,7 +1293,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
1280 container_init_list_instruction->item_count = item_count;1293 container_init_list_instruction->item_count = item_count;
1281 container_init_list_instruction->items = items;1294 container_init_list_instruction->items = items;
12821295
1283 ir_ref_instruction(container_type, irb->current_basic_block);1296 if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);
1284 for (size_t i = 0; i < item_count; i += 1) {1297 for (size_t i = 0; i < item_count; i += 1) {
1285 ir_ref_instruction(items[i], irb->current_basic_block);1298 ir_ref_instruction(items[i], irb->current_basic_block);
1286 }1299 }
...@@ -1355,10 +1368,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *...@@ -1355,10 +1368,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
1355 return &instruction->base;1368 return &instruction->base;
1356}1369}
13571370
1358static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,1371static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1359 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)1372 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
1360{1373{
1361 IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, scope, source_node);1374 IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarSrc>(irb, scope, source_node);
1362 decl_var_instruction->base.value.special = ConstValSpecialStatic;1375 decl_var_instruction->base.value.special = ConstValSpecialStatic;
1363 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;1376 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
1364 decl_var_instruction->var = var;1377 decl_var_instruction->var = var;
...@@ -1366,13 +1379,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1366,13 +1379,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s
1366 decl_var_instruction->align_value = align_value;1379 decl_var_instruction->align_value = align_value;
1367 decl_var_instruction->init_value = init_value;1380 decl_var_instruction->init_value = init_value;
13681381
1369 if (var_type) ir_ref_instruction(var_type, irb->current_basic_block);1382 if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
1370 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);1383 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
1371 ir_ref_instruction(init_value, irb->current_basic_block);1384 ir_ref_instruction(init_value, irb->current_basic_block);
13721385
1373 return &decl_var_instruction->base;1386 return &decl_var_instruction->base;
1374}1387}
13751388
1389static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1390 ZigVar *var, IrInstruction *init_value)
1391{
1392 IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarGen>(&ira->new_irb,
1393 source_instruction->scope, source_instruction->source_node);
1394 decl_var_instruction->base.value.special = ConstValSpecialStatic;
1395 decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void;
1396 decl_var_instruction->var = var;
1397 decl_var_instruction->init_value = init_value;
1398
1399 ir_ref_instruction(init_value, ira->new_irb.current_basic_block);
1400
1401 return &decl_var_instruction->base;
1402}
1403
1376static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,1404static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
1377 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)1405 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
1378{1406{
...@@ -1542,14 +1570,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod...@@ -1542,14 +1570,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
1542 return &instruction->base;1570 return &instruction->base;
1543}1571}
15441572
1545static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,1573static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1546 bool safety_check_on)1574 IrInstruction *base_ptr, bool safety_check_on)
1547{1575{
1548 IrInstructionUnwrapOptional *instruction = ir_build_instruction<IrInstructionUnwrapOptional>(irb, scope, source_node);1576 IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node);
1549 instruction->value = value;1577 instruction->base_ptr = base_ptr;
1550 instruction->safety_check_on = safety_check_on;1578 instruction->safety_check_on = safety_check_on;
15511579
1552 ir_ref_instruction(value, irb->current_basic_block);1580 ir_ref_instruction(base_ptr, irb->current_basic_block);
15531581
1554 return &instruction->base;1582 return &instruction->base;
1555}1583}
...@@ -1765,13 +1793,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode...@@ -1765,13 +1793,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
1765 return &instruction->base;1793 return &instruction->base;
1766}1794}
17671795
1768static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value,1796static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1769 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,1797 IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1770 IrInstruction *success_order_value, IrInstruction *failure_order_value,1798 IrInstruction *success_order_value, IrInstruction *failure_order_value,
1771 bool is_weak,1799 bool is_weak)
1772 ZigType *type, AtomicOrder success_order, AtomicOrder failure_order)
1773{1800{
1774 IrInstructionCmpxchg *instruction = ir_build_instruction<IrInstructionCmpxchg>(irb, scope, source_node);1801 IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);
1775 instruction->type_value = type_value;1802 instruction->type_value = type_value;
1776 instruction->ptr = ptr;1803 instruction->ptr = ptr;
1777 instruction->cmp_value = cmp_value;1804 instruction->cmp_value = cmp_value;
...@@ -1779,16 +1806,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so...@@ -1779,16 +1806,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so
1779 instruction->success_order_value = success_order_value;1806 instruction->success_order_value = success_order_value;
1780 instruction->failure_order_value = failure_order_value;1807 instruction->failure_order_value = failure_order_value;
1781 instruction->is_weak = is_weak;1808 instruction->is_weak = is_weak;
1782 instruction->type = type;
1783 instruction->success_order = success_order;
1784 instruction->failure_order = failure_order;
17851809
1786 if (type_value != nullptr) ir_ref_instruction(type_value, irb->current_basic_block);1810 ir_ref_instruction(type_value, irb->current_basic_block);
1787 ir_ref_instruction(ptr, irb->current_basic_block);1811 ir_ref_instruction(ptr, irb->current_basic_block);
1788 ir_ref_instruction(cmp_value, irb->current_basic_block);1812 ir_ref_instruction(cmp_value, irb->current_basic_block);
1789 ir_ref_instruction(new_value, irb->current_basic_block);1813 ir_ref_instruction(new_value, irb->current_basic_block);
1790 if (type_value != nullptr) ir_ref_instruction(success_order_value, irb->current_basic_block);1814 ir_ref_instruction(success_order_value, irb->current_basic_block);
1791 if (type_value != nullptr) ir_ref_instruction(failure_order_value, irb->current_basic_block);1815 ir_ref_instruction(failure_order_value, irb->current_basic_block);
1816
1817 return &instruction->base;
1818}
1819
1820static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1821 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1822 AtomicOrder success_order, AtomicOrder failure_order, bool is_weak)
1823{
1824 IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb,
1825 source_instruction->scope, source_instruction->source_node);
1826 instruction->ptr = ptr;
1827 instruction->cmp_value = cmp_value;
1828 instruction->new_value = new_value;
1829 instruction->success_order = success_order;
1830 instruction->failure_order = failure_order;
1831 instruction->is_weak = is_weak;
1832
1833 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
1834 ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);
1835 ir_ref_instruction(new_value, ira->new_irb.current_basic_block);
17921836
1793 return &instruction->base;1837 return &instruction->base;
1794}1838}
...@@ -2060,12 +2104,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s...@@ -2060,12 +2104,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s
2060}2104}
20612105
2062static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,2106static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
2063 IrInstruction *value)2107 IrInstruction *err_union)
2064{2108{
2065 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);2109 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);
2066 instruction->value = value;2110 instruction->err_union = err_union;
20672111
2068 ir_ref_instruction(value, irb->current_basic_block);2112 ir_ref_instruction(err_union, irb->current_basic_block);
20692113
2070 return &instruction->base;2114 return &instruction->base;
2071}2115}
...@@ -2115,20 +2159,33 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo...@@ -2115,20 +2159,33 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
2115 return &instruction->base;2159 return &instruction->base;
2116}2160}
21172161
2118static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,2162static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2119 IrInstruction *dest_type, IrInstruction *ptr)2163 IrInstruction *dest_type, IrInstruction *ptr)
2120{2164{
2121 IrInstructionPtrCast *instruction = ir_build_instruction<IrInstructionPtrCast>(2165 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
2122 irb, scope, source_node);2166 irb, scope, source_node);
2123 instruction->dest_type = dest_type;2167 instruction->dest_type = dest_type;
2124 instruction->ptr = ptr;2168 instruction->ptr = ptr;
21252169
2126 if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);2170 ir_ref_instruction(dest_type, irb->current_basic_block);
2127 ir_ref_instruction(ptr, irb->current_basic_block);2171 ir_ref_instruction(ptr, irb->current_basic_block);
21282172
2129 return &instruction->base;2173 return &instruction->base;
2130}2174}
21312175
2176static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
2177 ZigType *ptr_type, IrInstruction *ptr)
2178{
2179 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(
2180 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2181 instruction->base.value.type = ptr_type;
2182 instruction->ptr = ptr;
2183
2184 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
2185
2186 return &instruction->base;
2187}
2188
2132static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,2189static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
2133 IrInstruction *dest_type, IrInstruction *value)2190 IrInstruction *dest_type, IrInstruction *value)
2134{2191{
...@@ -2807,10 +2864,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o...@@ -2807,10 +2864,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
2807 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;2864 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
2808 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);2865 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
2809 if (defer_expr_value != irb->codegen->invalid_instruction) {2866 if (defer_expr_value != irb->codegen->invalid_instruction) {
2810 if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == ZigTypeIdUnreachable) {2867 if (defer_expr_value->value.type != nullptr &&
2868 defer_expr_value->value.type->id == ZigTypeIdUnreachable)
2869 {
2811 is_noreturn = true;2870 is_noreturn = true;
2812 } else {2871 } else {
2813 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));2872 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
2873 defer_expr_value));
2814 }2874 }
2815 }2875 }
2816 }2876 }
...@@ -3065,7 +3125,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s...@@ -3065,7 +3125,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
3065 variable_entry->mem_slot_index = SIZE_MAX;3125 variable_entry->mem_slot_index = SIZE_MAX;
3066 variable_entry->is_comptime = is_comptime;3126 variable_entry->is_comptime = is_comptime;
3067 variable_entry->src_arg_index = SIZE_MAX;3127 variable_entry->src_arg_index = SIZE_MAX;
3068 variable_entry->value = create_const_vals(1);3128 variable_entry->const_value = create_const_vals(1);
30693129
3070 if (is_comptime != nullptr) {3130 if (is_comptime != nullptr) {
3071 is_comptime->ref_count += 1;3131 is_comptime->ref_count += 1;
...@@ -3080,20 +3140,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s...@@ -3080,20 +3140,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
3080 ErrorMsg *msg = add_node_error(codegen, node,3140 ErrorMsg *msg = add_node_error(codegen, node,
3081 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));3141 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3082 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));3142 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3083 variable_entry->value->type = codegen->builtin_types.entry_invalid;3143 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3084 } else {3144 } else {
3085 ZigType *type;3145 ZigType *type;
3086 if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {3146 if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
3087 add_node_error(codegen, node,3147 add_node_error(codegen, node,
3088 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));3148 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
3089 variable_entry->value->type = codegen->builtin_types.entry_invalid;3149 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3090 } else {3150 } else {
3091 Tld *tld = find_decl(codegen, parent_scope, name);3151 Tld *tld = find_decl(codegen, parent_scope, name);
3092 if (tld != nullptr) {3152 if (tld != nullptr) {
3093 ErrorMsg *msg = add_node_error(codegen, node,3153 ErrorMsg *msg = add_node_error(codegen, node,
3094 buf_sprintf("redefinition of '%s'", buf_ptr(name)));3154 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
3095 add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));3155 add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));
3096 variable_entry->value->type = codegen->builtin_types.entry_invalid;3156 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3097 }3157 }
3098 }3158 }
3099 }3159 }
...@@ -3156,7 +3216,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3156,7 +3216,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3156 scope_block->incoming_blocks = &incoming_blocks;3216 scope_block->incoming_blocks = &incoming_blocks;
3157 scope_block->incoming_values = &incoming_values;3217 scope_block->incoming_values = &incoming_values;
3158 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");3218 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
3159 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope));3219 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
3220 ir_should_inline(irb->exec, parent_scope));
3160 }3221 }
31613222
3162 bool is_continuation_unreachable = false;3223 bool is_continuation_unreachable = false;
...@@ -3174,9 +3235,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3174,9 +3235,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3174 // defer starts a new scope3235 // defer starts a new scope
3175 child_scope = statement_node->data.defer.child_scope;3236 child_scope = statement_node->data.defer.child_scope;
3176 assert(child_scope);3237 assert(child_scope);
3177 } else if (statement_value->id == IrInstructionIdDeclVar) {3238 } else if (statement_value->id == IrInstructionIdDeclVarSrc) {
3178 // variable declarations start a new scope3239 // variable declarations start a new scope
3179 IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;3240 IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value;
3180 child_scope = decl_var_instruction->var->child_scope;3241 child_scope = decl_var_instruction->var->child_scope;
3181 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {3242 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {
3182 // this statement's value must be void3243 // this statement's value must be void
...@@ -3331,7 +3392,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3331,7 +3392,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
3331 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);3392 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
3332}3393}
33333394
3334static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {3395static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
3335 assert(node->type == NodeTypeBinOpExpr);3396 assert(node->type == NodeTypeBinOpExpr);
33363397
3337 AstNode *op1_node = node->data.bin_op_expr.op1;3398 AstNode *op1_node = node->data.bin_op_expr.op1;
...@@ -3365,7 +3426,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As...@@ -3365,7 +3426,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
3365 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));3426 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
33663427
3367 ir_set_cursor_at_end_and_append_block(irb, ok_block);3428 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3368 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);3429 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false);
3369 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);3430 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
3370 IrBasicBlock *after_ok_block = irb->current_basic_block;3431 IrBasicBlock *after_ok_block = irb->current_basic_block;
3371 ir_build_br(irb, parent_scope, node, end_block, is_comptime);3432 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
...@@ -3483,7 +3544,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3483,7 +3544,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
3483 case BinOpTypeMergeErrorSets:3544 case BinOpTypeMergeErrorSets:
3484 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);3545 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);
3485 case BinOpTypeUnwrapOptional:3546 case BinOpTypeUnwrapOptional:
3486 return ir_gen_maybe_ok_or(irb, scope, node);3547 return ir_gen_orelse(irb, scope, node);
3487 case BinOpTypeErrorUnion:3548 case BinOpTypeErrorUnion:
3488 return ir_gen_error_union(irb, scope, node);3549 return ir_gen_error_union(irb, scope, node);
3489 }3550 }
...@@ -3542,6 +3603,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3542,6 +3603,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
3542 buf_ptr(variable_name)));3603 buf_ptr(variable_name)));
3543 return irb->codegen->invalid_instruction;3604 return irb->codegen->invalid_instruction;
3544 }3605 }
3606 assert(err == ErrorPrimitiveTypeNotFound);
3545 } else {3607 } else {
3546 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);3608 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);
3547 if (lval == LValPtr) {3609 if (lval == LValPtr) {
...@@ -3904,9 +3966,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -3904,9 +3966,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
3904 if (arg5_value == irb->codegen->invalid_instruction)3966 if (arg5_value == irb->codegen->invalid_instruction)
3905 return arg5_value;3967 return arg5_value;
39063968
3907 IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value,3969 IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
3908 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),3970 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
3909 nullptr, AtomicOrderUnordered, AtomicOrderUnordered);
3910 return ir_lval_wrap(irb, scope, cmpxchg, lval);3971 return ir_lval_wrap(irb, scope, cmpxchg, lval);
3911 }3972 }
3912 case BuiltinFnIdFence:3973 case BuiltinFnIdFence:
...@@ -4346,7 +4407,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4346,7 +4407,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4346 if (arg1_value == irb->codegen->invalid_instruction)4407 if (arg1_value == irb->codegen->invalid_instruction)
4347 return arg1_value;4408 return arg1_value;
43484409
4349 IrInstruction *ptr_cast = ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value);4410 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value);
4350 return ir_lval_wrap(irb, scope, ptr_cast, lval);4411 return ir_lval_wrap(irb, scope, ptr_cast, lval);
4351 }4412 }
4352 case BuiltinFnIdBitCast:4413 case BuiltinFnIdBitCast:
...@@ -4784,7 +4845,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -4784,7 +4845,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
4784 }4845 }
4785 }4846 }
47864847
4787 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr);4848 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
4849 is_async, async_allocator, nullptr);
4788 return ir_lval_wrap(irb, scope, fn_call, lval);4850 return ir_lval_wrap(irb, scope, fn_call, lval);
4789}4851}
47904852
...@@ -4793,7 +4855,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4793,7 +4855,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
47934855
4794 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);4856 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
4795 if (condition == irb->codegen->invalid_instruction)4857 if (condition == irb->codegen->invalid_instruction)
4796 return condition;4858 return irb->codegen->invalid_instruction;
47974859
4798 IrInstruction *is_comptime;4860 IrInstruction *is_comptime;
4799 if (ir_should_inline(irb->exec, scope)) {4861 if (ir_should_inline(irb->exec, scope)) {
...@@ -4816,7 +4878,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4816,7 +4878,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4816 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);4878 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
4817 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);4879 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);
4818 if (then_expr_result == irb->codegen->invalid_instruction)4880 if (then_expr_result == irb->codegen->invalid_instruction)
4819 return then_expr_result;4881 return irb->codegen->invalid_instruction;
4820 IrBasicBlock *after_then_block = irb->current_basic_block;4882 IrBasicBlock *after_then_block = irb->current_basic_block;
4821 if (!instr_is_unreachable(then_expr_result))4883 if (!instr_is_unreachable(then_expr_result))
4822 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));4884 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
...@@ -4826,7 +4888,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4826,7 +4888,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4826 if (else_node) {4888 if (else_node) {
4827 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);4889 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
4828 if (else_expr_result == irb->codegen->invalid_instruction)4890 if (else_expr_result == irb->codegen->invalid_instruction)
4829 return else_expr_result;4891 return irb->codegen->invalid_instruction;
4830 } else {4892 } else {
4831 else_expr_result = ir_build_const_void(irb, scope, node);4893 else_expr_result = ir_build_const_void(irb, scope, node);
4832 }4894 }
...@@ -4927,7 +4989,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -4927,7 +4989,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
4927 ptr_len, align_value, bit_offset_start, host_int_bytes);4989 ptr_len, align_value, bit_offset_start, host_int_bytes);
4928}4990}
49294991
4930static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,4992static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
4931 LVal lval)4993 LVal lval)
4932{4994{
4933 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);4995 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
...@@ -5053,11 +5115,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5053,11 +5115,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5053 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);5115 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
5054 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,5116 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
5055 is_const, is_const, is_shadowable, is_comptime);5117 is_const, is_const, is_shadowable, is_comptime);
5056 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node5118 // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node
5057 // is inside var->child_scope5119 // is inside var->child_scope
50585120
5059 if (!is_extern && !variable_declaration->expr) {5121 if (!is_extern && !variable_declaration->expr) {
5060 var->value->type = irb->codegen->builtin_types.entry_invalid;5122 var->var_type = irb->codegen->builtin_types.entry_invalid;
5061 add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));5123 add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));
5062 return irb->codegen->invalid_instruction;5124 return irb->codegen->invalid_instruction;
5063 }5125 }
...@@ -5084,7 +5146,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5084,7 +5146,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5084 if (init_value == irb->codegen->invalid_instruction)5146 if (init_value == irb->codegen->invalid_instruction)
5085 return init_value;5147 return init_value;
50865148
5087 return ir_build_var_decl(irb, scope, node, var, type_instruction, align_value, init_value);5149 return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value);
5088}5150}
50895151
5090static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {5152static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -5140,7 +5202,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5140,7 +5202,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5140 err_val_ptr, false);5202 err_val_ptr, false);
5141 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?5203 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
5142 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);5204 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
5143 ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);5205 ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
5144 }5206 }
51455207
5146 ZigList<IrInstruction *> incoming_values = {0};5208 ZigList<IrInstruction *> incoming_values = {0};
...@@ -5180,7 +5242,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5180,7 +5242,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5180 true, false, false, is_comptime);5242 true, false, false, is_comptime);
5181 Scope *err_scope = err_var->child_scope;5243 Scope *err_scope = err_var->child_scope;
5182 IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);5244 IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
5183 ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);5245 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);
51845246
5185 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);5247 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
5186 if (else_result == irb->codegen->invalid_instruction)5248 if (else_result == irb->codegen->invalid_instruction)
...@@ -5220,10 +5282,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5220,10 +5282,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5220 }5282 }
52215283
5222 ir_set_cursor_at_end_and_append_block(irb, body_block);5284 ir_set_cursor_at_end_and_append_block(irb, body_block);
5223 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false);5285 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
5224 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?5286 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
5225 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);5287 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
5226 ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);5288 ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
52275289
5228 ZigList<IrInstruction *> incoming_values = {0};5290 ZigList<IrInstruction *> incoming_values = {0};
5229 ZigList<IrBasicBlock *> incoming_blocks = {0};5291 ZigList<IrBasicBlock *> incoming_blocks = {0};
...@@ -5380,7 +5442,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5380,7 +5442,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5380 Scope *child_scope = elem_var->child_scope;5442 Scope *child_scope = elem_var->child_scope;
53815443
5382 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);5444 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
5383 ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);5445 ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
5384 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);5446 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
53855447
5386 AstNode *index_var_source_node;5448 AstNode *index_var_source_node;
...@@ -5398,7 +5460,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5398,7 +5460,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5398 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);5460 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
5399 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);5461 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
5400 IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);5462 IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);
5401 ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);5463 ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);
5402 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);5464 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);
54035465
54045466
...@@ -5622,8 +5684,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5622,8 +5684,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
5622 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);5684 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);
5623}5685}
56245686
5625static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) {5687static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5626 assert(node->type == NodeTypeTestExpr);5688 assert(node->type == NodeTypeIfOptional);
56275689
5628 Buf *var_symbol = node->data.test_expr.var_symbol;5690 Buf *var_symbol = node->data.test_expr.var_symbol;
5629 AstNode *expr_node = node->data.test_expr.target_node;5691 AstNode *expr_node = node->data.test_expr.target_node;
...@@ -5661,9 +5723,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no...@@ -5661,9 +5723,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
5661 ZigVar *var = ir_create_var(irb, node, subexpr_scope,5723 ZigVar *var = ir_create_var(irb, node, subexpr_scope,
5662 var_symbol, is_const, is_const, is_shadowable, is_comptime);5724 var_symbol, is_const, is_const, is_shadowable, is_comptime);
56635725
5664 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, subexpr_scope, node, maybe_val_ptr, false);5726 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false);
5665 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);5727 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
5666 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);5728 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5667 var_scope = var->child_scope;5729 var_scope = var->child_scope;
5668 } else {5730 } else {
5669 var_scope = subexpr_scope;5731 var_scope = subexpr_scope;
...@@ -5738,7 +5800,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5738,7 +5800,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
57385800
5739 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);5801 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
5740 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);5802 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
5741 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);5803 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5742 var_scope = var->child_scope;5804 var_scope = var->child_scope;
5743 } else {5805 } else {
5744 var_scope = subexpr_scope;5806 var_scope = subexpr_scope;
...@@ -5763,7 +5825,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5763,7 +5825,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
5763 err_symbol, is_const, is_const, is_shadowable, is_comptime);5825 err_symbol, is_const, is_const, is_shadowable, is_comptime);
57645826
5765 IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);5827 IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
5766 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);5828 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5767 err_var_scope = var->child_scope;5829 err_var_scope = var->child_scope;
5768 } else {5830 } else {
5769 err_var_scope = subexpr_scope;5831 err_var_scope = subexpr_scope;
...@@ -5818,7 +5880,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit...@@ -5818,7 +5880,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
5818 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);5880 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);
5819 }5881 }
5820 IrInstruction *var_type = nullptr; // infer the type5882 IrInstruction *var_type = nullptr; // infer the type
5821 ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);5883 ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
5822 } else {5884 } else {
5823 child_scope = scope;5885 child_scope = scope;
5824 }5886 }
...@@ -6228,7 +6290,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -6228,7 +6290,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
6228 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);6290 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
6229}6291}
62306292
6231static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {6293static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
6232 assert(node->type == NodeTypeUnwrapErrorExpr);6294 assert(node->type == NodeTypeUnwrapErrorExpr);
62336295
6234 AstNode *op1_node = node->data.unwrap_err_expr.op1;6296 AstNode *op1_node = node->data.unwrap_err_expr.op1;
...@@ -6242,7 +6304,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -6242,7 +6304,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
6242 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));6304 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
6243 return irb->codegen->invalid_instruction;6305 return irb->codegen->invalid_instruction;
6244 }6306 }
6245 return ir_gen_err_assert_ok(irb, parent_scope, node, op1_node, LValNone);6307 return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone);
6246 }6308 }
62476309
62486310
...@@ -6276,7 +6338,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -6276,7 +6338,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
6276 is_const, is_const, is_shadowable, is_comptime);6338 is_const, is_const, is_shadowable, is_comptime);
6277 err_scope = var->child_scope;6339 err_scope = var->child_scope;
6278 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);6340 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
6279 ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val);6341 ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
6280 } else {6342 } else {
6281 err_scope = parent_scope;6343 err_scope = parent_scope;
6282 }6344 }
...@@ -6312,7 +6374,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o...@@ -6312,7 +6374,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
6312 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;6374 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;
6313 if (need_comma)6375 if (need_comma)
6314 buf_append_char(name, ',');6376 buf_append_char(name, ',');
6315 render_const_value(codegen, name, var_scope->var->value);6377 // TODO: const ptr reinterpret here to make the var type agree with the value?
6378 render_const_value(codegen, name, var_scope->var->const_value);
6316 return true;6379 return true;
6317}6380}
63186381
...@@ -6562,7 +6625,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6562,7 +6625,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
6562 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b0106625 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
65636626
6564 // TODO relies on Zig not re-ordering fields6627 // TODO relies on Zig not re-ordering fields
6565 IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);6628 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
6566 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6629 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6567 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6630 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6568 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6631 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
...@@ -6640,7 +6703,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6640,7 +6703,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
6640 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));6703 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
66416704
6642 // TODO relies on Zig not re-ordering fields6705 // TODO relies on Zig not re-ordering fields
6643 IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);6706 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
6644 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6707 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6645 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6708 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6646 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6709 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
...@@ -6756,7 +6819,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6756,7 +6819,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
6756 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);6819 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
6757 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);6820 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
6758 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);6821 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
6759 ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);6822 ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
6760 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);6823 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
6761 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);6824 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
6762 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);6825 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
...@@ -7050,7 +7113,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7050,7 +7113,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7050 if (maybe_ptr == irb->codegen->invalid_instruction)7113 if (maybe_ptr == irb->codegen->invalid_instruction)
7051 return irb->codegen->invalid_instruction;7114 return irb->codegen->invalid_instruction;
70527115
7053 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true);7116 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true);
7054 if (lval == LValPtr)7117 if (lval == LValPtr)
7055 return unwrapped_ptr;7118 return unwrapped_ptr;
70567119
...@@ -7074,8 +7137,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7074,8 +7137,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7074 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);7137 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
7075 case NodeTypeIfErrorExpr:7138 case NodeTypeIfErrorExpr:
7076 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);7139 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
7077 case NodeTypeTestExpr:7140 case NodeTypeIfOptional:
7078 return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);7141 return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);
7079 case NodeTypeSwitchExpr:7142 case NodeTypeSwitchExpr:
7080 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);7143 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
7081 case NodeTypeCompTime:7144 case NodeTypeCompTime:
...@@ -7093,7 +7156,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7093,7 +7156,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7093 case NodeTypeSliceExpr:7156 case NodeTypeSliceExpr:
7094 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);7157 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
7095 case NodeTypeUnwrapErrorExpr:7158 case NodeTypeUnwrapErrorExpr:
7096 return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval);7159 return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval);
7097 case NodeTypeContainerDecl:7160 case NodeTypeContainerDecl:
7098 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);7161 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
7099 case NodeTypeFnProto:7162 case NodeTypeFnProto:
...@@ -7152,6 +7215,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7152,6 +7215,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7152 ir_ref_bb(irb->current_basic_block);7215 ir_ref_bb(irb->current_basic_block);
71537216
7154 ZigFn *fn_entry = exec_fn_entry(irb->exec);7217 ZigFn *fn_entry = exec_fn_entry(irb->exec);
7218
7155 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;7219 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
7156 IrInstruction *coro_id;7220 IrInstruction *coro_id;
7157 IrInstruction *u8_ptr_type;7221 IrInstruction *u8_ptr_type;
...@@ -7172,27 +7236,27 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7172,27 +7236,27 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7172 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);7236 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
7173 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);7237 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
7174 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa7238 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
7175 ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);7239 ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
7176 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);7240 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
71777241
7178 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);7242 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7179 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);7243 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
7180 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,7244 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
7181 get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));7245 get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
7182 ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);7246 ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
7183 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);7247 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
71847248
7185 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,7249 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
7186 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));7250 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
7187 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);7251 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);
7188 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);7252 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
7189 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);7253 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7190 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);7254 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
7191 ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);7255 ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
7192 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,7256 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
7193 ImplicitAllocatorIdArg);7257 ImplicitAllocatorIdArg);
7194 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);7258 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
7195 ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);7259 ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
7196 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);7260 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
7197 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);7261 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);
7198 IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);7262 IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);
...@@ -7208,7 +7272,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7208,7 +7272,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7208 ir_build_return(irb, coro_scope, node, undef);7272 ir_build_return(irb, coro_scope, node, undef);
72097273
7210 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);7274 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
7211 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);7275 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);
7212 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);7276 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
72137277
7214 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);7278 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
...@@ -7286,8 +7350,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7286,8 +7350,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7286 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7350 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7287 false, false, PtrLenUnknown, 0, 0, 0));7351 false, false, PtrLenUnknown, 0, 0, 0));
7288 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);7352 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
7289 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);7353 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
7290 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,7354 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7291 irb->exec->coro_result_field_ptr);7355 irb->exec->coro_result_field_ptr);
7292 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,7356 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
7293 fn_entry->type_entry->data.fn.fn_type_id.return_type);7357 fn_entry->type_entry->data.fn.fn_type_id.return_type);
...@@ -7303,7 +7367,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7303,7 +7367,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7303 // Before we destroy the coroutine frame, we need to load the target promise into7367 // Before we destroy the coroutine frame, we need to load the target promise into
7304 // a register or local variable which does not get spilled into the frame,7368 // a register or local variable which does not get spilled into the frame,
7305 // otherwise llvm tries to access memory inside the destroyed frame.7369 // otherwise llvm tries to access memory inside the destroyed frame.
7306 IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,7370 IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node,
7307 irb->exec->await_handle_var_ptr, false);7371 irb->exec->await_handle_var_ptr, false);
7308 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);7372 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
7309 ir_build_br(irb, scope, node, check_free_block, const_bool_false);7373 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
...@@ -7338,7 +7402,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7338,7 +7402,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7338 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7402 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7339 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7403 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7340 false, false, PtrLenUnknown, 0, 0, 0));7404 false, false, PtrLenUnknown, 0, 0, 0));
7341 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);7405 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
7342 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);7406 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
7343 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);7407 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
7344 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);7408 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
...@@ -7435,7 +7499,7 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal...@@ -7435,7 +7499,7 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
7435 return val;7499 return val;
7436}7500}
74377501
7438static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {7502static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
7439 IrBasicBlock *bb = exec->basic_block_list.at(0);7503 IrBasicBlock *bb = exec->basic_block_list.at(0);
7440 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {7504 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
7441 IrInstruction *instruction = bb->instruction_list.at(i);7505 IrInstruction *instruction = bb->instruction_list.at(i);
...@@ -7445,16 +7509,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)...@@ -7445,16 +7509,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)
7445 if (value->value.special == ConstValSpecialRuntime) {7509 if (value->value.special == ConstValSpecialRuntime) {
7446 exec_add_error_node(codegen, exec, value->source_node,7510 exec_add_error_node(codegen, exec, value->source_node,
7447 buf_sprintf("unable to evaluate constant expression"));7511 buf_sprintf("unable to evaluate constant expression"));
7448 return codegen->invalid_instruction;7512 return &codegen->invalid_instruction->value;
7449 }7513 }
7450 return value;7514 return &value->value;
7451 } else if (ir_has_side_effects(instruction)) {7515 } else if (ir_has_side_effects(instruction)) {
7452 exec_add_error_node(codegen, exec, instruction->source_node,7516 exec_add_error_node(codegen, exec, instruction->source_node,
7453 buf_sprintf("unable to evaluate constant expression"));7517 buf_sprintf("unable to evaluate constant expression"));
7454 return codegen->invalid_instruction;7518 return &codegen->invalid_instruction->value;
7455 }7519 }
7456 }7520 }
7457 return codegen->invalid_instruction;7521 return &codegen->invalid_instruction->value;
7458}7522}
74597523
7460static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {7524static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {
...@@ -8768,13 +8832,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8768,13 +8832,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8768 size_t errors_count = 0;8832 size_t errors_count = 0;
8769 ZigType *err_set_type = nullptr;8833 ZigType *err_set_type = nullptr;
8770 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {8834 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
8835 if (!resolve_inferred_error_set(ira->codegen, prev_inst->value.type, prev_inst->source_node)) {
8836 return ira->codegen->builtin_types.entry_invalid;
8837 }
8771 if (type_is_global_error_set(prev_inst->value.type)) {8838 if (type_is_global_error_set(prev_inst->value.type)) {
8772 err_set_type = ira->codegen->builtin_types.entry_global_error_set;8839 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
8773 } else {8840 } else {
8774 err_set_type = prev_inst->value.type;8841 err_set_type = prev_inst->value.type;
8775 if (!resolve_inferred_error_set(ira->codegen, err_set_type, prev_inst->source_node)) {
8776 return ira->codegen->builtin_types.entry_invalid;
8777 }
8778 update_errors_helper(ira->codegen, &errors, &errors_count);8842 update_errors_helper(ira->codegen, &errors, &errors_count);
87798843
8780 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {8844 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
...@@ -8933,6 +8997,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8933,6 +8997,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8933 if (prev_type->id == ZigTypeIdArray) {8997 if (prev_type->id == ZigTypeIdArray) {
8934 convert_to_const_slice = true;8998 convert_to_const_slice = true;
8935 }8999 }
9000 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
9001 return ira->codegen->builtin_types.entry_invalid;
9002 }
8936 if (type_is_global_error_set(cur_type)) {9003 if (type_is_global_error_set(cur_type)) {
8937 err_set_type = ira->codegen->builtin_types.entry_global_error_set;9004 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
8938 continue;9005 continue;
...@@ -8940,9 +9007,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8940,9 +9007,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8940 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {9007 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {
8941 continue;9008 continue;
8942 }9009 }
8943 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
8944 return ira->codegen->builtin_types.entry_invalid;
8945 }
89469010
8947 update_errors_helper(ira->codegen, &errors, &errors_count);9011 update_errors_helper(ira->codegen, &errors, &errors_count);
89489012
...@@ -9432,14 +9496,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -9432,14 +9496,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
9432 }9496 }
9433 return true;9497 return true;
9434}9498}
9499
9500static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
9501 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9502 old_instruction->scope, old_instruction->source_node);
9503 IrInstruction *new_instruction = &const_instruction->base;
9504 new_instruction->value.type = ty;
9505 new_instruction->value.special = ConstValSpecialStatic;
9506 return new_instruction;
9507}
9508
9435static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,9509static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
9436 ZigType *wanted_type, CastOp cast_op, bool need_alloca)9510 ZigType *wanted_type, CastOp cast_op, bool need_alloca)
9437{9511{
9438 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&9512 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
9439 cast_op != CastOpResizeSlice)9513 cast_op != CastOpResizeSlice)
9440 {9514 {
9441 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9515 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9442 source_instr->source_node, wanted_type);
9443 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,9516 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
9444 &result->value, wanted_type))9517 &result->value, wanted_type))
9445 {9518 {
...@@ -9476,9 +9549,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,...@@ -9476,9 +9549,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
9476 if (pointee == nullptr)9549 if (pointee == nullptr)
9477 return ira->codegen->invalid_instruction;9550 return ira->codegen->invalid_instruction;
9478 if (pointee->special != ConstValSpecialRuntime) {9551 if (pointee->special != ConstValSpecialRuntime) {
9479 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9552 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9480 source_instr->source_node, wanted_type);
9481 result->value.type = wanted_type;
9482 result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;9553 result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;
9483 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;9554 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
9484 result->value.data.x_ptr.data.base_array.array_val = pointee;9555 result->value.data.x_ptr.data.base_array.array_val = pointee;
...@@ -9517,8 +9588,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc...@@ -9517,8 +9588,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
9517 assert(is_slice(wanted_type));9588 assert(is_slice(wanted_type));
9518 bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;9589 bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
95199590
9520 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9591 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9521 source_instr->source_node, wanted_type);
9522 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);9592 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
9523 result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =9593 result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =
9524 value->value.data.x_ptr.mut;9594 value->value.data.x_ptr.mut;
...@@ -9653,15 +9723,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)...@@ -9653,15 +9723,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)
9653 return instruction;9723 return instruction;
9654}9724}
96559725
9656static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
9657 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9658 old_instruction->scope, old_instruction->source_node);
9659 IrInstruction *new_instruction = &const_instruction->base;
9660 new_instruction->value.type = ty;
9661 new_instruction->value.special = ConstValSpecialStatic;
9662 return new_instruction;
9663}
9664
9665static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {9726static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
9666 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);9727 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);
9667 result->value.data.x_type = ty;9728 result->value.data.x_type = ty;
...@@ -9719,13 +9780,13 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un...@@ -9719,13 +9780,13 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
9719 zig_unreachable();9780 zig_unreachable();
9720}9781}
97219782
9722IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,9783ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
9723 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,9784 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
9724 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,9785 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
9725 IrExecutable *parent_exec)9786 IrExecutable *parent_exec)
9726{9787{
9727 if (expected_type != nullptr && type_is_invalid(expected_type))9788 if (expected_type != nullptr && type_is_invalid(expected_type))
9728 return codegen->invalid_instruction;9789 return &codegen->invalid_instruction->value;
97299790
9730 IrExecutable *ir_executable = allocate<IrExecutable>(1);9791 IrExecutable *ir_executable = allocate<IrExecutable>(1);
9731 ir_executable->source_node = source_node;9792 ir_executable->source_node = source_node;
...@@ -9738,13 +9799,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node...@@ -9738,13 +9799,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
9738 ir_gen(codegen, node, scope, ir_executable);9799 ir_gen(codegen, node, scope, ir_executable);
97399800
9740 if (ir_executable->invalid)9801 if (ir_executable->invalid)
9741 return codegen->invalid_instruction;9802 return &codegen->invalid_instruction->value;
97429803
9743 if (codegen->verbose_ir) {9804 if (codegen->verbose_ir) {
9744 fprintf(stderr, "\nSource: ");9805 fprintf(stderr, "\nSource: ");
9745 ast_render(codegen, stderr, node, 4);9806 ast_render(codegen, stderr, node, 4);
9746 fprintf(stderr, "\n{ // (IR)\n");9807 fprintf(stderr, "\n{ // (IR)\n");
9747 ir_print(codegen, stderr, ir_executable, 4);9808 ir_print(codegen, stderr, ir_executable, 2);
9748 fprintf(stderr, "}\n");9809 fprintf(stderr, "}\n");
9749 }9810 }
9750 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);9811 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);
...@@ -9760,11 +9821,11 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node...@@ -9760,11 +9821,11 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
9760 analyzed_executable->begin_scope = scope;9821 analyzed_executable->begin_scope = scope;
9761 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);9822 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);
9762 if (type_is_invalid(result_type))9823 if (type_is_invalid(result_type))
9763 return codegen->invalid_instruction;9824 return &codegen->invalid_instruction->value;
97649825
9765 if (codegen->verbose_ir) {9826 if (codegen->verbose_ir) {
9766 fprintf(stderr, "{ // (analyzed)\n");9827 fprintf(stderr, "{ // (analyzed)\n");
9767 ir_print(codegen, stderr, analyzed_executable, 4);9828 ir_print(codegen, stderr, analyzed_executable, 2);
9768 fprintf(stderr, "}\n");9829 fprintf(stderr, "}\n");
9769 }9830 }
97709831
...@@ -9838,7 +9899,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {...@@ -9838,7 +9899,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
9838 return const_val->data.x_ptr.data.fn.fn_entry;9899 return const_val->data.x_ptr.data.fn.fn_entry;
9839}9900}
98409901
9841static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {9902static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
9903 ZigType *wanted_type)
9904{
9842 assert(wanted_type->id == ZigTypeIdOptional);9905 assert(wanted_type->id == ZigTypeIdOptional);
98439906
9844 if (instr_is_comptime(value)) {9907 if (instr_is_comptime(value)) {
...@@ -9854,7 +9917,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc...@@ -9854,7 +9917,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
9854 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,9917 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9855 source_instr->scope, source_instr->source_node);9918 source_instr->scope, source_instr->source_node);
9856 const_instruction->base.value.special = ConstValSpecialStatic;9919 const_instruction->base.value.special = ConstValSpecialStatic;
9857 if (get_codegen_ptr_type(wanted_type) != nullptr) {9920 if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) {
9858 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);9921 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
9859 } else {9922 } else {
9860 const_instruction->base.value.data.x_optional = val;9923 const_instruction->base.value.data.x_optional = val;
...@@ -9885,11 +9948,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction...@@ -9885,11 +9948,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
9885 if (!val)9948 if (!val)
9886 return ira->codegen->invalid_instruction;9949 return ira->codegen->invalid_instruction;
98879950
9951 ConstExprValue *err_set_val = create_const_vals(1);
9952 err_set_val->type = wanted_type->data.error_union.err_set_type;
9953 err_set_val->special = ConstValSpecialStatic;
9954 err_set_val->data.x_err_set = nullptr;
9955
9888 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,9956 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9889 source_instr->scope, source_instr->source_node);9957 source_instr->scope, source_instr->source_node);
9890 const_instruction->base.value.type = wanted_type;9958 const_instruction->base.value.type = wanted_type;
9891 const_instruction->base.value.special = ConstValSpecialStatic;9959 const_instruction->base.value.special = ConstValSpecialStatic;
9892 const_instruction->base.value.data.x_err_union.err = nullptr;9960 const_instruction->base.value.data.x_err_union.error_set = err_set_val;
9893 const_instruction->base.value.data.x_err_union.payload = val;9961 const_instruction->base.value.data.x_err_union.payload = val;
9894 return &const_instruction->base;9962 return &const_instruction->base;
9895 }9963 }
...@@ -9954,11 +10022,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so...@@ -9954,11 +10022,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
9954 if (!val)10022 if (!val)
9955 return ira->codegen->invalid_instruction;10023 return ira->codegen->invalid_instruction;
995610024
10025 ConstExprValue *err_set_val = create_const_vals(1);
10026 err_set_val->special = ConstValSpecialStatic;
10027 err_set_val->type = wanted_type->data.error_union.err_set_type;
10028 err_set_val->data.x_err_set = val->data.x_err_set;
10029
9957 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,10030 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9958 source_instr->scope, source_instr->source_node);10031 source_instr->scope, source_instr->source_node);
9959 const_instruction->base.value.type = wanted_type;10032 const_instruction->base.value.type = wanted_type;
9960 const_instruction->base.value.special = ConstValSpecialStatic;10033 const_instruction->base.value.special = ConstValSpecialStatic;
9961 const_instruction->base.value.data.x_err_union.err = val->data.x_err_set;10034 const_instruction->base.value.data.x_err_union.error_set = err_set_val;
9962 const_instruction->base.value.data.x_err_union.payload = nullptr;10035 const_instruction->base.value.data.x_err_union.payload = nullptr;
9963 return &const_instruction->base;10036 return &const_instruction->base;
9964 }10037 }
...@@ -9980,8 +10053,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so...@@ -9980,8 +10053,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
9980 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);10053 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);
9981 const_instruction->base.value.special = ConstValSpecialStatic;10054 const_instruction->base.value.special = ConstValSpecialStatic;
9982 if (get_codegen_ptr_type(wanted_type) != nullptr) {10055 if (get_codegen_ptr_type(wanted_type) != nullptr) {
9983 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;10056 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull;
9984 const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0;10057 } else if (is_opt_err_set(wanted_type)) {
10058 const_instruction->base.value.data.x_err_set = nullptr;
9985 } else {10059 } else {
9986 const_instruction->base.value.data.x_optional = nullptr;10060 const_instruction->base.value.data.x_optional = nullptr;
9987 }10061 }
...@@ -10014,7 +10088,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi...@@ -10014,7 +10088,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
10014 source_instruction->source_node, value, is_const, is_volatile);10088 source_instruction->source_node, value, is_const, is_volatile);
10015 new_instruction->value.type = ptr_type;10089 new_instruction->value.type = ptr_type;
10016 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;10090 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
10017 if (type_has_bits(ptr_type)) {10091 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
10018 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);10092 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
10019 assert(fn_entry);10093 assert(fn_entry);
10020 fn_entry->alloca_list.append(new_instruction);10094 fn_entry->alloca_list.append(new_instruction);
...@@ -10040,20 +10114,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -10040,20 +10114,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
10040 ZigType *array_type = array->value.type;10114 ZigType *array_type = array->value.type;
10041 assert(array_type->id == ZigTypeIdArray);10115 assert(array_type->id == ZigTypeIdArray);
1004210116
10043 if (instr_is_comptime(array)) {10117 if (instr_is_comptime(array) || array_type->data.array.len == 0) {
10044 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10118 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10045 source_instr->source_node, wanted_type);
10046 init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);10119 init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);
10047 result->value.type = wanted_type;10120 result->value.type = wanted_type;
10048 return result;10121 return result;
10049 }10122 }
1005010123
10051 IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope,10124 IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
10052 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10053 init_const_usize(ira->codegen, &start->value, 0);10125 init_const_usize(ira->codegen, &start->value, 0);
1005410126
10055 IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope,10127 IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
10056 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10057 init_const_usize(ira->codegen, &end->value, array_type->data.array.len);10128 init_const_usize(ira->codegen, &end->value, array_type->data.array.len);
1005810129
10059 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);10130 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
...@@ -10092,8 +10163,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -10092,8 +10163,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
10092 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);10163 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
10093 if (!val)10164 if (!val)
10094 return ira->codegen->invalid_instruction;10165 return ira->codegen->invalid_instruction;
10095 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10166 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10096 source_instr->source_node, wanted_type);
10097 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);10167 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
10098 return result;10168 return result;
10099 }10169 }
...@@ -10103,8 +10173,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -10103,8 +10173,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
10103 actual_type->data.enumeration.src_field_count == 1)10173 actual_type->data.enumeration.src_field_count == 1)
10104 {10174 {
10105 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);10175 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
10106 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10176 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10107 source_instr->source_node, wanted_type);
10108 init_const_bigint(&result->value, wanted_type,10177 init_const_bigint(&result->value, wanted_type,
10109 &actual_type->data.enumeration.fields[0].value);10178 &actual_type->data.enumeration.fields[0].value);
10110 return result;10179 return result;
...@@ -10127,8 +10196,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10127,8 +10196,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10127 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);10196 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
10128 if (!val)10197 if (!val)
10129 return ira->codegen->invalid_instruction;10198 return ira->codegen->invalid_instruction;
10130 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10199 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10131 source_instr->source_node, wanted_type);
10132 result->value.special = ConstValSpecialStatic;10200 result->value.special = ConstValSpecialStatic;
10133 result->value.type = wanted_type;10201 result->value.type = wanted_type;
10134 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag);10202 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag);
...@@ -10139,8 +10207,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10139,8 +10207,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10139 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&10207 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
10140 wanted_type->data.enumeration.src_field_count == 1)10208 wanted_type->data.enumeration.src_field_count == 1)
10141 {10209 {
10142 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10210 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10143 source_instr->source_node, wanted_type);
10144 result->value.special = ConstValSpecialStatic;10211 result->value.special = ConstValSpecialStatic;
10145 result->value.type = wanted_type;10212 result->value.type = wanted_type;
10146 TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field;10213 TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field;
...@@ -10157,8 +10224,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10157,8 +10224,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10157static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,10224static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
10158 IrInstruction *target, ZigType *wanted_type)10225 IrInstruction *target, ZigType *wanted_type)
10159{10226{
10160 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10227 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10161 source_instr->source_node, wanted_type);
10162 init_const_undefined(ira->codegen, &result->value);10228 init_const_undefined(ira->codegen, &result->value);
10163 return result;10229 return result;
10164}10230}
...@@ -10190,8 +10256,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so...@@ -10190,8 +10256,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
10190 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));10256 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
10191 return ira->codegen->invalid_instruction;10257 return ira->codegen->invalid_instruction;
10192 }10258 }
10193 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10259 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10194 source_instr->source_node, wanted_type);
10195 result->value.special = ConstValSpecialStatic;10260 result->value.special = ConstValSpecialStatic;
10196 result->value.type = wanted_type;10261 result->value.type = wanted_type;
10197 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);10262 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);
...@@ -10246,8 +10311,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction...@@ -10246,8 +10311,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
10246 return ira->codegen->invalid_instruction;10311 return ira->codegen->invalid_instruction;
10247 }10312 }
10248 }10313 }
10249 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10314 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10250 source_instr->source_node, wanted_type);
10251 result->value.type = wanted_type;10315 result->value.type = wanted_type;
10252 if (wanted_type->id == ZigTypeIdInt) {10316 if (wanted_type->id == ZigTypeIdInt) {
10253 bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);10317 bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);
...@@ -10301,8 +10365,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -10301,8 +10365,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
10301 return ira->codegen->invalid_instruction;10365 return ira->codegen->invalid_instruction;
10302 }10366 }
1030310367
10304 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10368 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10305 source_instr->source_node, wanted_type);
10306 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);10369 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);
10307 return result;10370 return result;
10308 }10371 }
...@@ -10320,8 +10383,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction...@@ -10320,8 +10383,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
10320 if (!val)10383 if (!val)
10321 return ira->codegen->invalid_instruction;10384 return ira->codegen->invalid_instruction;
1032210385
10323 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10386 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10324 source_instr->source_node, wanted_type);
10325 if (wanted_type->id == ZigTypeIdComptimeFloat) {10387 if (wanted_type->id == ZigTypeIdComptimeFloat) {
10326 float_init_float(&result->value, val);10388 float_init_float(&result->value, val);
10327 } else if (wanted_type->id == ZigTypeIdComptimeInt) {10389 } else if (wanted_type->id == ZigTypeIdComptimeInt) {
...@@ -10344,8 +10406,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc...@@ -10344,8 +10406,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
10344 if (!val)10406 if (!val)
10345 return ira->codegen->invalid_instruction;10407 return ira->codegen->invalid_instruction;
1034610408
10347 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10409 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10348 source_instr->source_node, wanted_type);
1034910410
10350 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {10411 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {
10351 return ira->codegen->invalid_instruction;10412 return ira->codegen->invalid_instruction;
...@@ -10409,12 +10470,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -10409,12 +10470,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
10409 if (!val)10470 if (!val)
10410 return ira->codegen->invalid_instruction;10471 return ira->codegen->invalid_instruction;
1041110472
10412 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10473 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10413 source_instr->source_node, wanted_type);
1041410474
10415 ErrorTableEntry *err;10475 ErrorTableEntry *err;
10416 if (err_type->id == ZigTypeIdErrorUnion) {10476 if (err_type->id == ZigTypeIdErrorUnion) {
10417 err = val->data.x_err_union.err;10477 err = val->data.x_err_union.error_set->data.x_err_set;
10418 } else if (err_type->id == ZigTypeIdErrorSet) {10478 } else if (err_type->id == ZigTypeIdErrorSet) {
10419 err = val->data.x_err_set;10479 err = val->data.x_err_set;
10420 } else {10480 } else {
...@@ -10449,15 +10509,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -10449,15 +10509,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
10449 return ira->codegen->invalid_instruction;10509 return ira->codegen->invalid_instruction;
10450 }10510 }
10451 if (err_set_type->data.error_set.err_count == 0) {10511 if (err_set_type->data.error_set.err_count == 0) {
10452 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10512 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10453 source_instr->source_node, wanted_type);
10454 result->value.type = wanted_type;
10455 bigint_init_unsigned(&result->value.data.x_bigint, 0);10513 bigint_init_unsigned(&result->value.data.x_bigint, 0);
10456 return result;10514 return result;
10457 } else if (err_set_type->data.error_set.err_count == 1) {10515 } else if (err_set_type->data.error_set.err_count == 1) {
10458 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10516 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10459 source_instr->source_node, wanted_type);
10460 result->value.type = wanted_type;
10461 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];10517 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];
10462 bigint_init_unsigned(&result->value.data.x_bigint, err->value);10518 bigint_init_unsigned(&result->value.data.x_bigint, err->value);
10463 return result;10519 return result;
...@@ -10504,8 +10560,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou...@@ -10504,8 +10560,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
10504 array_val->type = array_type;10560 array_val->type = array_type;
10505 array_val->data.x_array.special = ConstArraySpecialNone;10561 array_val->data.x_array.special = ConstArraySpecialNone;
10506 array_val->data.x_array.data.s_none.elements = pointee;10562 array_val->data.x_array.data.s_none.elements = pointee;
10507 array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar;10563 array_val->parent.id = ConstParentIdScalar;
10508 array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee;10564 array_val->parent.data.p_scalar.scalar_val = pointee;
1050910565
10510 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,10566 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
10511 source_instr->scope, source_instr->source_node);10567 source_instr->scope, source_instr->source_node);
...@@ -10653,12 +10709,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10653,12 +10709,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10653 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,10709 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
10654 false).id == ConstCastResultIdOk)10710 false).id == ConstCastResultIdOk)
10655 {10711 {
10656 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);10712 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
10657 } else if (actual_type->id == ZigTypeIdComptimeInt ||10713 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10658 actual_type->id == ZigTypeIdComptimeFloat)10714 actual_type->id == ZigTypeIdComptimeFloat)
10659 {10715 {
10660 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {10716 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
10661 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);10717 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
10662 } else {10718 } else {
10663 return ira->codegen->invalid_instruction;10719 return ira->codegen->invalid_instruction;
10664 }10720 }
...@@ -10682,7 +10738,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10682,7 +10738,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10682 wanted_child_type);10738 wanted_child_type);
10683 if (type_is_invalid(cast1->value.type))10739 if (type_is_invalid(cast1->value.type))
10684 return ira->codegen->invalid_instruction;10740 return ira->codegen->invalid_instruction;
10685 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);10741 return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type);
10686 }10742 }
10687 }10743 }
10688 }10744 }
...@@ -10735,6 +10791,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10735,6 +10791,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10735 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||10791 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
10736 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))10792 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
10737 {10793 {
10794 if (value->value.special == ConstValSpecialUndef) {
10795 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10796 result->value.special = ConstValSpecialUndef;
10797 return result;
10798 }
10738 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {10799 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
10739 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {10800 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
10740 IrInstruction *result = ir_const(ira, source_instr, wanted_type);10801 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
...@@ -10788,6 +10849,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10788,6 +10849,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1078810849
1078910850
10790 // cast from [N]T to []const T10851 // cast from [N]T to []const T
10852 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
10791 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {10853 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
10792 ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;10854 ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
10793 assert(ptr_type->id == ZigTypeIdPointer);10855 assert(ptr_type->id == ZigTypeIdPointer);
...@@ -10800,6 +10862,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10800,6 +10862,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10800 }10862 }
1080110863
10802 // cast from [N]T to ?[]const T10864 // cast from [N]T to ?[]const T
10865 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
10803 if (wanted_type->id == ZigTypeIdOptional &&10866 if (wanted_type->id == ZigTypeIdOptional &&
10804 is_slice(wanted_type->data.maybe.child_type) &&10867 is_slice(wanted_type->data.maybe.child_type) &&
10805 actual_type->id == ZigTypeIdArray)10868 actual_type->id == ZigTypeIdArray)
...@@ -10894,7 +10957,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10894,7 +10957,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10894 }10957 }
10895 }10958 }
1089610959
10897 // cast from error set to error union type10960 // cast from E to E!T
10898 if (wanted_type->id == ZigTypeIdErrorUnion &&10961 if (wanted_type->id == ZigTypeIdErrorUnion &&
10899 actual_type->id == ZigTypeIdErrorSet)10962 actual_type->id == ZigTypeIdErrorSet)
10900 {10963 {
...@@ -11046,8 +11109,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -11046,8 +11109,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
11046 ZigType *child_type = type_entry->data.pointer.child_type;11109 ZigType *child_type = type_entry->data.pointer.child_type;
11047 // dereferencing a *u0 is comptime known to be 011110 // dereferencing a *u0 is comptime known to be 0
11048 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {11111 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
11049 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,11112 IrInstruction *result = ir_const(ira, source_instruction, child_type);
11050 source_instruction->source_node, child_type);
11051 init_const_unsigned_negative(&result->value, child_type, 0, false);11113 init_const_unsigned_negative(&result->value, child_type, 0, false);
11052 return result;11114 return result;
11053 }11115 }
...@@ -11061,8 +11123,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -11061,8 +11123,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
11061 {11123 {
11062 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);11124 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
11063 if (pointee->special != ConstValSpecialRuntime) {11125 if (pointee->special != ConstValSpecialRuntime) {
11064 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,11126 IrInstruction *result = ir_const(ira, source_instruction, child_type);
11065 source_instruction->source_node, child_type);
1106611127
11067 if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,11128 if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
11068 &ptr->value)))11129 &ptr->value)))
...@@ -11074,7 +11135,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -11074,7 +11135,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
11074 }11135 }
11075 }11136 }
11076 }11137 }
11077 // TODO if the instruction is a const ref instruction we can skip it11138 // if the instruction is a const ref instruction we can skip it
11139 if (ptr->id == IrInstructionIdRef) {
11140 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
11141 return ref_inst->value;
11142 }
11078 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,11143 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
11079 source_instruction->source_node, ptr);11144 source_instruction->source_node, ptr);
11080 load_ptr_instruction->value.type = child_type;11145 load_ptr_instruction->value.type = child_type;
...@@ -11321,8 +11386,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio...@@ -11321,8 +11386,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
1132111386
11322static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {11387static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {
11323 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);11388 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
11324 // TODO determine if we need to use copy_const_val here11389 copy_const_val(&result->value, &instruction->base.value, true);
11325 result->value = instruction->base.value;
11326 return result;11390 return result;
11327}11391}
1132811392
...@@ -11397,6 +11461,8 @@ static bool optional_value_is_null(ConstExprValue *val) {...@@ -11397,6 +11461,8 @@ static bool optional_value_is_null(ConstExprValue *val) {
11397 if (get_codegen_ptr_type(val->type) != nullptr) {11461 if (get_codegen_ptr_type(val->type) != nullptr) {
11398 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&11462 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
11399 val->data.x_ptr.data.hard_coded_addr.addr == 0;11463 val->data.x_ptr.data.hard_coded_addr.addr == 0;
11464 } else if (is_opt_err_set(val->type)) {
11465 return val->data.x_err_set == nullptr;
11400 } else {11466 } else {
11401 return val->data.x_optional == nullptr;11467 return val->data.x_optional == nullptr;
11402 }11468 }
...@@ -11596,19 +11662,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11596,19 +11662,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11596 if (casted_op2 == ira->codegen->invalid_instruction)11662 if (casted_op2 == ira->codegen->invalid_instruction)
11597 return ira->codegen->invalid_instruction;11663 return ira->codegen->invalid_instruction;
1159811664
11599 bool requires_comptime;11665 bool one_possible_value;
11600 switch (type_requires_comptime(ira->codegen, resolved_type)) {11666 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
11601 case ReqCompTimeYes:11667 case OnePossibleValueInvalid:
11602 requires_comptime = true;11668 return ira->codegen->invalid_instruction;
11669 case OnePossibleValueYes:
11670 one_possible_value = true;
11603 break;11671 break;
11604 case ReqCompTimeNo:11672 case OnePossibleValueNo:
11605 requires_comptime = false;11673 one_possible_value = false;
11606 break;11674 break;
11607 case ReqCompTimeInvalid:
11608 return ira->codegen->invalid_instruction;
11609 }11675 }
1161011676
11611 bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type);
11612 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {11677 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
11613 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);11678 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
11614 if (op1_val == nullptr)11679 if (op1_val == nullptr)
...@@ -12497,13 +12562,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio...@@ -12497,13 +12562,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio
12497 zig_unreachable();12562 zig_unreachable();
12498}12563}
1249912564
12500static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {12565static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
12566 IrInstructionDeclVarSrc *decl_var_instruction)
12567{
12501 Error err;12568 Error err;
12502 ZigVar *var = decl_var_instruction->var;12569 ZigVar *var = decl_var_instruction->var;
1250312570
12504 IrInstruction *init_value = decl_var_instruction->init_value->child;12571 IrInstruction *init_value = decl_var_instruction->init_value->child;
12505 if (type_is_invalid(init_value->value.type)) {12572 if (type_is_invalid(init_value->value.type)) {
12506 var->value->type = ira->codegen->builtin_types.entry_invalid;12573 var->var_type = ira->codegen->builtin_types.entry_invalid;
12507 return ira->codegen->invalid_instruction;12574 return ira->codegen->invalid_instruction;
12508 }12575 }
1250912576
...@@ -12514,7 +12581,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12514,7 +12581,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12514 ZigType *proposed_type = ir_resolve_type(ira, var_type);12581 ZigType *proposed_type = ir_resolve_type(ira, var_type);
12515 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);12582 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);
12516 if (type_is_invalid(explicit_type)) {12583 if (type_is_invalid(explicit_type)) {
12517 var->value->type = ira->codegen->builtin_types.entry_invalid;12584 var->var_type = ira->codegen->builtin_types.entry_invalid;
12518 return ira->codegen->invalid_instruction;12585 return ira->codegen->invalid_instruction;
12519 }12586 }
12520 }12587 }
...@@ -12539,7 +12606,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12539,7 +12606,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12539 case ReqCompTimeInvalid:12606 case ReqCompTimeInvalid:
12540 result_type = ira->codegen->builtin_types.entry_invalid;12607 result_type = ira->codegen->builtin_types.entry_invalid;
12541 break;12608 break;
12542 case ReqCompTimeYes: {12609 case ReqCompTimeYes:
12543 var_class_requires_const = true;12610 var_class_requires_const = true;
12544 if (!var->gen_is_const && !is_comptime_var) {12611 if (!var->gen_is_const && !is_comptime_var) {
12545 ir_add_error_node(ira, source_node,12612 ir_add_error_node(ira, source_node,
...@@ -12548,7 +12615,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12548,7 +12615,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12548 result_type = ira->codegen->builtin_types.entry_invalid;12615 result_type = ira->codegen->builtin_types.entry_invalid;
12549 }12616 }
12550 break;12617 break;
12551 }
12552 case ReqCompTimeNo:12618 case ReqCompTimeNo:
12553 if (casted_init_value->value.special == ConstValSpecialStatic &&12619 if (casted_init_value->value.special == ConstValSpecialStatic &&
12554 casted_init_value->value.type->id == ZigTypeIdFn &&12620 casted_init_value->value.type->id == ZigTypeIdFn &&
...@@ -12567,7 +12633,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12567,7 +12633,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12567 break;12633 break;
12568 }12634 }
1256912635
12570 if (var->value->type != nullptr && !is_comptime_var) {12636 if (var->var_type != nullptr && !is_comptime_var) {
12571 // This is at least the second time we've seen this variable declaration during analysis.12637 // This is at least the second time we've seen this variable declaration during analysis.
12572 // This means that this is actually a different variable due to, e.g. an inline while loop.12638 // This means that this is actually a different variable due to, e.g. an inline while loop.
12573 // We make a new variable so that it can hold a different type, and so the debug info can12639 // We make a new variable so that it can hold a different type, and so the debug info can
...@@ -12589,8 +12655,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12589,8 +12655,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12589 // This must be done after possibly creating a new variable above12655 // This must be done after possibly creating a new variable above
12590 var->ref_count = 0;12656 var->ref_count = 0;
1259112657
12592 var->value->type = result_type;12658 var->var_type = result_type;
12593 assert(var->value->type);12659 assert(var->var_type);
1259412660
12595 if (type_is_invalid(result_type)) {12661 if (type_is_invalid(result_type)) {
12596 return ir_const_void(ira, &decl_var_instruction->base);12662 return ir_const_void(ira, &decl_var_instruction->base);
...@@ -12598,13 +12664,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12598,13 +12664,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1259812664
12599 if (decl_var_instruction->align_value == nullptr) {12665 if (decl_var_instruction->align_value == nullptr) {
12600 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {12666 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {
12601 var->value->type = ira->codegen->builtin_types.entry_invalid;12667 var->var_type = ira->codegen->builtin_types.entry_invalid;
12602 return ir_const_void(ira, &decl_var_instruction->base);12668 return ir_const_void(ira, &decl_var_instruction->base);
12603 }12669 }
12604 var->align_bytes = get_abi_alignment(ira->codegen, result_type);12670 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
12605 } else {12671 } else {
12606 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {12672 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {
12607 var->value->type = ira->codegen->builtin_types.entry_invalid;12673 var->var_type = ira->codegen->builtin_types.entry_invalid;
12608 }12674 }
12609 }12675 }
1261012676
...@@ -12621,7 +12687,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12621,7 +12687,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12621 } else if (is_comptime_var) {12687 } else if (is_comptime_var) {
12622 ir_add_error(ira, &decl_var_instruction->base,12688 ir_add_error(ira, &decl_var_instruction->base,
12623 buf_sprintf("cannot store runtime value in compile time variable"));12689 buf_sprintf("cannot store runtime value in compile time variable"));
12624 var->value->type = ira->codegen->builtin_types.entry_invalid;12690 var->var_type = ira->codegen->builtin_types.entry_invalid;
12625 return ira->codegen->invalid_instruction;12691 return ira->codegen->invalid_instruction;
12626 }12692 }
1262712693
...@@ -12629,11 +12695,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12629,11 +12695,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12629 if (fn_entry)12695 if (fn_entry)
12630 fn_entry->variable_list.append(var);12696 fn_entry->variable_list.append(var);
1263112697
12632 IrInstruction *result = ir_build_var_decl(&ira->new_irb,12698 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
12633 decl_var_instruction->base.scope, decl_var_instruction->base.source_node,
12634 var, var_type, nullptr, casted_init_value);
12635 result->value.type = ira->codegen->builtin_types.entry_void;
12636 return result;
12637}12699}
1263812700
12639static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {12701static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
...@@ -12963,7 +13025,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node...@@ -12963,7 +13025,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
1296313025
12964 Buf *param_name = param_decl_node->data.param_decl.name;13026 Buf *param_name = param_decl_node->data.param_decl.name;
12965 ZigVar *var = add_variable(ira->codegen, param_decl_node,13027 ZigVar *var = add_variable(ira->codegen, param_decl_node,
12966 *exec_scope, param_name, true, arg_val, nullptr);13028 *exec_scope, param_name, true, arg_val, nullptr, arg_val->type);
12967 *exec_scope = var->child_scope;13029 *exec_scope = var->child_scope;
12968 *next_proto_i += 1;13030 *next_proto_i += 1;
1296913031
...@@ -13021,7 +13083,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -13021,7 +13083,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
13021 if (!param_name) return false;13083 if (!param_name) return false;
13022 if (!is_var_args) {13084 if (!is_var_args) {
13023 ZigVar *var = add_variable(ira->codegen, param_decl_node,13085 ZigVar *var = add_variable(ira->codegen, param_decl_node,
13024 *child_scope, param_name, true, arg_val, nullptr);13086 *child_scope, param_name, true, arg_val, nullptr, arg_val->type);
13025 *child_scope = var->child_scope;13087 *child_scope = var->child_scope;
13026 var->shadowable = !comptime_arg;13088 var->shadowable = !comptime_arg;
1302713089
...@@ -13075,9 +13137,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {...@@ -13075,9 +13137,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
13075 return fn_entry->variable_list.at(next_var_i);13137 return fn_entry->variable_list.at(next_var_i);
13076}13138}
1307713139
13078static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,13140static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) {
13079 ZigVar *var)
13080{
13081 while (var->next_var != nullptr) {13141 while (var->next_var != nullptr) {
13082 var = var->next_var;13142 var = var->next_var;
13083 }13143 }
...@@ -13086,14 +13146,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -13086,14 +13146,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13086 assert(ira->codegen->errors.length != 0);13146 assert(ira->codegen->errors.length != 0);
13087 return ira->codegen->invalid_instruction;13147 return ira->codegen->invalid_instruction;
13088 }13148 }
13089 if (var->value->type == nullptr || type_is_invalid(var->value->type))13149 if (var->var_type == nullptr || type_is_invalid(var->var_type))
13090 return ira->codegen->invalid_instruction;13150 return ira->codegen->invalid_instruction;
1309113151
13092 bool comptime_var_mem = ir_get_var_is_comptime(var);13152 bool comptime_var_mem = ir_get_var_is_comptime(var);
1309313153
13094 ConstExprValue *mem_slot = nullptr;13154 ConstExprValue *mem_slot = nullptr;
13095 if (var->value->special == ConstValSpecialStatic) {13155 if (var->const_value->special == ConstValSpecialStatic) {
13096 mem_slot = var->value;13156 mem_slot = var->const_value;
13097 } else {13157 } else {
13098 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {13158 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
13099 // find the relevant exec_context13159 // find the relevant exec_context
...@@ -13122,7 +13182,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -13122,7 +13182,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13122 assert(!comptime_var_mem);13182 assert(!comptime_var_mem);
13123 ptr_mut = ConstPtrMutRuntimeVar;13183 ptr_mut = ConstPtrMutRuntimeVar;
13124 }13184 }
13125 return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type,13185 return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type,
13126 ptr_mut, is_const, is_volatile, var->align_bytes);13186 ptr_mut, is_const, is_volatile, var->align_bytes);
13127 }13187 }
13128 }13188 }
...@@ -13133,7 +13193,7 @@ no_mem_slot:...@@ -13133,7 +13193,7 @@ no_mem_slot:
1313313193
13134 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,13194 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
13135 instruction->scope, instruction->source_node, var);13195 instruction->scope, instruction->source_node, var);
13136 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,13196 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type,
13137 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);13197 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
1313813198
13139 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);13199 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
...@@ -13142,6 +13202,96 @@ no_mem_slot:...@@ -13142,6 +13202,96 @@ no_mem_slot:
13142 return var_ptr_instruction;13202 return var_ptr_instruction;
13143}13203}
1314413204
13205static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
13206 IrInstruction *ptr, IrInstruction *uncasted_value)
13207{
13208 if (ptr->value.type->id != ZigTypeIdPointer) {
13209 ir_add_error(ira, ptr,
13210 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
13211 return ira->codegen->invalid_instruction;
13212 }
13213
13214 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
13215 return ir_const_void(ira, source_instr);
13216 }
13217
13218 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
13219 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13220 return ira->codegen->invalid_instruction;
13221 }
13222
13223 ZigType *child_type = ptr->value.type->data.pointer.child_type;
13224 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
13225 if (value == ira->codegen->invalid_instruction)
13226 return ira->codegen->invalid_instruction;
13227
13228 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
13229 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
13230 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13231 return ira->codegen->invalid_instruction;
13232 }
13233 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
13234 if (instr_is_comptime(value)) {
13235 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
13236 if (dest_val == nullptr)
13237 return ira->codegen->invalid_instruction;
13238 if (dest_val->special != ConstValSpecialRuntime) {
13239 // TODO this allows a value stored to have the original value modified and then
13240 // have that affect what should be a copy. We need some kind of advanced copy-on-write
13241 // system to make these two tests pass at the same time:
13242 // * "string literal used as comptime slice is memoized"
13243 // * "comptime modification of const struct field" - except modified to avoid
13244 // ConstPtrMutComptimeVar, thus defeating the logic below.
13245 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
13246 copy_const_val(dest_val, &value->value, same_global_refs);
13247 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
13248 switch (type_has_one_possible_value(ira->codegen, child_type)) {
13249 case OnePossibleValueInvalid:
13250 return ira->codegen->invalid_instruction;
13251 case OnePossibleValueNo:
13252 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
13253 break;
13254 case OnePossibleValueYes:
13255 break;
13256 }
13257 }
13258 return ir_const_void(ira, source_instr);
13259 }
13260 }
13261 ir_add_error(ira, source_instr,
13262 buf_sprintf("cannot store runtime value in compile time variable"));
13263 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
13264 dest_val->type = ira->codegen->builtin_types.entry_invalid;
13265
13266 return ira->codegen->invalid_instruction;
13267 }
13268 }
13269
13270 switch (type_requires_comptime(ira->codegen, child_type)) {
13271 case ReqCompTimeInvalid:
13272 return ira->codegen->invalid_instruction;
13273 case ReqCompTimeYes:
13274 switch (type_has_one_possible_value(ira->codegen, ptr->value.type)) {
13275 case OnePossibleValueInvalid:
13276 return ira->codegen->invalid_instruction;
13277 case OnePossibleValueNo:
13278 ir_add_error(ira, source_instr,
13279 buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name)));
13280 return ira->codegen->invalid_instruction;
13281 case OnePossibleValueYes:
13282 return ir_const_void(ira, source_instr);
13283 }
13284 zig_unreachable();
13285 case ReqCompTimeNo:
13286 break;
13287 }
13288
13289 IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
13290 ptr, value);
13291 result->value.type = ira->codegen->builtin_types.entry_void;
13292 return result;
13293}
13294
13145static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,13295static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
13146 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,13296 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
13147 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)13297 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
...@@ -13286,7 +13436,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13286,7 +13436,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13286 }13436 }
1328713437
13288 bool cacheable = fn_eval_cacheable(exec_scope, return_type);13438 bool cacheable = fn_eval_cacheable(exec_scope, return_type);
13289 IrInstruction *result = nullptr;13439 ConstExprValue *result = nullptr;
13290 if (cacheable) {13440 if (cacheable) {
13291 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);13441 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
13292 if (entry)13442 if (entry)
...@@ -13302,18 +13452,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13302,18 +13452,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1330213452
13303 if (inferred_err_set_type != nullptr) {13453 if (inferred_err_set_type != nullptr) {
13304 inferred_err_set_type->data.error_set.infer_fn = nullptr;13454 inferred_err_set_type->data.error_set.infer_fn = nullptr;
13305 if (result->value.type->id == ZigTypeIdErrorUnion) {13455 if (result->type->id == ZigTypeIdErrorUnion) {
13306 if (result->value.data.x_err_union.err != nullptr) {13456 ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
13457 if (err != nullptr) {
13307 inferred_err_set_type->data.error_set.err_count = 1;13458 inferred_err_set_type->data.error_set.err_count = 1;
13308 inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1);13459 inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1);
13309 inferred_err_set_type->data.error_set.errors[0] = result->value.data.x_err_union.err;13460 inferred_err_set_type->data.error_set.errors[0] = err;
13310 }13461 }
13311 ZigType *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type;13462 ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type;
13312 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;13463 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;
13313 inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;13464 inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;
13314 } else if (result->value.type->id == ZigTypeIdErrorSet) {13465 } else if (result->type->id == ZigTypeIdErrorSet) {
13315 inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count;13466 inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count;
13316 inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors;13467 inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors;
13317 }13468 }
13318 }13469 }
1331913470
...@@ -13321,13 +13472,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13321,13 +13472,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13321 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);13472 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
13322 }13473 }
1332313474
13324 if (type_is_invalid(result->value.type))13475 if (type_is_invalid(result->type))
13325 return ira->codegen->invalid_instruction;13476 return ira->codegen->invalid_instruction;
13326 }13477 }
1332713478
13328 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type);13479 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);
13329 // TODO should we use copy_const_val?13480 copy_const_val(&new_instruction->value, result, true);
13330 new_instruction->value = result->value;
13331 new_instruction->value.type = return_type;13481 new_instruction->value.type = return_type;
13332 return ir_finish_anal(ira, new_instruction);13482 return ir_finish_anal(ira, new_instruction);
13333 }13483 }
...@@ -13486,18 +13636,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13486,18 +13636,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13486 ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,13636 ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,
13487 first_var_arg, inst_fn_type_id.param_count);13637 first_var_arg, inst_fn_type_id.param_count);
13488 ZigVar *var = add_variable(ira->codegen, param_decl_node,13638 ZigVar *var = add_variable(ira->codegen, param_decl_node,
13489 impl_fn->child_scope, param_name, true, var_args_val, nullptr);13639 impl_fn->child_scope, param_name, true, var_args_val, nullptr, var_args_val->type);
13490 impl_fn->child_scope = var->child_scope;13640 impl_fn->child_scope = var->child_scope;
13491 }13641 }
1349213642
13493 if (fn_proto_node->data.fn_proto.align_expr != nullptr) {13643 if (fn_proto_node->data.fn_proto.align_expr != nullptr) {
13494 IrInstruction *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,13644 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
13495 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),13645 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
13496 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,13646 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
13497 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);13647 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);
13648 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
13649 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
13650 const_instruction->base.value = *align_result;
1349813651
13499 uint32_t align_bytes = 0;13652 uint32_t align_bytes = 0;
13500 ir_resolve_align(ira, align_result, &align_bytes);13653 ir_resolve_align(ira, &const_instruction->base, &align_bytes);
13501 impl_fn->align_bytes = align_bytes;13654 impl_fn->align_bytes = align_bytes;
13502 inst_fn_type_id.alignment = align_bytes;13655 inst_fn_type_id.alignment = align_bytes;
13503 }13656 }
...@@ -13575,12 +13728,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13575,12 +13728,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13575 ira->codegen->fn_defs.append(impl_fn);13728 ira->codegen->fn_defs.append(impl_fn);
13576 }13729 }
1357713730
13578 ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;13731 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
13579 if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) {13732 if (fn_type_can_fail(impl_fn_type_id)) {
13580 parent_fn_entry->calls_or_awaits_errorable_fn = true;13733 parent_fn_entry->calls_or_awaits_errorable_fn = true;
13581 }13734 }
1358213735
13583 size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;13736 size_t impl_param_count = impl_fn_type_id->param_count;
13584 if (call_instruction->is_async) {13737 if (call_instruction->is_async) {
13585 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,13738 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
13586 fn_ref, casted_args, impl_param_count, async_allocator_inst);13739 fn_ref, casted_args, impl_param_count, async_allocator_inst);
...@@ -13593,9 +13746,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13593,9 +13746,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13593 call_instruction->base.scope, call_instruction->base.source_node,13746 call_instruction->base.scope, call_instruction->base.source_node,
13594 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,13747 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
13595 call_instruction->is_async, nullptr, casted_new_stack);13748 call_instruction->is_async, nullptr, casted_new_stack);
13596 new_call_instruction->value.type = return_type;13749 new_call_instruction->value.type = impl_fn_type_id->return_type;
1359713750
13598 ir_add_alloca(ira, new_call_instruction, return_type);13751 ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type);
1359913752
13600 return ir_finish_anal(ira, new_call_instruction);13753 return ir_finish_anal(ira, new_call_instruction);
13601 }13754 }
...@@ -13790,6 +13943,13 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -13790,6 +13943,13 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
13790 switch (ptr_val->data.x_ptr.special) {13943 switch (ptr_val->data.x_ptr.special) {
13791 case ConstPtrSpecialInvalid:13944 case ConstPtrSpecialInvalid:
13792 zig_unreachable();13945 zig_unreachable();
13946 case ConstPtrSpecialNull:
13947 if (dst_size == 0)
13948 return ErrorNone;
13949 opt_ir_add_error_node(ira, codegen, source_node,
13950 buf_sprintf("attempt to read %zu bytes from null pointer",
13951 dst_size));
13952 return ErrorSemanticAnalyzeFail;
13793 case ConstPtrSpecialRef: {13953 case ConstPtrSpecialRef: {
13794 opt_ir_add_error_node(ira, codegen, source_node,13954 opt_ir_add_error_node(ira, codegen, source_node,
13795 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",13955 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
...@@ -13822,6 +13982,9 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -13822,6 +13982,9 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
13822 return ErrorNone;13982 return ErrorNone;
13823 }13983 }
13824 case ConstPtrSpecialBaseStruct:13984 case ConstPtrSpecialBaseStruct:
13985 case ConstPtrSpecialBaseErrorUnionCode:
13986 case ConstPtrSpecialBaseErrorUnionPayload:
13987 case ConstPtrSpecialBaseOptionalPayload:
13825 case ConstPtrSpecialDiscard:13988 case ConstPtrSpecialDiscard:
13826 case ConstPtrSpecialHardCodedAddr:13989 case ConstPtrSpecialHardCodedAddr:
13827 case ConstPtrSpecialFunction:13990 case ConstPtrSpecialFunction:
...@@ -14017,9 +14180,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi...@@ -14017,9 +14180,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
14017 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))14180 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))
14018 return ir_unreach_error(ira);14181 return ir_unreach_error(ira);
1401914182
14020 if (is_comptime || instr_is_comptime(condition)) {14183 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
14184 IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
14185 if (type_is_invalid(casted_condition->value.type))
14186 return ir_unreach_error(ira);
14187
14188 if (is_comptime || instr_is_comptime(casted_condition)) {
14021 bool cond_is_true;14189 bool cond_is_true;
14022 if (!ir_resolve_bool(ira, condition, &cond_is_true))14190 if (!ir_resolve_bool(ira, casted_condition, &cond_is_true))
14023 return ir_unreach_error(ira);14191 return ir_unreach_error(ira);
1402414192
14025 IrBasicBlock *old_dest_block = cond_is_true ?14193 IrBasicBlock *old_dest_block = cond_is_true ?
...@@ -14038,11 +14206,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi...@@ -14038,11 +14206,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
14038 return ir_finish_anal(ira, result);14206 return ir_finish_anal(ira, result);
14039 }14207 }
1404014208
14041 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
14042 IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
14043 if (casted_condition == ira->codegen->invalid_instruction)
14044 return ir_unreach_error(ira);
14045
14046 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);14209 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);
14047 IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);14210 IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);
14048 if (new_then_block == nullptr)14211 if (new_then_block == nullptr)
...@@ -14081,8 +14244,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -14081,8 +14244,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1408114244
14082 if (value->value.special != ConstValSpecialRuntime) {14245 if (value->value.special != ConstValSpecialRuntime) {
14083 IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);14246 IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);
14084 // TODO use copy_const_val?14247 copy_const_val(&result->value, &value->value, true);
14085 result->value = value->value;
14086 return result;14248 return result;
14087 } else {14249 } else {
14088 return value;14250 return value;
...@@ -14131,14 +14293,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -14131,14 +14293,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
14131 if (type_is_invalid(resolved_type))14293 if (type_is_invalid(resolved_type))
14132 return ira->codegen->invalid_instruction;14294 return ira->codegen->invalid_instruction;
1413314295
14134 if (resolved_type->id == ZigTypeIdComptimeFloat ||14296 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
14135 resolved_type->id == ZigTypeIdComptimeInt ||14297 case OnePossibleValueInvalid:
14136 resolved_type->id == ZigTypeIdNull ||14298 return ira->codegen->invalid_instruction;
14137 resolved_type->id == ZigTypeIdUndefined)14299 case OnePossibleValueYes:
14138 {14300 return ir_const(ira, &phi_instruction->base, resolved_type);
14301 case OnePossibleValueNo:
14302 break;
14303 }
14304
14305 switch (type_requires_comptime(ira->codegen, resolved_type)) {
14306 case ReqCompTimeInvalid:
14307 return ira->codegen->invalid_instruction;
14308 case ReqCompTimeYes:
14139 ir_add_error_node(ira, phi_instruction->base.source_node,14309 ir_add_error_node(ira, phi_instruction->base.source_node,
14140 buf_sprintf("unable to infer expression type"));14310 buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name)));
14141 return ira->codegen->invalid_instruction;14311 return ira->codegen->invalid_instruction;
14312 case ReqCompTimeNo:
14313 break;
14142 }14314 }
1414314315
14144 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);14316 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);
...@@ -14428,10 +14600,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14428,10 +14600,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
14428 }14600 }
14429 case ConstPtrSpecialBaseStruct:14601 case ConstPtrSpecialBaseStruct:
14430 zig_panic("TODO elem ptr on a const inner struct");14602 zig_panic("TODO elem ptr on a const inner struct");
14603 case ConstPtrSpecialBaseErrorUnionCode:
14604 zig_panic("TODO elem ptr on a const inner error union code");
14605 case ConstPtrSpecialBaseErrorUnionPayload:
14606 zig_panic("TODO elem ptr on a const inner error union payload");
14607 case ConstPtrSpecialBaseOptionalPayload:
14608 zig_panic("TODO elem ptr on a const inner optional payload");
14431 case ConstPtrSpecialHardCodedAddr:14609 case ConstPtrSpecialHardCodedAddr:
14432 zig_unreachable();14610 zig_unreachable();
14433 case ConstPtrSpecialFunction:14611 case ConstPtrSpecialFunction:
14434 zig_panic("TODO element ptr of a function casted to a ptr");14612 zig_panic("TODO element ptr of a function casted to a ptr");
14613 case ConstPtrSpecialNull:
14614 zig_panic("TODO elem ptr on a null pointer");
14435 }14615 }
14436 if (new_index >= mem_size) {14616 if (new_index >= mem_size) {
14437 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,14617 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
...@@ -14481,10 +14661,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14481,10 +14661,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
14481 }14661 }
14482 case ConstPtrSpecialBaseStruct:14662 case ConstPtrSpecialBaseStruct:
14483 zig_panic("TODO elem ptr on a slice backed by const inner struct");14663 zig_panic("TODO elem ptr on a slice backed by const inner struct");
14664 case ConstPtrSpecialBaseErrorUnionCode:
14665 zig_panic("TODO elem ptr on a slice backed by const inner error union code");
14666 case ConstPtrSpecialBaseErrorUnionPayload:
14667 zig_panic("TODO elem ptr on a slice backed by const inner error union payload");
14668 case ConstPtrSpecialBaseOptionalPayload:
14669 zig_panic("TODO elem ptr on a slice backed by const optional payload");
14484 case ConstPtrSpecialHardCodedAddr:14670 case ConstPtrSpecialHardCodedAddr:
14485 zig_unreachable();14671 zig_unreachable();
14486 case ConstPtrSpecialFunction:14672 case ConstPtrSpecialFunction:
14487 zig_panic("TODO elem ptr on a slice that was ptrcast from a function");14673 zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
14674 case ConstPtrSpecialNull:
14675 zig_panic("TODO elem ptr on a slice has a null pointer");
14488 }14676 }
14489 return result;14677 return result;
14490 } else if (array_type->id == ZigTypeIdArray) {14678 } else if (array_type->id == ZigTypeIdArray) {
...@@ -15171,74 +15359,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -15171,74 +15359,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
15171 }15359 }
15172}15360}
1517315361
15174static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {15362static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) {
15175 IrInstruction *ptr = load_ptr_instruction->ptr->child;15363 IrInstruction *ptr = instruction->ptr->child;
15176 if (type_is_invalid(ptr->value.type))
15177 return ira->codegen->invalid_instruction;
15178 return ir_get_deref(ira, &load_ptr_instruction->base, ptr);
15179}
15180
15181static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {
15182 IrInstruction *ptr = store_ptr_instruction->ptr->child;
15183 if (type_is_invalid(ptr->value.type))15364 if (type_is_invalid(ptr->value.type))
15184 return ira->codegen->invalid_instruction;15365 return ira->codegen->invalid_instruction;
1518515366
15186 IrInstruction *value = store_ptr_instruction->value->child;15367 IrInstruction *value = instruction->value->child;
15187 if (type_is_invalid(value->value.type))15368 if (type_is_invalid(value->value.type))
15188 return ira->codegen->invalid_instruction;15369 return ira->codegen->invalid_instruction;
1518915370
15190 if (ptr->value.type->id != ZigTypeIdPointer) {15371 return ir_analyze_store_ptr(ira, &instruction->base, ptr, value);
15191 ir_add_error(ira, ptr,15372}
15192 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
15193 return ira->codegen->invalid_instruction;
15194 }
15195
15196 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
15197 return ir_const_void(ira, &store_ptr_instruction->base);
15198 }
15199
15200 if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) {
15201 ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
15202 return ira->codegen->invalid_instruction;
15203 }
1520415373
15205 ZigType *child_type = ptr->value.type->data.pointer.child_type;15374static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {
15206 IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type);15375 IrInstruction *ptr = instruction->ptr->child;
15207 if (casted_value == ira->codegen->invalid_instruction)15376 if (type_is_invalid(ptr->value.type))
15208 return ira->codegen->invalid_instruction;15377 return ira->codegen->invalid_instruction;
1520915378 return ir_get_deref(ira, &instruction->base, ptr);
15210 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
15211 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
15212 ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
15213 return ira->codegen->invalid_instruction;
15214 }
15215 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
15216 if (instr_is_comptime(casted_value)) {
15217 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, store_ptr_instruction->base.source_node);
15218 if (dest_val == nullptr)
15219 return ira->codegen->invalid_instruction;
15220 if (dest_val->special != ConstValSpecialRuntime) {
15221 *dest_val = casted_value->value;
15222 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
15223 ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base;
15224 }
15225 return ir_const_void(ira, &store_ptr_instruction->base);
15226 }
15227 }
15228 ir_add_error(ira, &store_ptr_instruction->base,
15229 buf_sprintf("cannot store runtime value in compile time variable"));
15230 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
15231 dest_val->type = ira->codegen->builtin_types.entry_invalid;
15232
15233 return ira->codegen->invalid_instruction;
15234 }
15235 }
15236
15237 IrInstruction *result = ir_build_store_ptr(&ira->new_irb,
15238 store_ptr_instruction->base.scope, store_ptr_instruction->base.source_node,
15239 ptr, casted_value);
15240 result->value.type = ira->codegen->builtin_types.entry_void;
15241 return result;
15242}15379}
1524315380
15244static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {15381static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
...@@ -15709,11 +15846,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -15709,11 +15846,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
15709 zig_unreachable();15846 zig_unreachable();
15710}15847}
1571115848
15712static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {15849static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
15713 IrInstruction *value = instruction->value->child;
15714 if (type_is_invalid(value->value.type))
15715 return ira->codegen->invalid_instruction;
15716
15717 ZigType *type_entry = value->value.type;15850 ZigType *type_entry = value->value.type;
1571815851
15719 if (type_entry->id == ZigTypeIdOptional) {15852 if (type_entry->id == ZigTypeIdOptional) {
...@@ -15722,60 +15855,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns...@@ -15722,60 +15855,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
15722 if (!maybe_val)15855 if (!maybe_val)
15723 return ira->codegen->invalid_instruction;15856 return ira->codegen->invalid_instruction;
1572415857
15725 return ir_const_bool(ira, &instruction->base, !optional_value_is_null(maybe_val));15858 return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val));
15726 }15859 }
1572715860
15728 IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,15861 IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,
15729 instruction->base.scope, instruction->base.source_node, value);15862 source_inst->scope, source_inst->source_node, value);
15730 result->value.type = ira->codegen->builtin_types.entry_bool;15863 result->value.type = ira->codegen->builtin_types.entry_bool;
15731 return result;15864 return result;
15732 } else if (type_entry->id == ZigTypeIdNull) {15865 } else if (type_entry->id == ZigTypeIdNull) {
15733 return ir_const_bool(ira, &instruction->base, false);15866 return ir_const_bool(ira, source_inst, false);
15734 } else {15867 } else {
15735 return ir_const_bool(ira, &instruction->base, true);15868 return ir_const_bool(ira, source_inst, true);
15736 }15869 }
15737}15870}
1573815871
15739static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,15872static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
15740 IrInstructionUnwrapOptional *unwrap_maybe_instruction)15873 IrInstruction *value = instruction->value->child;
15741{
15742 IrInstruction *value = unwrap_maybe_instruction->value->child;
15743 if (type_is_invalid(value->value.type))15874 if (type_is_invalid(value->value.type))
15744 return ira->codegen->invalid_instruction;15875 return ira->codegen->invalid_instruction;
1574515876
15746 ZigType *ptr_type = value->value.type;15877 return ir_analyze_test_non_null(ira, &instruction->base, value);
15878}
15879
15880static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
15881 IrInstruction *base_ptr, bool safety_check_on)
15882{
15883 ZigType *ptr_type = base_ptr->value.type;
15747 assert(ptr_type->id == ZigTypeIdPointer);15884 assert(ptr_type->id == ZigTypeIdPointer);
1574815885
15749 ZigType *type_entry = ptr_type->data.pointer.child_type;15886 ZigType *type_entry = ptr_type->data.pointer.child_type;
15750 if (type_is_invalid(type_entry)) {15887 if (type_is_invalid(type_entry))
15751 return ira->codegen->invalid_instruction;15888 return ira->codegen->invalid_instruction;
15752 } else if (type_entry->id != ZigTypeIdOptional) {15889
15753 ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node,15890 if (type_entry->id != ZigTypeIdOptional) {
15891 ir_add_error_node(ira, base_ptr->source_node,
15754 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));15892 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
15755 return ira->codegen->invalid_instruction;15893 return ira->codegen->invalid_instruction;
15756 }15894 }
15895
15757 ZigType *child_type = type_entry->data.maybe.child_type;15896 ZigType *child_type = type_entry->data.maybe.child_type;
15758 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,15897 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
15759 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);15898 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
1576015899
15761 if (instr_is_comptime(value)) {15900 if (instr_is_comptime(base_ptr)) {
15762 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);15901 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
15763 if (!val)15902 if (!val)
15764 return ira->codegen->invalid_instruction;15903 return ira->codegen->invalid_instruction;
15765 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, unwrap_maybe_instruction->base.source_node);15904 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
15766 if (maybe_val == nullptr)15905 if (maybe_val == nullptr)
15767 return ira->codegen->invalid_instruction;15906 return ira->codegen->invalid_instruction;
1576815907
15769 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {15908 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
15770 if (optional_value_is_null(maybe_val)) {15909 if (optional_value_is_null(maybe_val)) {
15771 ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null"));15910 ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
15772 return ira->codegen->invalid_instruction;15911 return ira->codegen->invalid_instruction;
15773 }15912 }
15774 IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type);15913 IrInstruction *result = ir_const(ira, source_instr, result_type);
15775 ConstExprValue *out_val = &result->value;15914 ConstExprValue *out_val = &result->value;
15776 out_val->data.x_ptr.special = ConstPtrSpecialRef;15915 out_val->data.x_ptr.special = ConstPtrSpecialRef;
15777 out_val->data.x_ptr.mut = val->data.x_ptr.mut;15916 out_val->data.x_ptr.mut = val->data.x_ptr.mut;
15778 if (type_is_codegen_pointer(child_type)) {15917 if (types_have_same_zig_comptime_repr(type_entry, child_type)) {
15779 out_val->data.x_ptr.data.ref.pointee = maybe_val;15918 out_val->data.x_ptr.data.ref.pointee = maybe_val;
15780 } else {15919 } else {
15781 out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;15920 out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;
...@@ -15784,13 +15923,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,...@@ -15784,13 +15923,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
15784 }15923 }
15785 }15924 }
1578615925
15787 IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb,15926 IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
15788 unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node,15927 source_instr->source_node, base_ptr, safety_check_on);
15789 value, unwrap_maybe_instruction->safety_check_on);
15790 result->value.type = result_type;15928 result->value.type = result_type;
15791 return result;15929 return result;
15792}15930}
1579315931
15932static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
15933 IrInstructionOptionalUnwrapPtr *instruction)
15934{
15935 IrInstruction *base_ptr = instruction->base_ptr->child;
15936 if (type_is_invalid(base_ptr->value.type))
15937 return ira->codegen->invalid_instruction;
15938
15939 return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on);
15940}
15941
15794static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {15942static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
15795 IrInstruction *value = ctz_instruction->value->child;15943 IrInstruction *value = ctz_instruction->value->child;
15796 if (type_is_invalid(value->value.type)) {15944 if (type_is_invalid(value->value.type)) {
...@@ -16091,9 +16239,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16091,9 +16239,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16091 return result;16239 return result;
16092 }16240 }
1609316241
16094 IrInstruction *result = ir_build_load_ptr(&ira->new_irb,16242 IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
16095 switch_target_instruction->base.scope, switch_target_instruction->base.source_node,
16096 target_value_ptr);
16097 result->value.type = target_type;16243 result->value.type = target_type;
16098 return result;16244 return result;
16099 }16245 }
...@@ -16123,8 +16269,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16123,8 +16269,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16123 return result;16269 return result;
16124 }16270 }
1612516271
16126 IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,16272 IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
16127 switch_target_instruction->base.source_node, target_value_ptr);
16128 union_value->value.type = target_type;16273 union_value->value.type = target_type;
1612916274
16130 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,16275 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
...@@ -16148,8 +16293,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16148,8 +16293,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16148 return result;16293 return result;
16149 }16294 }
1615016295
16151 IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,16296 IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
16152 switch_target_instruction->base.source_node, target_value_ptr);
16153 enum_value->value.type = target_type;16297 enum_value->value.type = target_type;
16154 return enum_value;16298 return enum_value;
16155 }16299 }
...@@ -16306,7 +16450,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -16306,7 +16450,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
16306 Error err;16450 Error err;
16307 assert(container_type->id == ZigTypeIdUnion);16451 assert(container_type->id == ZigTypeIdUnion);
1630816452
16309 if ((err = ensure_complete_type(ira->codegen, container_type)))16453 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
16310 return ira->codegen->invalid_instruction;16454 return ira->codegen->invalid_instruction;
1631116455
16312 if (instr_field_count != 1) {16456 if (instr_field_count != 1) {
...@@ -16350,12 +16494,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -16350,12 +16494,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
16350 ConstExprValue *out_val = &result->value;16494 ConstExprValue *out_val = &result->value;
16351 out_val->data.x_union.payload = field_val;16495 out_val->data.x_union.payload = field_val;
16352 out_val->data.x_union.tag = type_field->enum_field->value;16496 out_val->data.x_union.tag = type_field->enum_field->value;
1635316497 out_val->parent.id = ConstParentIdUnion;
16354 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);16498 out_val->parent.data.p_union.union_val = out_val;
16355 if (parent != nullptr) {
16356 parent->id = ConstParentIdUnion;
16357 parent->data.p_union.union_val = out_val;
16358 }
1635916499
16360 return result;16500 return result;
16361 }16501 }
...@@ -16382,7 +16522,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16382,7 +16522,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
16382 return ira->codegen->invalid_instruction;16522 return ira->codegen->invalid_instruction;
16383 }16523 }
1638416524
16385 if ((err = ensure_complete_type(ira->codegen, container_type)))16525 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
16386 return ira->codegen->invalid_instruction;16526 return ira->codegen->invalid_instruction;
1638716527
16388 size_t actual_field_count = container_type->data.structure.src_field_count;16528 size_t actual_field_count = container_type->data.structure.src_field_count;
...@@ -16461,9 +16601,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16461,9 +16601,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
16461 if (const_val.special == ConstValSpecialStatic) {16601 if (const_val.special == ConstValSpecialStatic) {
16462 IrInstruction *result = ir_const(ira, instruction, nullptr);16602 IrInstruction *result = ir_const(ira, instruction, nullptr);
16463 ConstExprValue *out_val = &result->value;16603 ConstExprValue *out_val = &result->value;
16464 // TODO copy_const_val?16604 copy_const_val(out_val, &const_val, true);
16465 *out_val = const_val;16605 out_val->type = container_type;
16466 result->value.type = container_type;
1646716606
16468 for (size_t i = 0; i < instr_field_count; i += 1) {16607 for (size_t i = 0; i < instr_field_count; i += 1) {
16469 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];16608 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
...@@ -16495,127 +16634,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16495,127 +16634,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
16495static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,16634static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
16496 IrInstructionContainerInitList *instruction)16635 IrInstructionContainerInitList *instruction)
16497{16636{
16498 IrInstruction *container_type_value = instruction->container_type->child;16637 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
16499 if (type_is_invalid(container_type_value->value.type))16638 if (type_is_invalid(container_type))
16500 return ira->codegen->invalid_instruction;16639 return ira->codegen->invalid_instruction;
1650116640
16502 size_t elem_count = instruction->item_count;16641 size_t elem_count = instruction->item_count;
16503 if (container_type_value->value.type->id == ZigTypeIdMetaType) {
16504 ZigType *container_type = ir_resolve_type(ira, container_type_value);
16505 if (type_is_invalid(container_type))
16506 return ira->codegen->invalid_instruction;
1650716642
16508 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {16643 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
16509 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,16644 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
16510 0, nullptr);16645 0, nullptr);
16511 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {16646 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
16512 // array is same as slice init but we make a compile error if the length is wrong16647 // array is same as slice init but we make a compile error if the length is wrong
16513 ZigType *child_type;16648 ZigType *child_type;
16514 if (container_type->id == ZigTypeIdArray) {16649 if (container_type->id == ZigTypeIdArray) {
16515 child_type = container_type->data.array.child_type;16650 child_type = container_type->data.array.child_type;
16516 if (container_type->data.array.len != elem_count) {16651 if (container_type->data.array.len != elem_count) {
16517 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);16652 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
1651816653
16519 ir_add_error(ira, &instruction->base,16654 ir_add_error(ira, &instruction->base,
16520 buf_sprintf("expected %s literal, found %s literal",16655 buf_sprintf("expected %s literal, found %s literal",
16521 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));16656 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
16522 return ira->codegen->invalid_instruction;16657 return ira->codegen->invalid_instruction;
16523 }
16524 } else {
16525 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
16526 assert(pointer_type->id == ZigTypeIdPointer);
16527 child_type = pointer_type->data.pointer.child_type;
16528 }16658 }
16659 } else {
16660 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
16661 assert(pointer_type->id == ZigTypeIdPointer);
16662 child_type = pointer_type->data.pointer.child_type;
16663 }
1652916664
16530 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);16665 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
1653116666
16532 ConstExprValue const_val = {};16667 ConstExprValue const_val = {};
16533 const_val.special = ConstValSpecialStatic;16668 const_val.special = ConstValSpecialStatic;
16534 const_val.type = fixed_size_array_type;16669 const_val.type = fixed_size_array_type;
16535 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);16670 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
1653616671
16537 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);16672 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
1653816673
16539 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);16674 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
1654016675
16541 IrInstruction *first_non_const_instruction = nullptr;16676 IrInstruction *first_non_const_instruction = nullptr;
1654216677
16543 for (size_t i = 0; i < elem_count; i += 1) {16678 for (size_t i = 0; i < elem_count; i += 1) {
16544 IrInstruction *arg_value = instruction->items[i]->child;16679 IrInstruction *arg_value = instruction->items[i]->child;
16545 if (type_is_invalid(arg_value->value.type))16680 if (type_is_invalid(arg_value->value.type))
16546 return ira->codegen->invalid_instruction;16681 return ira->codegen->invalid_instruction;
1654716682
16548 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);16683 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
16549 if (casted_arg == ira->codegen->invalid_instruction)16684 if (casted_arg == ira->codegen->invalid_instruction)
16550 return ira->codegen->invalid_instruction;16685 return ira->codegen->invalid_instruction;
1655116686
16552 new_items[i] = casted_arg;16687 new_items[i] = casted_arg;
1655316688
16554 if (const_val.special == ConstValSpecialStatic) {16689 if (const_val.special == ConstValSpecialStatic) {
16555 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {16690 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
16556 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);16691 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
16557 if (!elem_val)16692 if (!elem_val)
16558 return ira->codegen->invalid_instruction;16693 return ira->codegen->invalid_instruction;
1655916694
16560 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);16695 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
16561 } else {16696 } else {
16562 first_non_const_instruction = casted_arg;16697 first_non_const_instruction = casted_arg;
16563 const_val.special = ConstValSpecialRuntime;16698 const_val.special = ConstValSpecialRuntime;
16564 }
16565 }16699 }
16566 }16700 }
16701 }
1656716702
16568 if (const_val.special == ConstValSpecialStatic) {16703 if (const_val.special == ConstValSpecialStatic) {
16569 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);16704 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
16570 ConstExprValue *out_val = &result->value;16705 ConstExprValue *out_val = &result->value;
16571 // TODO copy_const_val?16706 copy_const_val(out_val, &const_val, true);
16572 *out_val = const_val;16707 result->value.type = fixed_size_array_type;
16573 result->value.type = fixed_size_array_type;16708 for (size_t i = 0; i < elem_count; i += 1) {
16574 for (size_t i = 0; i < elem_count; i += 1) {16709 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
16575 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];16710 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
16576 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);16711 if (parent != nullptr) {
16577 if (parent != nullptr) {16712 parent->id = ConstParentIdArray;
16578 parent->id = ConstParentIdArray;16713 parent->data.p_array.array_val = out_val;
16579 parent->data.p_array.array_val = out_val;16714 parent->data.p_array.elem_index = i;
16580 parent->data.p_array.elem_index = i;
16581 }
16582 }16715 }
16583 return result;
16584 }16716 }
16717 return result;
16718 }
1658516719
16586 if (is_comptime) {16720 if (is_comptime) {
16587 ir_add_error_node(ira, first_non_const_instruction->source_node,16721 ir_add_error_node(ira, first_non_const_instruction->source_node,
16588 buf_sprintf("unable to evaluate constant expression"));16722 buf_sprintf("unable to evaluate constant expression"));
16589 return ira->codegen->invalid_instruction;16723 return ira->codegen->invalid_instruction;
16590 }16724 }
1659116725
16592 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,16726 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
16593 instruction->base.scope, instruction->base.source_node,16727 instruction->base.scope, instruction->base.source_node,
16594 container_type_value, elem_count, new_items);16728 nullptr, elem_count, new_items);
16595 new_instruction->value.type = fixed_size_array_type;16729 new_instruction->value.type = fixed_size_array_type;
16596 ir_add_alloca(ira, new_instruction, fixed_size_array_type);16730 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
16597 return new_instruction;16731 return new_instruction;
16598 } else if (container_type->id == ZigTypeIdVoid) {16732 } else if (container_type->id == ZigTypeIdVoid) {
16599 if (elem_count != 0) {16733 if (elem_count != 0) {
16600 ir_add_error_node(ira, instruction->base.source_node,
16601 buf_sprintf("void expression expects no arguments"));
16602 return ira->codegen->invalid_instruction;
16603 }
16604 return ir_const_void(ira, &instruction->base);
16605 } else {
16606 ir_add_error_node(ira, instruction->base.source_node,16734 ir_add_error_node(ira, instruction->base.source_node,
16607 buf_sprintf("type '%s' does not support array initialization",16735 buf_sprintf("void expression expects no arguments"));
16608 buf_ptr(&container_type->name)));
16609 return ira->codegen->invalid_instruction;16736 return ira->codegen->invalid_instruction;
16610 }16737 }
16738 return ir_const_void(ira, &instruction->base);
16611 } else {16739 } else {
16612 ir_add_error(ira, container_type_value,16740 ir_add_error_node(ira, instruction->base.source_node,
16613 buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name)));16741 buf_sprintf("type '%s' does not support array initialization",
16742 buf_ptr(&container_type->name)));
16614 return ira->codegen->invalid_instruction;16743 return ira->codegen->invalid_instruction;
16615 }16744 }
16616}16745}
1661716746
16618static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {16747static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
16748 IrInstructionContainerInitFields *instruction)
16749{
16619 IrInstruction *container_type_value = instruction->container_type->child;16750 IrInstruction *container_type_value = instruction->container_type->child;
16620 ZigType *container_type = ir_resolve_type(ira, container_type_value);16751 ZigType *container_type = ir_resolve_type(ira, container_type_value);
16621 if (type_is_invalid(container_type))16752 if (type_is_invalid(container_type))
...@@ -16675,7 +16806,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct...@@ -16675,7 +16806,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
16675 if (type_is_invalid(value->value.type))16806 if (type_is_invalid(value->value.type))
16676 return ira->codegen->invalid_instruction;16807 return ira->codegen->invalid_instruction;
1667716808
16678 IrInstruction *casted_value = ir_implicit_cast(ira, value, value->value.type);16809 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set);
16679 if (type_is_invalid(casted_value->value.type))16810 if (type_is_invalid(casted_value->value.type))
16680 return ira->codegen->invalid_instruction;16811 return ira->codegen->invalid_instruction;
1668116812
...@@ -16936,10 +17067,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig...@@ -16936,10 +17067,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
1693617067
16937 ZigVar *var = tld->var;17068 ZigVar *var = tld->var;
1693817069
16939 if ((err = ensure_complete_type(ira->codegen, var->value->type)))17070 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
16940 return ira->codegen->builtin_types.entry_invalid;17071 return ira->codegen->builtin_types.entry_invalid;
16941 assert(var->value->type->id == ZigTypeIdMetaType);17072
16942 return var->value->data.x_type;17073 assert(var->const_value->type->id == ZigTypeIdMetaType);
17074 return var->const_value->data.x_type;
16943}17075}
1694417076
16945static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) {17077static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) {
...@@ -16994,7 +17126,6 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -16994,7 +17126,6 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
16994 definition_array->special = ConstValSpecialStatic;17126 definition_array->special = ConstValSpecialStatic;
16995 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);17127 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);
16996 definition_array->data.x_array.special = ConstArraySpecialNone;17128 definition_array->data.x_array.special = ConstArraySpecialNone;
16997 definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
16998 definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);17129 definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);
16999 init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);17130 init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);
1700017131
...@@ -17025,33 +17156,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17025,33 +17156,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17025 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;17156 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;
17026 inner_fields[2].special = ConstValSpecialStatic;17157 inner_fields[2].special = ConstValSpecialStatic;
17027 inner_fields[2].type = type_info_definition_data_type;17158 inner_fields[2].type = type_info_definition_data_type;
17028 inner_fields[2].data.x_union.parent.id = ConstParentIdStruct;17159 inner_fields[2].parent.id = ConstParentIdStruct;
17029 inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val;17160 inner_fields[2].parent.data.p_struct.struct_val = definition_val;
17030 inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1;17161 inner_fields[2].parent.data.p_struct.field_index = 1;
1703117162
17032 switch (curr_entry->value->id) {17163 switch (curr_entry->value->id) {
17033 case TldIdVar:17164 case TldIdVar:
17034 {17165 {
17035 ZigVar *var = ((TldVar *)curr_entry->value)->var;17166 ZigVar *var = ((TldVar *)curr_entry->value)->var;
17036 if ((err = ensure_complete_type(ira->codegen, var->value->type)))17167 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
17037 return ErrorSemanticAnalyzeFail;17168 return ErrorSemanticAnalyzeFail;
1703817169
17039 if (var->value->type->id == ZigTypeIdMetaType)17170 if (var->const_value->type->id == ZigTypeIdMetaType) {
17040 {
17041 // We have a variable of type 'type', so it's actually a type definition.17171 // We have a variable of type 'type', so it's actually a type definition.
17042 // 0: Data.Type: type17172 // 0: Data.Type: type
17043 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);17173 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
17044 inner_fields[2].data.x_union.payload = var->value;17174 inner_fields[2].data.x_union.payload = var->const_value;
17045 }17175 } else {
17046 else
17047 {
17048 // We have a variable of another type, so we store the type of the variable.17176 // We have a variable of another type, so we store the type of the variable.
17049 // 1: Data.Var: type17177 // 1: Data.Var: type
17050 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);17178 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);
1705117179
17052 ConstExprValue *payload = create_const_vals(1);17180 ConstExprValue *payload = create_const_vals(1);
17053 payload->type = ira->codegen->builtin_types.entry_type;17181 payload->type = ira->codegen->builtin_types.entry_type;
17054 payload->data.x_type = var->value->type;17182 payload->data.x_type = var->const_value->type;
1705517183
17056 inner_fields[2].data.x_union.payload = payload;17184 inner_fields[2].data.x_union.payload = payload;
17057 }17185 }
...@@ -17071,8 +17199,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17071,8 +17199,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17071 ConstExprValue *fn_def_val = create_const_vals(1);17199 ConstExprValue *fn_def_val = create_const_vals(1);
17072 fn_def_val->special = ConstValSpecialStatic;17200 fn_def_val->special = ConstValSpecialStatic;
17073 fn_def_val->type = type_info_fn_def_type;17201 fn_def_val->type = type_info_fn_def_type;
17074 fn_def_val->data.x_struct.parent.id = ConstParentIdUnion;17202 fn_def_val->parent.id = ConstParentIdUnion;
17075 fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2];17203 fn_def_val->parent.data.p_union.union_val = &inner_fields[2];
1707617204
17077 ConstExprValue *fn_def_fields = create_const_vals(9);17205 ConstExprValue *fn_def_fields = create_const_vals(9);
17078 fn_def_val->data.x_struct.fields = fn_def_fields;17206 fn_def_val->data.x_struct.fields = fn_def_fields;
...@@ -17136,20 +17264,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17136,20 +17264,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17136 fn_arg_name_array->type = get_array_type(ira->codegen,17264 fn_arg_name_array->type = get_array_type(ira->codegen,
17137 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);17265 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);
17138 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;17266 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
17139 fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17140 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);17267 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1714117268
17142 init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);17269 init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);
1714317270
17144 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++)17271 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
17145 {
17146 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);17272 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
17147 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];17273 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
17148 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);17274 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);
17149 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true);17275 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true);
17150 fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray;17276 fn_arg_name_val->parent.id = ConstParentIdArray;
17151 fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array;17277 fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;
17152 fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;17278 fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index;
17153 }17279 }
1715417280
17155 inner_fields[2].data.x_union.payload = fn_def_val;17281 inner_fields[2].data.x_union.payload = fn_def_val;
...@@ -17442,7 +17568,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17442,7 +17568,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17442 enum_field_array->special = ConstValSpecialStatic;17568 enum_field_array->special = ConstValSpecialStatic;
17443 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);17569 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);
17444 enum_field_array->data.x_array.special = ConstArraySpecialNone;17570 enum_field_array->data.x_array.special = ConstArraySpecialNone;
17445 enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17446 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);17571 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
1744717572
17448 init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false);17573 init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false);
...@@ -17452,9 +17577,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17452,9 +17577,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17452 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];17577 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
17453 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];17578 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];
17454 make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);17579 make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);
17455 enum_field_val->data.x_struct.parent.id = ConstParentIdArray;17580 enum_field_val->parent.id = ConstParentIdArray;
17456 enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array;17581 enum_field_val->parent.data.p_array.array_val = enum_field_array;
17457 enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index;17582 enum_field_val->parent.data.p_array.elem_index = enum_field_index;
17458 }17583 }
17459 // defs: []TypeInfo.Definition17584 // defs: []TypeInfo.Definition
17460 ensure_field_index(result->type, "defs", 3);17585 ensure_field_index(result->type, "defs", 3);
...@@ -17481,7 +17606,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17481,7 +17606,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17481 error_array->special = ConstValSpecialStatic;17606 error_array->special = ConstValSpecialStatic;
17482 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);17607 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);
17483 error_array->data.x_array.special = ConstArraySpecialNone;17608 error_array->data.x_array.special = ConstArraySpecialNone;
17484 error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17485 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);17609 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
1748617610
17487 init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);17611 init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);
...@@ -17505,9 +17629,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17505,9 +17629,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17505 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);17629 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);
1750617630
17507 error_val->data.x_struct.fields = inner_fields;17631 error_val->data.x_struct.fields = inner_fields;
17508 error_val->data.x_struct.parent.id = ConstParentIdArray;17632 error_val->parent.id = ConstParentIdArray;
17509 error_val->data.x_struct.parent.data.p_array.array_val = error_array;17633 error_val->parent.data.p_array.array_val = error_array;
17510 error_val->data.x_struct.parent.data.p_array.elem_index = error_index;17634 error_val->parent.data.p_array.elem_index = error_index;
17511 }17635 }
1751217636
17513 break;17637 break;
...@@ -17576,7 +17700,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17576,7 +17700,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17576 union_field_array->special = ConstValSpecialStatic;17700 union_field_array->special = ConstValSpecialStatic;
17577 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);17701 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);
17578 union_field_array->data.x_array.special = ConstArraySpecialNone;17702 union_field_array->data.x_array.special = ConstArraySpecialNone;
17579 union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17580 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);17703 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
1758117704
17582 init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false);17705 init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false);
...@@ -17609,9 +17732,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17609,9 +17732,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17609 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);17732 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);
1761017733
17611 union_field_val->data.x_struct.fields = inner_fields;17734 union_field_val->data.x_struct.fields = inner_fields;
17612 union_field_val->data.x_struct.parent.id = ConstParentIdArray;17735 union_field_val->parent.id = ConstParentIdArray;
17613 union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array;17736 union_field_val->parent.data.p_array.array_val = union_field_array;
17614 union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index;17737 union_field_val->parent.data.p_array.elem_index = union_field_index;
17615 }17738 }
17616 // defs: []TypeInfo.Definition17739 // defs: []TypeInfo.Definition
17617 ensure_field_index(result->type, "defs", 3);17740 ensure_field_index(result->type, "defs", 3);
...@@ -17651,7 +17774,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17651,7 +17774,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17651 struct_field_array->special = ConstValSpecialStatic;17774 struct_field_array->special = ConstValSpecialStatic;
17652 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);17775 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);
17653 struct_field_array->data.x_array.special = ConstArraySpecialNone;17776 struct_field_array->data.x_array.special = ConstArraySpecialNone;
17654 struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17655 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);17777 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
1765617778
17657 init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false);17779 init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false);
...@@ -17685,9 +17807,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17685,9 +17807,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17685 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);17807 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);
1768617808
17687 struct_field_val->data.x_struct.fields = inner_fields;17809 struct_field_val->data.x_struct.fields = inner_fields;
17688 struct_field_val->data.x_struct.parent.id = ConstParentIdArray;17810 struct_field_val->parent.id = ConstParentIdArray;
17689 struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array;17811 struct_field_val->parent.data.p_array.array_val = struct_field_array;
17690 struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index;17812 struct_field_val->parent.data.p_array.elem_index = struct_field_index;
17691 }17813 }
17692 // defs: []TypeInfo.Definition17814 // defs: []TypeInfo.Definition
17693 ensure_field_index(result->type, "defs", 2);17815 ensure_field_index(result->type, "defs", 2);
...@@ -17757,7 +17879,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17757,7 +17879,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17757 fn_arg_array->special = ConstValSpecialStatic;17879 fn_arg_array->special = ConstValSpecialStatic;
17758 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);17880 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);
17759 fn_arg_array->data.x_array.special = ConstArraySpecialNone;17881 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
17760 fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17761 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);17882 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1776217883
17763 init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false);17884 init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false);
...@@ -17794,9 +17915,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17794,9 +17915,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17794 }17915 }
1779517916
17796 fn_arg_val->data.x_struct.fields = inner_fields;17917 fn_arg_val->data.x_struct.fields = inner_fields;
17797 fn_arg_val->data.x_struct.parent.id = ConstParentIdArray;17918 fn_arg_val->parent.id = ConstParentIdArray;
17798 fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array;17919 fn_arg_val->parent.data.p_array.array_val = fn_arg_array;
17799 fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;17920 fn_arg_val->parent.data.p_array.elem_index = fn_arg_index;
17800 }17921 }
1780117922
17802 break;17923 break;
...@@ -17840,8 +17961,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,...@@ -17840,8 +17961,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
1784017961
17841 if (payload != nullptr) {17962 if (payload != nullptr) {
17842 assert(payload->type->id == ZigTypeIdStruct);17963 assert(payload->type->id == ZigTypeIdStruct);
17843 payload->data.x_struct.parent.id = ConstParentIdUnion;17964 payload->parent.id = ConstParentIdUnion;
17844 payload->data.x_struct.parent.data.p_union.union_val = out_val;17965 payload->parent.data.p_union.union_val = out_val;
17845 }17966 }
1784617967
17847 return result;17968 return result;
...@@ -17913,10 +18034,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -17913,10 +18034,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1791318034
17914 // Execute the C import block like an inline function18035 // Execute the C import block like an inline function
17915 ZigType *void_type = ira->codegen->builtin_types.entry_void;18036 ZigType *void_type = ira->codegen->builtin_types.entry_void;
17916 IrInstruction *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,18037 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
17917 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,18038 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
17918 &cimport_scope->buf, block_node, nullptr, nullptr);18039 &cimport_scope->buf, block_node, nullptr, nullptr);
17919 if (type_is_invalid(cimport_result->value.type))18040 if (type_is_invalid(cimport_result->type))
17920 return ira->codegen->invalid_instruction;18041 return ira->codegen->invalid_instruction;
1792118042
17922 find_libc_include_path(ira->codegen);18043 find_libc_include_path(ira->codegen);
...@@ -18066,7 +18187,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru...@@ -18066,7 +18187,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
18066 return result;18187 return result;
18067}18188}
1806818189
18069static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {18190static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) {
18070 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);18191 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
18071 if (type_is_invalid(operand_type))18192 if (type_is_invalid(operand_type))
18072 return ira->codegen->invalid_instruction;18193 return ira->codegen->invalid_instruction;
...@@ -18138,9 +18259,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi...@@ -18138,9 +18259,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
18138 zig_panic("TODO compile-time execution of cmpxchg");18259 zig_panic("TODO compile-time execution of cmpxchg");
18139 }18260 }
1814018261
18141 IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node,18262 IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
18142 nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak,18263 casted_ptr, casted_cmp_value, casted_new_value,
18143 operand_type, success_order, failure_order);18264 success_order, failure_order, instruction->is_weak);
18144 result->value.type = get_optional_type(ira->codegen, operand_type);18265 result->value.type = get_optional_type(ira->codegen, operand_type);
18145 ir_add_alloca(ira, result, result->value.type);18266 ir_add_alloca(ira, result, result->value.type);
18146 return result;18267 return result;
...@@ -18312,18 +18433,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst...@@ -18312,18 +18433,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst
18312 return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);18433 return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
18313}18434}
1831418435
18315static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
18316 Error err;
18317
18318 if (ty->id == ZigTypeIdPointer) {
18319 if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown)))
18320 return err;
18321 }
18322
18323 *result_align = get_ptr_align(ira->codegen, ty);
18324 return ErrorNone;
18325}
18326
18327static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {18436static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
18328 Error err;18437 Error err;
1832918438
...@@ -18442,6 +18551,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct...@@ -18442,6 +18551,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
18442 return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);18551 return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
18443}18552}
1844418553
18554static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
18555 Error err;
18556
18557 ZigType *ptr_type = get_src_ptr_type(ty);
18558 assert(ptr_type != nullptr);
18559 if (ptr_type->id == ZigTypeIdPointer) {
18560 if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
18561 return err;
18562 }
18563
18564 *result_align = get_ptr_align(ira->codegen, ty);
18565 return ErrorNone;
18566}
18567
18445static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {18568static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
18446 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);18569 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
18447 if (type_is_invalid(dest_type))18570 if (type_is_invalid(dest_type))
...@@ -18646,10 +18769,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio...@@ -18646,10 +18769,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
18646 }18769 }
18647 case ConstPtrSpecialBaseStruct:18770 case ConstPtrSpecialBaseStruct:
18648 zig_panic("TODO memset on const inner struct");18771 zig_panic("TODO memset on const inner struct");
18772 case ConstPtrSpecialBaseErrorUnionCode:
18773 zig_panic("TODO memset on const inner error union code");
18774 case ConstPtrSpecialBaseErrorUnionPayload:
18775 zig_panic("TODO memset on const inner error union payload");
18776 case ConstPtrSpecialBaseOptionalPayload:
18777 zig_panic("TODO memset on const inner optional payload");
18649 case ConstPtrSpecialHardCodedAddr:18778 case ConstPtrSpecialHardCodedAddr:
18650 zig_unreachable();18779 zig_unreachable();
18651 case ConstPtrSpecialFunction:18780 case ConstPtrSpecialFunction:
18652 zig_panic("TODO memset on ptr cast from function");18781 zig_panic("TODO memset on ptr cast from function");
18782 case ConstPtrSpecialNull:
18783 zig_panic("TODO memset on null ptr");
18653 }18784 }
1865418785
18655 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);18786 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);
...@@ -18761,10 +18892,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -18761,10 +18892,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
18761 }18892 }
18762 case ConstPtrSpecialBaseStruct:18893 case ConstPtrSpecialBaseStruct:
18763 zig_panic("TODO memcpy on const inner struct");18894 zig_panic("TODO memcpy on const inner struct");
18895 case ConstPtrSpecialBaseErrorUnionCode:
18896 zig_panic("TODO memcpy on const inner error union code");
18897 case ConstPtrSpecialBaseErrorUnionPayload:
18898 zig_panic("TODO memcpy on const inner error union payload");
18899 case ConstPtrSpecialBaseOptionalPayload:
18900 zig_panic("TODO memcpy on const inner optional payload");
18764 case ConstPtrSpecialHardCodedAddr:18901 case ConstPtrSpecialHardCodedAddr:
18765 zig_unreachable();18902 zig_unreachable();
18766 case ConstPtrSpecialFunction:18903 case ConstPtrSpecialFunction:
18767 zig_panic("TODO memcpy on ptr cast from function");18904 zig_panic("TODO memcpy on ptr cast from function");
18905 case ConstPtrSpecialNull:
18906 zig_panic("TODO memcpy on null ptr");
18768 }18907 }
1876918908
18770 if (dest_start + count > dest_end) {18909 if (dest_start + count > dest_end) {
...@@ -18797,10 +18936,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -18797,10 +18936,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
18797 }18936 }
18798 case ConstPtrSpecialBaseStruct:18937 case ConstPtrSpecialBaseStruct:
18799 zig_panic("TODO memcpy on const inner struct");18938 zig_panic("TODO memcpy on const inner struct");
18939 case ConstPtrSpecialBaseErrorUnionCode:
18940 zig_panic("TODO memcpy on const inner error union code");
18941 case ConstPtrSpecialBaseErrorUnionPayload:
18942 zig_panic("TODO memcpy on const inner error union payload");
18943 case ConstPtrSpecialBaseOptionalPayload:
18944 zig_panic("TODO memcpy on const inner optional payload");
18800 case ConstPtrSpecialHardCodedAddr:18945 case ConstPtrSpecialHardCodedAddr:
18801 zig_unreachable();18946 zig_unreachable();
18802 case ConstPtrSpecialFunction:18947 case ConstPtrSpecialFunction:
18803 zig_panic("TODO memcpy on ptr cast from function");18948 zig_panic("TODO memcpy on ptr cast from function");
18949 case ConstPtrSpecialNull:
18950 zig_panic("TODO memcpy on null ptr");
18804 }18951 }
1880518952
18806 if (src_start + count > src_end) {18953 if (src_start + count > src_end) {
...@@ -18828,9 +18975,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18828,9 +18975,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18828 if (type_is_invalid(ptr_ptr->value.type))18975 if (type_is_invalid(ptr_ptr->value.type))
18829 return ira->codegen->invalid_instruction;18976 return ira->codegen->invalid_instruction;
1883018977
18831 ZigType *ptr_type = ptr_ptr->value.type;18978 ZigType *ptr_ptr_type = ptr_ptr->value.type;
18832 assert(ptr_type->id == ZigTypeIdPointer);18979 assert(ptr_ptr_type->id == ZigTypeIdPointer);
18833 ZigType *array_type = ptr_type->data.pointer.child_type;18980 ZigType *array_type = ptr_ptr_type->data.pointer.child_type;
1883418981
18835 IrInstruction *start = instruction->start->child;18982 IrInstruction *start = instruction->start->child;
18836 if (type_is_invalid(start->value.type))18983 if (type_is_invalid(start->value.type))
...@@ -18859,10 +19006,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18859,10 +19006,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18859 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&19006 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
18860 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;19007 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
18861 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,19008 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,
18862 ptr_type->data.pointer.is_const || is_comptime_const,19009 ptr_ptr_type->data.pointer.is_const || is_comptime_const,
18863 ptr_type->data.pointer.is_volatile,19010 ptr_ptr_type->data.pointer.is_volatile,
18864 PtrLenUnknown,19011 PtrLenUnknown,
18865 ptr_type->data.pointer.explicit_alignment, 0, 0);19012 ptr_ptr_type->data.pointer.explicit_alignment, 0, 0);
18866 return_type = get_slice_type(ira->codegen, slice_ptr_type);19013 return_type = get_slice_type(ira->codegen, slice_ptr_type);
18867 } else if (array_type->id == ZigTypeIdPointer) {19014 } else if (array_type->id == ZigTypeIdPointer) {
18868 if (array_type->data.pointer.ptr_len == PtrLenSingle) {19015 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
...@@ -18960,6 +19107,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18960,6 +19107,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18960 break;19107 break;
18961 case ConstPtrSpecialBaseStruct:19108 case ConstPtrSpecialBaseStruct:
18962 zig_panic("TODO slice const inner struct");19109 zig_panic("TODO slice const inner struct");
19110 case ConstPtrSpecialBaseErrorUnionCode:
19111 zig_panic("TODO slice const inner error union code");
19112 case ConstPtrSpecialBaseErrorUnionPayload:
19113 zig_panic("TODO slice const inner error union payload");
19114 case ConstPtrSpecialBaseOptionalPayload:
19115 zig_panic("TODO slice const inner optional payload");
18963 case ConstPtrSpecialHardCodedAddr:19116 case ConstPtrSpecialHardCodedAddr:
18964 array_val = nullptr;19117 array_val = nullptr;
18965 abs_offset = 0;19118 abs_offset = 0;
...@@ -18967,6 +19120,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18967,6 +19120,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18967 break;19120 break;
18968 case ConstPtrSpecialFunction:19121 case ConstPtrSpecialFunction:
18969 zig_panic("TODO slice of ptr cast from function");19122 zig_panic("TODO slice of ptr cast from function");
19123 case ConstPtrSpecialNull:
19124 zig_panic("TODO slice of null ptr");
18970 }19125 }
18971 } else if (is_slice(array_type)) {19126 } else if (is_slice(array_type)) {
18972 ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);19127 ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
...@@ -18997,6 +19152,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18997,6 +19152,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18997 break;19152 break;
18998 case ConstPtrSpecialBaseStruct:19153 case ConstPtrSpecialBaseStruct:
18999 zig_panic("TODO slice const inner struct");19154 zig_panic("TODO slice const inner struct");
19155 case ConstPtrSpecialBaseErrorUnionCode:
19156 zig_panic("TODO slice const inner error union code");
19157 case ConstPtrSpecialBaseErrorUnionPayload:
19158 zig_panic("TODO slice const inner error union payload");
19159 case ConstPtrSpecialBaseOptionalPayload:
19160 zig_panic("TODO slice const inner optional payload");
19000 case ConstPtrSpecialHardCodedAddr:19161 case ConstPtrSpecialHardCodedAddr:
19001 array_val = nullptr;19162 array_val = nullptr;
19002 abs_offset = 0;19163 abs_offset = 0;
...@@ -19004,6 +19165,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -19004,6 +19165,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
19004 break;19165 break;
19005 case ConstPtrSpecialFunction:19166 case ConstPtrSpecialFunction:
19006 zig_panic("TODO slice of slice cast from function");19167 zig_panic("TODO slice of slice cast from function");
19168 case ConstPtrSpecialNull:
19169 zig_panic("TODO slice of null");
19007 }19170 }
19008 } else {19171 } else {
19009 zig_unreachable();19172 zig_unreachable();
...@@ -19069,6 +19232,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -19069,6 +19232,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
19069 zig_unreachable();19232 zig_unreachable();
19070 case ConstPtrSpecialBaseStruct:19233 case ConstPtrSpecialBaseStruct:
19071 zig_panic("TODO");19234 zig_panic("TODO");
19235 case ConstPtrSpecialBaseErrorUnionCode:
19236 zig_panic("TODO");
19237 case ConstPtrSpecialBaseErrorUnionPayload:
19238 zig_panic("TODO");
19239 case ConstPtrSpecialBaseOptionalPayload:
19240 zig_panic("TODO");
19072 case ConstPtrSpecialHardCodedAddr:19241 case ConstPtrSpecialHardCodedAddr:
19073 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,19242 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
19074 parent_ptr->type->data.pointer.child_type,19243 parent_ptr->type->data.pointer.child_type,
...@@ -19077,6 +19246,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -19077,6 +19246,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
19077 break;19246 break;
19078 case ConstPtrSpecialFunction:19247 case ConstPtrSpecialFunction:
19079 zig_panic("TODO");19248 zig_panic("TODO");
19249 case ConstPtrSpecialNull:
19250 zig_panic("TODO");
19080 }19251 }
1908119252
19082 ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];19253 ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];
...@@ -19432,7 +19603,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct...@@ -19432,7 +19603,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
19432 return ira->codegen->invalid_instruction;19603 return ira->codegen->invalid_instruction;
1943319604
19434 if (err_union_val->special != ConstValSpecialRuntime) {19605 if (err_union_val->special != ConstValSpecialRuntime) {
19435 return ir_const_bool(ira, &instruction->base, (err_union_val->data.x_err_union.err != nullptr));19606 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
19607 return ir_const_bool(ira, &instruction->base, (err != nullptr));
19436 }19608 }
19437 }19609 }
1943819610
...@@ -19458,48 +19630,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct...@@ -19458,48 +19630,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
19458 }19630 }
19459}19631}
1946019632
19461static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,19633static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
19462 IrInstructionUnwrapErrCode *instruction)19634 IrInstruction *base_ptr = instruction->err_union->child;
19463{19635 if (type_is_invalid(base_ptr->value.type))
19464 IrInstruction *value = instruction->value->child;
19465 if (type_is_invalid(value->value.type))
19466 return ira->codegen->invalid_instruction;19636 return ira->codegen->invalid_instruction;
19467 ZigType *ptr_type = value->value.type;19637 ZigType *ptr_type = base_ptr->value.type;
1946819638
19469 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.19639 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
19470 assert(ptr_type->id == ZigTypeIdPointer);19640 assert(ptr_type->id == ZigTypeIdPointer);
1947119641
19472 ZigType *type_entry = ptr_type->data.pointer.child_type;19642 ZigType *type_entry = ptr_type->data.pointer.child_type;
19473 if (type_is_invalid(type_entry)) {19643 if (type_is_invalid(type_entry))
19474 return ira->codegen->invalid_instruction;19644 return ira->codegen->invalid_instruction;
19475 } else if (type_entry->id == ZigTypeIdErrorUnion) {
19476 if (instr_is_comptime(value)) {
19477 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19478 if (!ptr_val)
19479 return ira->codegen->invalid_instruction;
19480 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19481 if (err_union_val == nullptr)
19482 return ira->codegen->invalid_instruction;
19483 if (err_union_val->special != ConstValSpecialRuntime) {
19484 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
19485 assert(err);
19486
19487 IrInstruction *result = ir_const(ira, &instruction->base,
19488 type_entry->data.error_union.err_set_type);
19489 result->value.data.x_err_set = err;
19490 return result;
19491 }
19492 }
1949319645
19494 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,19646 if (type_entry->id != ZigTypeIdErrorUnion) {
19495 instruction->base.scope, instruction->base.source_node, value);19647 ir_add_error(ira, base_ptr,
19496 result->value.type = type_entry->data.error_union.err_set_type;
19497 return result;
19498 } else {
19499 ir_add_error(ira, value,
19500 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));19648 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
19501 return ira->codegen->invalid_instruction;19649 return ira->codegen->invalid_instruction;
19502 }19650 }
19651
19652 if (instr_is_comptime(base_ptr)) {
19653 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
19654 if (!ptr_val)
19655 return ira->codegen->invalid_instruction;
19656 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19657 if (err_union_val == nullptr)
19658 return ira->codegen->invalid_instruction;
19659 if (err_union_val->special != ConstValSpecialRuntime) {
19660 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
19661 assert(err);
19662
19663 IrInstruction *result = ir_const(ira, &instruction->base,
19664 type_entry->data.error_union.err_set_type);
19665 result->value.data.x_err_set = err;
19666 return result;
19667 }
19668 }
19669
19670 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
19671 instruction->base.scope, instruction->base.source_node, base_ptr);
19672 result->value.type = type_entry->data.error_union.err_set_type;
19673 return result;
19503}19674}
1950419675
19505static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,19676static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
...@@ -19515,48 +19686,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -19515,48 +19686,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
19515 assert(ptr_type->id == ZigTypeIdPointer);19686 assert(ptr_type->id == ZigTypeIdPointer);
1951619687
19517 ZigType *type_entry = ptr_type->data.pointer.child_type;19688 ZigType *type_entry = ptr_type->data.pointer.child_type;
19518 if (type_is_invalid(type_entry)) {19689 if (type_is_invalid(type_entry))
19519 return ira->codegen->invalid_instruction;19690 return ira->codegen->invalid_instruction;
19520 } else if (type_entry->id == ZigTypeIdErrorUnion) {
19521 ZigType *payload_type = type_entry->data.error_union.payload_type;
19522 if (type_is_invalid(payload_type)) {
19523 return ira->codegen->invalid_instruction;
19524 }
19525 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
19526 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
19527 PtrLenSingle, 0, 0, 0);
19528 if (instr_is_comptime(value)) {
19529 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19530 if (!ptr_val)
19531 return ira->codegen->invalid_instruction;
19532 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19533 if (err_union_val == nullptr)
19534 return ira->codegen->invalid_instruction;
19535 if (err_union_val->special != ConstValSpecialRuntime) {
19536 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
19537 if (err != nullptr) {
19538 ir_add_error(ira, &instruction->base,
19539 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
19540 return ira->codegen->invalid_instruction;
19541 }
1954219691
19543 IrInstruction *result = ir_const(ira, &instruction->base, result_type);19692 if (type_entry->id != ZigTypeIdErrorUnion) {
19544 result->value.data.x_ptr.special = ConstPtrSpecialRef;
19545 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
19546 return result;
19547 }
19548 }
19549
19550 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
19551 instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
19552 result->value.type = result_type;
19553 return result;
19554 } else {
19555 ir_add_error(ira, value,19693 ir_add_error(ira, value,
19556 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));19694 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
19557 return ira->codegen->invalid_instruction;19695 return ira->codegen->invalid_instruction;
19558 }19696 }
1955919697
19698 ZigType *payload_type = type_entry->data.error_union.payload_type;
19699 if (type_is_invalid(payload_type))
19700 return ira->codegen->invalid_instruction;
19701
19702 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
19703 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
19704 PtrLenSingle, 0, 0, 0);
19705 if (instr_is_comptime(value)) {
19706 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19707 if (!ptr_val)
19708 return ira->codegen->invalid_instruction;
19709 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19710 if (err_union_val == nullptr)
19711 return ira->codegen->invalid_instruction;
19712 if (err_union_val->special != ConstValSpecialRuntime) {
19713 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
19714 if (err != nullptr) {
19715 ir_add_error(ira, &instruction->base,
19716 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
19717 return ira->codegen->invalid_instruction;
19718 }
19719
19720 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
19721 result->value.data.x_ptr.special = ConstPtrSpecialRef;
19722 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
19723 return result;
19724 }
19725 }
19726
19727 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
19728 instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
19729 result->value.type = result_type;
19730 return result;
19560}19731}
1956119732
19562static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {19733static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
...@@ -19973,7 +20144,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -19973,7 +20144,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
19973 return ira->codegen->invalid_instruction;20144 return ira->codegen->invalid_instruction;
19974 }20145 }
1997520146
19976 IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type);20147 IrInstruction *result = ir_const(ira, target, result_type);
19977 copy_const_val(&result->value, val, false);20148 copy_const_val(&result->value, val, false);
19978 result->value.type = result_type;20149 result->value.type = result_type;
19979 return result;20150 return result;
...@@ -20021,8 +20192,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20021,8 +20192,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20021 if (!val)20192 if (!val)
20022 return ira->codegen->invalid_instruction;20193 return ira->codegen->invalid_instruction;
2002320194
20024 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node,20195 IrInstruction *result = ir_const(ira, source_instr, dest_type);
20025 dest_type);
20026 copy_const_val(&result->value, val, false);20196 copy_const_val(&result->value, val, false);
20027 result->value.type = dest_type;20197 result->value.type = dest_type;
20028 return result;20198 return result;
...@@ -20045,9 +20215,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20045,9 +20215,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20045 return ira->codegen->invalid_instruction;20215 return ira->codegen->invalid_instruction;
20046 }20216 }
2004720217
20048 IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope,20218 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr);
20049 source_instr->source_node, nullptr, ptr);
20050 casted_ptr->value.type = dest_type;
2005120219
20052 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {20220 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
20053 ErrorMsg *msg = ir_add_error(ira, source_instr,20221 ErrorMsg *msg = ir_add_error(ira, source_instr,
...@@ -20073,7 +20241,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20073,7 +20241,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20073 return result;20241 return result;
20074}20242}
2007520243
20076static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {20244static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) {
20077 IrInstruction *dest_type_value = instruction->dest_type->child;20245 IrInstruction *dest_type_value = instruction->dest_type->child;
20078 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);20246 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20079 if (type_is_invalid(dest_type))20247 if (type_is_invalid(dest_type))
...@@ -20211,15 +20379,29 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -20211,15 +20379,29 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
20211 if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))20379 if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
20212 return err;20380 return err;
20213 }20381 }
20214 break;20382 return ErrorNone;
20215 case ConstArraySpecialUndef:20383 case ConstArraySpecialUndef:
20216 zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");20384 zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
20217 case ConstArraySpecialBuf:20385 case ConstArraySpecialBuf:
20218 zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");20386 zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
20219 }20387 }
2022020388 zig_unreachable();
20221 return ErrorNone;
20222 }20389 }
20390 case ZigTypeIdEnum:
20391 switch (val->type->data.enumeration.layout) {
20392 case ContainerLayoutAuto:
20393 zig_panic("TODO buf_read_value_bytes enum auto");
20394 case ContainerLayoutPacked:
20395 zig_panic("TODO buf_read_value_bytes enum packed");
20396 case ContainerLayoutExtern: {
20397 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
20398 assert(tag_int_type->id == ZigTypeIdInt);
20399 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
20400 codegen->is_big_endian, tag_int_type->data.integral.is_signed);
20401 return ErrorNone;
20402 }
20403 }
20404 zig_unreachable();
20223 case ZigTypeIdStruct:20405 case ZigTypeIdStruct:
20224 switch (val->type->data.structure.layout) {20406 switch (val->type->data.structure.layout) {
20225 case ContainerLayoutAuto: {20407 case ContainerLayoutAuto: {
...@@ -20258,8 +20440,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -20258,8 +20440,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
20258 zig_panic("TODO buf_read_value_bytes error union");20440 zig_panic("TODO buf_read_value_bytes error union");
20259 case ZigTypeIdErrorSet:20441 case ZigTypeIdErrorSet:
20260 zig_panic("TODO buf_read_value_bytes pure error type");20442 zig_panic("TODO buf_read_value_bytes pure error type");
20261 case ZigTypeIdEnum:
20262 zig_panic("TODO buf_read_value_bytes enum type");
20263 case ZigTypeIdFn:20443 case ZigTypeIdFn:
20264 zig_panic("TODO buf_read_value_bytes fn type");20444 zig_panic("TODO buf_read_value_bytes fn type");
20265 case ZigTypeIdUnion:20445 case ZigTypeIdUnion:
...@@ -20426,8 +20606,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,...@@ -20426,8 +20606,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20426 case TldIdContainer:20606 case TldIdContainer:
20427 case TldIdCompTime:20607 case TldIdCompTime:
20428 zig_unreachable();20608 zig_unreachable();
20429 case TldIdVar:20609 case TldIdVar: {
20430 {
20431 TldVar *tld_var = (TldVar *)tld;20610 TldVar *tld_var = (TldVar *)tld;
20432 ZigVar *var = tld_var->var;20611 ZigVar *var = tld_var->var;
2043320612
...@@ -20445,8 +20624,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,...@@ -20445,8 +20624,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20445 return ir_get_deref(ira, &instruction->base, var_ptr);20624 return ir_get_deref(ira, &instruction->base, var_ptr);
20446 }20625 }
20447 }20626 }
20448 case TldIdFn:20627 case TldIdFn: {
20449 {
20450 TldFn *tld_fn = (TldFn *)tld;20628 TldFn *tld_fn = (TldFn *)tld;
20451 ZigFn *fn_entry = tld_fn->fn_entry;20629 ZigFn *fn_entry = tld_fn->fn_entry;
20452 assert(fn_entry->type_entry);20630 assert(fn_entry->type_entry);
...@@ -20492,8 +20670,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru...@@ -20492,8 +20670,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru
20492 if (!val)20670 if (!val)
20493 return ira->codegen->invalid_instruction;20671 return ira->codegen->invalid_instruction;
20494 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {20672 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
20495 IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope,20673 IrInstruction *result = ir_const(ira, &instruction->base, usize);
20496 instruction->base.source_node, usize);
20497 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);20674 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
20498 result->value.type = usize;20675 result->value.type = usize;
20499 return result;20676 return result;
...@@ -21331,6 +21508,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21331,6 +21508,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21331 case IrInstructionIdErrWrapCode:21508 case IrInstructionIdErrWrapCode:
21332 case IrInstructionIdErrWrapPayload:21509 case IrInstructionIdErrWrapPayload:
21333 case IrInstructionIdCast:21510 case IrInstructionIdCast:
21511 case IrInstructionIdDeclVarGen:
21512 case IrInstructionIdPtrCastGen:
21513 case IrInstructionIdCmpxchgGen:
21334 zig_unreachable();21514 zig_unreachable();
2133521515
21336 case IrInstructionIdReturn:21516 case IrInstructionIdReturn:
...@@ -21341,8 +21521,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21341,8 +21521,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21341 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);21521 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);
21342 case IrInstructionIdBinOp:21522 case IrInstructionIdBinOp:
21343 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);21523 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
21344 case IrInstructionIdDeclVar:21524 case IrInstructionIdDeclVarSrc:
21345 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction);21525 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction);
21346 case IrInstructionIdLoadPtr:21526 case IrInstructionIdLoadPtr:
21347 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);21527 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
21348 case IrInstructionIdStorePtr:21528 case IrInstructionIdStorePtr:
...@@ -21387,8 +21567,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21387,8 +21567,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21387 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);21567 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
21388 case IrInstructionIdTestNonNull:21568 case IrInstructionIdTestNonNull:
21389 return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);21569 return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);
21390 case IrInstructionIdUnwrapOptional:21570 case IrInstructionIdOptionalUnwrapPtr:
21391 return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction);21571 return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction);
21392 case IrInstructionIdClz:21572 case IrInstructionIdClz:
21393 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);21573 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
21394 case IrInstructionIdCtz:21574 case IrInstructionIdCtz:
...@@ -21429,8 +21609,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21429,8 +21609,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21429 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);21609 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
21430 case IrInstructionIdEmbedFile:21610 case IrInstructionIdEmbedFile:
21431 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);21611 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
21432 case IrInstructionIdCmpxchg:21612 case IrInstructionIdCmpxchgSrc:
21433 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction);21613 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction);
21434 case IrInstructionIdFence:21614 case IrInstructionIdFence:
21435 return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);21615 return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);
21436 case IrInstructionIdTruncate:21616 case IrInstructionIdTruncate:
...@@ -21497,8 +21677,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21497,8 +21677,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21497 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);21677 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
21498 case IrInstructionIdPanic:21678 case IrInstructionIdPanic:
21499 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);21679 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
21500 case IrInstructionIdPtrCast:21680 case IrInstructionIdPtrCastSrc:
21501 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction);21681 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);
21502 case IrInstructionIdBitCast:21682 case IrInstructionIdBitCast:
21503 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);21683 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
21504 case IrInstructionIdIntToPtr:21684 case IrInstructionIdIntToPtr:
...@@ -21682,7 +21862,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21682,7 +21862,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21682 case IrInstructionIdBr:21862 case IrInstructionIdBr:
21683 case IrInstructionIdCondBr:21863 case IrInstructionIdCondBr:
21684 case IrInstructionIdSwitchBr:21864 case IrInstructionIdSwitchBr:
21685 case IrInstructionIdDeclVar:21865 case IrInstructionIdDeclVarSrc:
21866 case IrInstructionIdDeclVarGen:
21686 case IrInstructionIdStorePtr:21867 case IrInstructionIdStorePtr:
21687 case IrInstructionIdCall:21868 case IrInstructionIdCall:
21688 case IrInstructionIdReturn:21869 case IrInstructionIdReturn:
...@@ -21697,7 +21878,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21697,7 +21878,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21697 case IrInstructionIdCInclude:21878 case IrInstructionIdCInclude:
21698 case IrInstructionIdCDefine:21879 case IrInstructionIdCDefine:
21699 case IrInstructionIdCUndef:21880 case IrInstructionIdCUndef:
21700 case IrInstructionIdCmpxchg:
21701 case IrInstructionIdFence:21881 case IrInstructionIdFence:
21702 case IrInstructionIdMemset:21882 case IrInstructionIdMemset:
21703 case IrInstructionIdMemcpy:21883 case IrInstructionIdMemcpy:
...@@ -21725,6 +21905,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21725,6 +21905,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21725 case IrInstructionIdMergeErrRetTraces:21905 case IrInstructionIdMergeErrRetTraces:
21726 case IrInstructionIdMarkErrRetTracePtr:21906 case IrInstructionIdMarkErrRetTracePtr:
21727 case IrInstructionIdAtomicRmw:21907 case IrInstructionIdAtomicRmw:
21908 case IrInstructionIdCmpxchgGen:
21909 case IrInstructionIdCmpxchgSrc:
21728 return true;21910 return true;
2172921911
21730 case IrInstructionIdPhi:21912 case IrInstructionIdPhi:
...@@ -21750,7 +21932,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21750,7 +21932,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21750 case IrInstructionIdSliceType:21932 case IrInstructionIdSliceType:
21751 case IrInstructionIdSizeOf:21933 case IrInstructionIdSizeOf:
21752 case IrInstructionIdTestNonNull:21934 case IrInstructionIdTestNonNull:
21753 case IrInstructionIdUnwrapOptional:21935 case IrInstructionIdOptionalUnwrapPtr:
21754 case IrInstructionIdClz:21936 case IrInstructionIdClz:
21755 case IrInstructionIdCtz:21937 case IrInstructionIdCtz:
21756 case IrInstructionIdPopCount:21938 case IrInstructionIdPopCount:
...@@ -21777,7 +21959,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21777,7 +21959,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21777 case IrInstructionIdErrWrapPayload:21959 case IrInstructionIdErrWrapPayload:
21778 case IrInstructionIdFnProto:21960 case IrInstructionIdFnProto:
21779 case IrInstructionIdTestComptime:21961 case IrInstructionIdTestComptime:
21780 case IrInstructionIdPtrCast:21962 case IrInstructionIdPtrCastSrc:
21963 case IrInstructionIdPtrCastGen:
21781 case IrInstructionIdBitCast:21964 case IrInstructionIdBitCast:
21782 case IrInstructionIdWidenOrShorten:21965 case IrInstructionIdWidenOrShorten:
21783 case IrInstructionIdPtrToInt:21966 case IrInstructionIdPtrToInt:
src/ir.hpp+1-1
...@@ -13,7 +13,7 @@...@@ -13,7 +13,7 @@
13bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);13bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
14bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);14bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
1515
16IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
19 IrExecutable *parent_exec);19 IrExecutable *parent_exec);
src/ir_print.cpp+61-22
...@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction...@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
172 }172 }
173}173}
174174
175static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {175static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) {
176 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";176 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
177 const char *name = buf_ptr(&decl_var_instruction->var->name);177 const char *name = buf_ptr(&decl_var_instruction->var->name);
178 if (decl_var_instruction->var_type) {178 if (decl_var_instruction->var_type) {
...@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {...@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
332}332}
333333
334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
335 fprintf(irp->f, "*");
336 ir_print_other_instruction(irp, instruction->ptr);335 ir_print_other_instruction(irp, instruction->ptr);
336 fprintf(irp->f, ".*");
337}337}
338338
339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
...@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {...@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
479 fprintf(irp->f, ")");479 fprintf(irp->f, ")");
480}480}
481481
482static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {482static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
483 fprintf(irp->f, "*");
484 ir_print_other_instruction(irp, instruction->value);483 ir_print_other_instruction(irp, instruction->value);
485 fprintf(irp->f, " != null");484 fprintf(irp->f, " != null");
486}485}
487486
488static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) {487static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) {
489 fprintf(irp->f, "&??*");488 fprintf(irp->f, "&");
490 ir_print_other_instruction(irp, instruction->value);489 ir_print_other_instruction(irp, instruction->base_ptr);
490 fprintf(irp->f, ".*.?");
491 if (!instruction->safety_check_on) {491 if (!instruction->safety_check_on) {
492 fprintf(irp->f, " // no safety");492 fprintf(irp->f, " // no safety");
493 }493 }
...@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio...@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio
613 fprintf(irp->f, ")");613 fprintf(irp->f, ")");
614}614}
615615
616static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {616static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) {
617 fprintf(irp->f, "@cmpxchg(");617 fprintf(irp->f, "@cmpxchg(");
618 ir_print_other_instruction(irp, instruction->ptr);618 ir_print_other_instruction(irp, instruction->ptr);
619 fprintf(irp->f, ", ");619 fprintf(irp->f, ", ");
...@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {...@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
627 fprintf(irp->f, ")");627 fprintf(irp->f, ")");
628}628}
629629
630static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
631 fprintf(irp->f, "@cmpxchg(");
632 ir_print_other_instruction(irp, instruction->ptr);
633 fprintf(irp->f, ", ");
634 ir_print_other_instruction(irp, instruction->cmp_value);
635 fprintf(irp->f, ", ");
636 ir_print_other_instruction(irp, instruction->new_value);
637 fprintf(irp->f, ", TODO print atomic orders)");
638}
639
630static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {640static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
631 fprintf(irp->f, "@fence(");641 fprintf(irp->f, "@fence(");
632 ir_print_other_instruction(irp, instruction->order_value);642 ir_print_other_instruction(irp, instruction->order_value);
...@@ -820,13 +830,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {...@@ -820,13 +830,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
820}830}
821831
822static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {832static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
823 fprintf(irp->f, "@unwrapErrorCode(");833 fprintf(irp->f, "UnwrapErrorCode(");
824 ir_print_other_instruction(irp, instruction->value);834 ir_print_other_instruction(irp, instruction->err_union);
825 fprintf(irp->f, ")");835 fprintf(irp->f, ")");
826}836}
827837
828static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {838static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
829 fprintf(irp->f, "@unwrapErrorPayload(");839 fprintf(irp->f, "ErrorUnionFieldPayload(");
830 ir_print_other_instruction(irp, instruction->value);840 ir_print_other_instruction(irp, instruction->value);
831 fprintf(irp->f, ")");841 fprintf(irp->f, ")");
832 if (!instruction->safety_check_on) {842 if (!instruction->safety_check_on) {
...@@ -879,7 +889,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst...@@ -879,7 +889,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
879 fprintf(irp->f, ")");889 fprintf(irp->f, ")");
880}890}
881891
882static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {892static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) {
883 fprintf(irp->f, "@ptrCast(");893 fprintf(irp->f, "@ptrCast(");
884 if (instruction->dest_type) {894 if (instruction->dest_type) {
885 ir_print_other_instruction(irp, instruction->dest_type);895 ir_print_other_instruction(irp, instruction->dest_type);
...@@ -889,6 +899,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {...@@ -889,6 +899,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
889 fprintf(irp->f, ")");899 fprintf(irp->f, ")");
890}900}
891901
902static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) {
903 fprintf(irp->f, "@ptrCast(");
904 ir_print_other_instruction(irp, instruction->ptr);
905 fprintf(irp->f, ")");
906}
907
892static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {908static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
893 fprintf(irp->f, "@bitCast(");909 fprintf(irp->f, "@bitCast(");
894 if (instruction->dest_type) {910 if (instruction->dest_type) {
...@@ -900,7 +916,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {...@@ -900,7 +916,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
900}916}
901917
902static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {918static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
903 fprintf(irp->f, "@widenOrShorten(");919 fprintf(irp->f, "WidenOrShorten(");
904 ir_print_other_instruction(irp, instruction->target);920 ir_print_other_instruction(irp, instruction->target);
905 fprintf(irp->f, ")");921 fprintf(irp->f, ")");
906}922}
...@@ -1323,6 +1339,20 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {...@@ -1323,6 +1339,20 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
1323 fprintf(irp->f, ")");1339 fprintf(irp->f, ")");
1324}1340}
13251341
1342static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) {
1343 ZigVar *var = decl_var_instruction->var;
1344 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
1345 const char *name = buf_ptr(&decl_var_instruction->var->name);
1346 fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
1347 var->align_bytes);
1348
1349 ir_print_other_instruction(irp, decl_var_instruction->init_value);
1350 if (decl_var_instruction->var->is_comptime != nullptr) {
1351 fprintf(irp->f, " // comptime = ");
1352 ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
1353 }
1354}
1355
1326static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {1356static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
1327 fprintf(irp->f, "@bswap(");1357 fprintf(irp->f, "@bswap(");
1328 if (instruction->type != nullptr) {1358 if (instruction->type != nullptr) {
...@@ -1361,8 +1391,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1361,8 +1391,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1361 case IrInstructionIdBinOp:1391 case IrInstructionIdBinOp:
1362 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);1392 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
1363 break;1393 break;
1364 case IrInstructionIdDeclVar:1394 case IrInstructionIdDeclVarSrc:
1365 ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);1395 ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction);
1366 break;1396 break;
1367 case IrInstructionIdCast:1397 case IrInstructionIdCast:
1368 ir_print_cast(irp, (IrInstructionCast *)instruction);1398 ir_print_cast(irp, (IrInstructionCast *)instruction);
...@@ -1452,10 +1482,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1452,10 +1482,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1452 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);1482 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
1453 break;1483 break;
1454 case IrInstructionIdTestNonNull:1484 case IrInstructionIdTestNonNull:
1455 ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction);1485 ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction);
1456 break;1486 break;
1457 case IrInstructionIdUnwrapOptional:1487 case IrInstructionIdOptionalUnwrapPtr:
1458 ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction);1488 ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction);
1459 break;1489 break;
1460 case IrInstructionIdCtz:1490 case IrInstructionIdCtz:
1461 ir_print_ctz(irp, (IrInstructionCtz *)instruction);1491 ir_print_ctz(irp, (IrInstructionCtz *)instruction);
...@@ -1508,8 +1538,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1508,8 +1538,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1508 case IrInstructionIdEmbedFile:1538 case IrInstructionIdEmbedFile:
1509 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);1539 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
1510 break;1540 break;
1511 case IrInstructionIdCmpxchg:1541 case IrInstructionIdCmpxchgSrc:
1512 ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction);1542 ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction);
1543 break;
1544 case IrInstructionIdCmpxchgGen:
1545 ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction);
1513 break;1546 break;
1514 case IrInstructionIdFence:1547 case IrInstructionIdFence:
1515 ir_print_fence(irp, (IrInstructionFence *)instruction);1548 ir_print_fence(irp, (IrInstructionFence *)instruction);
...@@ -1607,8 +1640,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1607,8 +1640,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1607 case IrInstructionIdTestComptime:1640 case IrInstructionIdTestComptime:
1608 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);1641 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
1609 break;1642 break;
1610 case IrInstructionIdPtrCast:1643 case IrInstructionIdPtrCastSrc:
1611 ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);1644 ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction);
1645 break;
1646 case IrInstructionIdPtrCastGen:
1647 ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
1612 break;1648 break;
1613 case IrInstructionIdBitCast:1649 case IrInstructionIdBitCast:
1614 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);1650 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
...@@ -1775,6 +1811,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1775,6 +1811,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1775 case IrInstructionIdCheckRuntimeScope:1811 case IrInstructionIdCheckRuntimeScope:
1776 ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);1812 ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
1777 break;1813 break;
1814 case IrInstructionIdDeclVarGen:
1815 ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction);
1816 break;
1778 }1817 }
1779 fprintf(irp->f, "\n");1818 fprintf(irp->f, "\n");
1780}1819}
src/parser.cpp+4-4
...@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse...@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse
381 else_body = ast_expect(pc, body_parser);381 else_body = ast_expect(pc, body_parser);
382 }382 }
383383
384 assert(res->type == NodeTypeTestExpr);384 assert(res->type == NodeTypeIfOptional);
385 if (err_payload != nullptr) {385 if (err_payload != nullptr) {
386 AstNodeTestExpr old = res->data.test_expr;386 AstNodeTestExpr old = res->data.test_expr;
387 res->type = NodeTypeIfErrorExpr;387 res->type = NodeTypeIfErrorExpr;
...@@ -990,7 +990,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {...@@ -990,7 +990,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
990 if (requires_semi && else_body == nullptr)990 if (requires_semi && else_body == nullptr)
991 expect_token(pc, TokenIdSemicolon);991 expect_token(pc, TokenIdSemicolon);
992992
993 assert(res->type == NodeTypeTestExpr);993 assert(res->type == NodeTypeIfOptional);
994 if (err_payload != nullptr) {994 if (err_payload != nullptr) {
995 AstNodeTestExpr old = res->data.test_expr;995 AstNodeTestExpr old = res->data.test_expr;
996 res->type = NodeTypeIfErrorExpr;996 res->type = NodeTypeIfErrorExpr;
...@@ -2204,7 +2204,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {...@@ -2204,7 +2204,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {
2204 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);2204 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
22052205
2206 PtrPayload payload;2206 PtrPayload payload;
2207 AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first);2207 AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
2208 res->data.test_expr.target_node = condition;2208 res->data.test_expr.target_node = condition;
2209 if (opt_payload.unwrap(&payload)) {2209 if (opt_payload.unwrap(&payload)) {
2210 res->data.test_expr.var_symbol = token_buf(payload.payload);2210 res->data.test_expr.var_symbol = token_buf(payload.payload);
...@@ -2999,7 +2999,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2999,7 +2999,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2999 visit_field(&node->data.if_err_expr.then_node, visit, context);2999 visit_field(&node->data.if_err_expr.then_node, visit, context);
3000 visit_field(&node->data.if_err_expr.else_node, visit, context);3000 visit_field(&node->data.if_err_expr.else_node, visit, context);
3001 break;3001 break;
3002 case NodeTypeTestExpr:3002 case NodeTypeIfOptional:
3003 visit_field(&node->data.test_expr.target_node, visit, context);3003 visit_field(&node->data.test_expr.target_node, visit, context);
3004 visit_field(&node->data.test_expr.then_node, visit, context);3004 visit_field(&node->data.test_expr.then_node, visit, context);
3005 visit_field(&node->data.test_expr.else_node, visit, context);3005 visit_field(&node->data.test_expr.else_node, visit, context);
std/event/fs.zig+23-26
...@@ -1307,32 +1307,29 @@ pub fn Watch(comptime V: type) type {...@@ -1307,32 +1307,29 @@ pub fn Watch(comptime V: type) type {
13071307
1308const test_tmp_dir = "std_event_fs_test";1308const test_tmp_dir = "std_event_fs_test";
13091309
1310test "write a file, watch it, write it again" {1310// TODO this test is disabled until the coroutine rewrite is finished.
1311 if (builtin.os == builtin.Os.windows) {1311//test "write a file, watch it, write it again" {
1312 // TODO this test is disabled on windows until the coroutine rewrite is finished.1312// return error.SkipZigTest;
1313 // https://github.com/ziglang/zig/issues/13631313// var da = std.heap.DirectAllocator.init();
1314 return error.SkipZigTest;1314// defer da.deinit();
1315 }1315//
1316 var da = std.heap.DirectAllocator.init();1316// const allocator = &da.allocator;
1317 defer da.deinit();1317//
13181318// // TODO move this into event loop too
1319 const allocator = &da.allocator;1319// try os.makePath(allocator, test_tmp_dir);
13201320// defer os.deleteTree(allocator, test_tmp_dir) catch {};
1321 // TODO move this into event loop too1321//
1322 try os.makePath(allocator, test_tmp_dir);1322// var loop: Loop = undefined;
1323 defer os.deleteTree(allocator, test_tmp_dir) catch {};1323// try loop.initMultiThreaded(allocator);
13241324// defer loop.deinit();
1325 var loop: Loop = undefined;1325//
1326 try loop.initMultiThreaded(allocator);1326// var result: anyerror!void = error.ResultNeverWritten;
1327 defer loop.deinit();1327// const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
13281328// defer cancel handle;
1329 var result: anyerror!void = error.ResultNeverWritten;1329//
1330 const handle = try async<allocator> testFsWatchCantFail(&loop, &result);1330// loop.run();
1331 defer cancel handle;1331// return result;
13321332//}
1333 loop.run();
1334 return result;
1335}
13361333
1337async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {1334async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {
1338 result.* = await (async testFsWatch(loop) catch unreachable);1335 result.* = await (async testFsWatch(loop) catch unreachable);
test/behavior.zig deleted-82
...@@ -1,82 +0,0 @@
1const builtin = @import("builtin");
2
3comptime {
4 _ = @import("cases/align.zig");
5 _ = @import("cases/alignof.zig");
6 _ = @import("cases/array.zig");
7 _ = @import("cases/asm.zig");
8 _ = @import("cases/atomics.zig");
9 _ = @import("cases/bitcast.zig");
10 _ = @import("cases/bool.zig");
11 _ = @import("cases/bswap.zig");
12 _ = @import("cases/bitreverse.zig");
13 _ = @import("cases/bugs/1076.zig");
14 _ = @import("cases/bugs/1111.zig");
15 _ = @import("cases/bugs/1277.zig");
16 _ = @import("cases/bugs/1322.zig");
17 _ = @import("cases/bugs/1381.zig");
18 _ = @import("cases/bugs/1421.zig");
19 _ = @import("cases/bugs/1442.zig");
20 _ = @import("cases/bugs/1486.zig");
21 _ = @import("cases/bugs/394.zig");
22 _ = @import("cases/bugs/655.zig");
23 _ = @import("cases/bugs/656.zig");
24 _ = @import("cases/bugs/726.zig");
25 _ = @import("cases/bugs/828.zig");
26 _ = @import("cases/bugs/920.zig");
27 _ = @import("cases/byval_arg_var.zig");
28 _ = @import("cases/cancel.zig");
29 _ = @import("cases/cast.zig");
30 _ = @import("cases/const_slice_child.zig");
31 _ = @import("cases/coroutine_await_struct.zig");
32 _ = @import("cases/coroutines.zig");
33 _ = @import("cases/defer.zig");
34 _ = @import("cases/enum.zig");
35 _ = @import("cases/enum_with_members.zig");
36 _ = @import("cases/error.zig");
37 _ = @import("cases/eval.zig");
38 _ = @import("cases/field_parent_ptr.zig");
39 _ = @import("cases/fn.zig");
40 _ = @import("cases/fn_in_struct_in_comptime.zig");
41 _ = @import("cases/for.zig");
42 _ = @import("cases/generics.zig");
43 _ = @import("cases/if.zig");
44 _ = @import("cases/import.zig");
45 _ = @import("cases/incomplete_struct_param_tld.zig");
46 _ = @import("cases/inttoptr.zig");
47 _ = @import("cases/ir_block_deps.zig");
48 _ = @import("cases/math.zig");
49 _ = @import("cases/merge_error_sets.zig");
50 _ = @import("cases/misc.zig");
51 _ = @import("cases/namespace_depends_on_compile_var/index.zig");
52 _ = @import("cases/new_stack_call.zig");
53 _ = @import("cases/null.zig");
54 _ = @import("cases/optional.zig");
55 _ = @import("cases/pointers.zig");
56 _ = @import("cases/popcount.zig");
57 _ = @import("cases/ptrcast.zig");
58 _ = @import("cases/pub_enum/index.zig");
59 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
60 _ = @import("cases/reflection.zig");
61 _ = @import("cases/sizeof_and_typeof.zig");
62 _ = @import("cases/slice.zig");
63 _ = @import("cases/struct.zig");
64 _ = @import("cases/struct_contains_null_ptr_itself.zig");
65 _ = @import("cases/struct_contains_slice_of_itself.zig");
66 _ = @import("cases/switch.zig");
67 _ = @import("cases/switch_prong_err_enum.zig");
68 _ = @import("cases/switch_prong_implicit_cast.zig");
69 _ = @import("cases/syntax.zig");
70 _ = @import("cases/this.zig");
71 _ = @import("cases/truncate.zig");
72 _ = @import("cases/try.zig");
73 _ = @import("cases/type_info.zig");
74 _ = @import("cases/undefined.zig");
75 _ = @import("cases/underscore.zig");
76 _ = @import("cases/union.zig");
77 _ = @import("cases/var_args.zig");
78 _ = @import("cases/void.zig");
79 _ = @import("cases/while.zig");
80 _ = @import("cases/widening.zig");
81 _ = @import("cases/bit_shifting.zig");
82}
test/cases/align.zig deleted-230
...@@ -1,230 +0,0 @@
1const assert = @import("std").debug.assert;
2const builtin = @import("builtin");
3
4var foo: u8 align(4) = 100;
5
6test "global variable alignment" {
7 assert(@typeOf(&foo).alignment == 4);
8 assert(@typeOf(&foo) == *align(4) u8);
9 const slice = (*[1]u8)(&foo)[0..];
10 assert(@typeOf(slice) == []align(4) u8);
11}
12
13fn derp() align(@sizeOf(usize) * 2) i32 {
14 return 1234;
15}
16fn noop1() align(1) void {}
17fn noop4() align(4) void {}
18
19test "function alignment" {
20 assert(derp() == 1234);
21 assert(@typeOf(noop1) == fn () align(1) void);
22 assert(@typeOf(noop4) == fn () align(4) void);
23 noop1();
24 noop4();
25}
26
27var baz: packed struct {
28 a: u32,
29 b: u32,
30} = undefined;
31
32test "packed struct alignment" {
33 assert(@typeOf(&baz.b) == *align(1) u32);
34}
35
36const blah: packed struct {
37 a: u3,
38 b: u3,
39 c: u2,
40} = undefined;
41
42test "bit field alignment" {
43 assert(@typeOf(&blah.b) == *align(1:3:1) const u3);
44}
45
46test "default alignment allows unspecified in type syntax" {
47 assert(*u32 == *align(@alignOf(u32)) u32);
48}
49
50test "implicitly decreasing pointer alignment" {
51 const a: u32 align(4) = 3;
52 const b: u32 align(8) = 4;
53 assert(addUnaligned(&a, &b) == 7);
54}
55
56fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
57 return a.* + b.*;
58}
59
60test "implicitly decreasing slice alignment" {
61 const a: u32 align(4) = 3;
62 const b: u32 align(8) = 4;
63 assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
64}
65fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
66 return a[0] + b[0];
67}
68
69test "specifying alignment allows pointer cast" {
70 testBytesAlign(0x33);
71}
72fn testBytesAlign(b: u8) void {
73 var bytes align(4) = []u8{
74 b,
75 b,
76 b,
77 b,
78 };
79 const ptr = @ptrCast(*u32, &bytes[0]);
80 assert(ptr.* == 0x33333333);
81}
82
83test "specifying alignment allows slice cast" {
84 testBytesAlignSlice(0x33);
85}
86fn testBytesAlignSlice(b: u8) void {
87 var bytes align(4) = []u8{
88 b,
89 b,
90 b,
91 b,
92 };
93 const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
94 assert(slice[0] == 0x33333333);
95}
96
97test "@alignCast pointers" {
98 var x: u32 align(4) = 1;
99 expectsOnly1(&x);
100 assert(x == 2);
101}
102fn expectsOnly1(x: *align(1) u32) void {
103 expects4(@alignCast(4, x));
104}
105fn expects4(x: *align(4) u32) void {
106 x.* += 1;
107}
108
109test "@alignCast slices" {
110 var array align(4) = []u32{
111 1,
112 1,
113 };
114 const slice = array[0..];
115 sliceExpectsOnly1(slice);
116 assert(slice[0] == 2);
117}
118fn sliceExpectsOnly1(slice: []align(1) u32) void {
119 sliceExpects4(@alignCast(4, slice));
120}
121fn sliceExpects4(slice: []align(4) u32) void {
122 slice[0] += 1;
123}
124
125test "implicitly decreasing fn alignment" {
126 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
127 testImplicitlyDecreaseFnAlign(alignedBig, 5678);
128}
129
130fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
131 assert(ptr() == answer);
132}
133
134fn alignedSmall() align(8) i32 {
135 return 1234;
136}
137fn alignedBig() align(16) i32 {
138 return 5678;
139}
140
141test "@alignCast functions" {
142 assert(fnExpectsOnly1(simple4) == 0x19);
143}
144fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
145 return fnExpects4(@alignCast(4, ptr));
146}
147fn fnExpects4(ptr: fn () align(4) i32) i32 {
148 return ptr();
149}
150fn simple4() align(4) i32 {
151 return 0x19;
152}
153
154test "generic function with align param" {
155 assert(whyWouldYouEverDoThis(1) == 0x1);
156 assert(whyWouldYouEverDoThis(4) == 0x1);
157 assert(whyWouldYouEverDoThis(8) == 0x1);
158}
159
160fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
161 return 0x1;
162}
163
164test "@ptrCast preserves alignment of bigger source" {
165 var x: u32 align(16) = 1234;
166 const ptr = @ptrCast(*u8, &x);
167 assert(@typeOf(ptr) == *align(16) u8);
168}
169
170test "runtime known array index has best alignment possible" {
171 // take full advantage of over-alignment
172 var array align(4) = []u8{ 1, 2, 3, 4 };
173 assert(@typeOf(&array[0]) == *align(4) u8);
174 assert(@typeOf(&array[1]) == *u8);
175 assert(@typeOf(&array[2]) == *align(2) u8);
176 assert(@typeOf(&array[3]) == *u8);
177
178 // because align is too small but we still figure out to use 2
179 var bigger align(2) = []u64{ 1, 2, 3, 4 };
180 assert(@typeOf(&bigger[0]) == *align(2) u64);
181 assert(@typeOf(&bigger[1]) == *align(2) u64);
182 assert(@typeOf(&bigger[2]) == *align(2) u64);
183 assert(@typeOf(&bigger[3]) == *align(2) u64);
184
185 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
186 var smaller align(2) = []u32{ 1, 2, 3, 4 };
187 comptime assert(@typeOf(smaller[0..]) == []align(2) u32);
188 comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
189 testIndex(smaller[0..].ptr, 0, *align(2) u32);
190 testIndex(smaller[0..].ptr, 1, *align(2) u32);
191 testIndex(smaller[0..].ptr, 2, *align(2) u32);
192 testIndex(smaller[0..].ptr, 3, *align(2) u32);
193
194 // has to use ABI alignment because index known at runtime only
195 testIndex2(array[0..].ptr, 0, *u8);
196 testIndex2(array[0..].ptr, 1, *u8);
197 testIndex2(array[0..].ptr, 2, *u8);
198 testIndex2(array[0..].ptr, 3, *u8);
199}
200fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
201 comptime assert(@typeOf(&smaller[index]) == T);
202}
203fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
204 comptime assert(@typeOf(&ptr[index]) == T);
205}
206
207test "alignstack" {
208 assert(fnWithAlignedStack() == 1234);
209}
210
211fn fnWithAlignedStack() i32 {
212 @setAlignStack(256);
213 return 1234;
214}
215
216test "alignment of structs" {
217 assert(@alignOf(struct {
218 a: i32,
219 b: *i32,
220 }) == @alignOf(usize));
221}
222
223test "alignment of extern() void" {
224 var runtime_nothing = nothing;
225 const casted1 = @ptrCast(*const u8, runtime_nothing);
226 const casted2 = @ptrCast(extern fn () void, casted1);
227 casted2();
228}
229
230extern fn nothing() void {}
test/cases/alignof.zig deleted-17
...@@ -1,17 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const Foo = struct {
7 x: u32,
8 y: u32,
9 z: u32,
10};
11
12test "@alignOf(T) before referencing T" {
13 comptime assert(@alignOf(Foo) != maxInt(usize));
14 if (builtin.arch == builtin.Arch.x86_64) {
15 comptime assert(@alignOf(Foo) == 4);
16 }
17}
test/cases/array.zig deleted-173
...@@ -1,173 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4test "arrays" {
5 var array: [5]u32 = undefined;
6
7 var i: u32 = 0;
8 while (i < 5) {
9 array[i] = i + 1;
10 i = array[i];
11 }
12
13 i = 0;
14 var accumulator = u32(0);
15 while (i < 5) {
16 accumulator += array[i];
17
18 i += 1;
19 }
20
21 assert(accumulator == 15);
22 assert(getArrayLen(array) == 5);
23}
24fn getArrayLen(a: []const u32) usize {
25 return a.len;
26}
27
28test "void arrays" {
29 var array: [4]void = undefined;
30 array[0] = void{};
31 array[1] = array[2];
32 assert(@sizeOf(@typeOf(array)) == 0);
33 assert(array.len == 4);
34}
35
36test "array literal" {
37 const hex_mult = []u16{
38 4096,
39 256,
40 16,
41 1,
42 };
43
44 assert(hex_mult.len == 4);
45 assert(hex_mult[1] == 256);
46}
47
48test "array dot len const expr" {
49 assert(comptime x: {
50 break :x some_array.len == 4;
51 });
52}
53
54const ArrayDotLenConstExpr = struct {
55 y: [some_array.len]u8,
56};
57const some_array = []u8{
58 0,
59 1,
60 2,
61 3,
62};
63
64test "nested arrays" {
65 const array_of_strings = [][]const u8{
66 "hello",
67 "this",
68 "is",
69 "my",
70 "thing",
71 };
72 for (array_of_strings) |s, i| {
73 if (i == 0) assert(mem.eql(u8, s, "hello"));
74 if (i == 1) assert(mem.eql(u8, s, "this"));
75 if (i == 2) assert(mem.eql(u8, s, "is"));
76 if (i == 3) assert(mem.eql(u8, s, "my"));
77 if (i == 4) assert(mem.eql(u8, s, "thing"));
78 }
79}
80
81var s_array: [8]Sub = undefined;
82const Sub = struct {
83 b: u8,
84};
85const Str = struct {
86 a: []Sub,
87};
88test "set global var array via slice embedded in struct" {
89 var s = Str{ .a = s_array[0..] };
90
91 s.a[0].b = 1;
92 s.a[1].b = 2;
93 s.a[2].b = 3;
94
95 assert(s_array[0].b == 1);
96 assert(s_array[1].b == 2);
97 assert(s_array[2].b == 3);
98}
99
100test "array literal with specified size" {
101 var array = [2]u8{
102 1,
103 2,
104 };
105 assert(array[0] == 1);
106 assert(array[1] == 2);
107}
108
109test "array child property" {
110 var x: [5]i32 = undefined;
111 assert(@typeOf(x).Child == i32);
112}
113
114test "array len property" {
115 var x: [5]i32 = undefined;
116 assert(@typeOf(x).len == 5);
117}
118
119test "array len field" {
120 var arr = [4]u8{ 0, 0, 0, 0 };
121 var ptr = &arr;
122 assert(arr.len == 4);
123 comptime assert(arr.len == 4);
124 assert(ptr.len == 4);
125 comptime assert(ptr.len == 4);
126}
127
128test "single-item pointer to array indexing and slicing" {
129 testSingleItemPtrArrayIndexSlice();
130 comptime testSingleItemPtrArrayIndexSlice();
131}
132
133fn testSingleItemPtrArrayIndexSlice() void {
134 var array = "aaaa";
135 doSomeMangling(&array);
136 assert(mem.eql(u8, "azya", array));
137}
138
139fn doSomeMangling(array: *[4]u8) void {
140 array[1] = 'z';
141 array[2..3][0] = 'y';
142}
143
144test "implicit cast single-item pointer" {
145 testImplicitCastSingleItemPtr();
146 comptime testImplicitCastSingleItemPtr();
147}
148
149fn testImplicitCastSingleItemPtr() void {
150 var byte: u8 = 100;
151 const slice = (*[1]u8)(&byte)[0..];
152 slice[0] += 1;
153 assert(byte == 101);
154}
155
156fn testArrayByValAtComptime(b: [2]u8) u8 {
157 return b[0];
158}
159
160test "comptime evalutating function that takes array by value" {
161 const arr = []u8{ 0, 1 };
162 _ = comptime testArrayByValAtComptime(arr);
163 _ = comptime testArrayByValAtComptime(arr);
164}
165
166test "implicit comptime in array type size" {
167 var arr: [plusOne(10)]bool = undefined;
168 assert(arr.len == 11);
169}
170
171fn plusOne(x: u32) u32 {
172 return x + 1;
173}
test/cases/asm.zig deleted-48
...@@ -1,48 +0,0 @@
1const config = @import("builtin");
2const assert = @import("std").debug.assert;
3
4comptime {
5 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
6 asm volatile (
7 \\.globl aoeu;
8 \\.type aoeu, @function;
9 \\.set aoeu, derp;
10 );
11 }
12}
13
14test "module level assembly" {
15 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
16 assert(aoeu() == 1234);
17 }
18}
19
20test "output constraint modifiers" {
21 // This is only testing compilation.
22 var a: u32 = 3;
23 asm volatile ("" : [_]"=m,r"(a) : : "");
24 asm volatile ("" : [_]"=r,m"(a) : : "");
25}
26
27test "alternative constraints" {
28 // Make sure we allow commas as a separator for alternative constraints.
29 var a: u32 = 3;
30 asm volatile ("" : [_]"=r,m"(a) : [_]"r,m"(a) : "");
31}
32
33test "sized integer/float in asm input" {
34 asm volatile ("" : : [_]"m"(usize(3)) : "");
35 asm volatile ("" : : [_]"m"(i15(-3)) : "");
36 asm volatile ("" : : [_]"m"(u3(3)) : "");
37 asm volatile ("" : : [_]"m"(i3(3)) : "");
38 asm volatile ("" : : [_]"m"(u121(3)) : "");
39 asm volatile ("" : : [_]"m"(i121(3)) : "");
40 asm volatile ("" : : [_]"m"(f32(3.17)) : "");
41 asm volatile ("" : : [_]"m"(f64(3.17)) : "");
42}
43
44extern fn aoeu() i32;
45
46export fn derp() i32 {
47 return 1234;
48}
test/cases/atomics.zig deleted-71
...@@ -1,71 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;
6
7test "cmpxchg" {
8 var x: i32 = 1234;
9 if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
10 assert(x1 == 1234);
11 } else {
12 @panic("cmpxchg should have failed");
13 }
14
15 while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
16 assert(x1 == 1234);
17 }
18 assert(x == 5678);
19
20 assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
21 assert(x == 42);
22}
23
24test "fence" {
25 var x: i32 = 1234;
26 @fence(AtomicOrder.SeqCst);
27 x = 5678;
28}
29
30test "atomicrmw and atomicload" {
31 var data: u8 = 200;
32 testAtomicRmw(&data);
33 assert(data == 42);
34 testAtomicLoad(&data);
35}
36
37fn testAtomicRmw(ptr: *u8) void {
38 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
39 assert(prev_value == 200);
40 comptime {
41 var x: i32 = 1234;
42 const y: i32 = 12345;
43 assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
44 assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
45 }
46}
47
48fn testAtomicLoad(ptr: *u8) void {
49 const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
50 assert(x == 42);
51}
52
53test "cmpxchg with ptr" {
54 var data1: i32 = 1234;
55 var data2: i32 = 5678;
56 var data3: i32 = 9101;
57 var x: *i32 = &data1;
58 if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
59 assert(x1 == &data1);
60 } else {
61 @panic("cmpxchg should have failed");
62 }
63
64 while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
65 assert(x1 == &data1);
66 }
67 assert(x == &data3);
68
69 assert(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
70 assert(x == &data2);
71}
test/cases/bit_shifting.zig deleted-88
...@@ -1,88 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 assert(Key == @IntType(false, Key.bit_count));
6 assert(Key.bit_count >= mask_bit_count);
7 const ShardKey = @IntType(false, mask_bit_count);
8 const shift_amount = Key.bit_count - ShardKey.bit_count;
9 return struct {
10 const Self = @This();
11 shards: [1 << ShardKey.bit_count]?*Node,
12
13 pub fn create() Self {
14 return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) };
15 }
16
17 fn getShardKey(key: Key) ShardKey {
18 // https://github.com/ziglang/zig/issues/1544
19 // this special case is needed because you can't u32 >> 32.
20 if (ShardKey == u0) return 0;
21
22 // this can be u1 >> u0
23 const shard_key = key >> shift_amount;
24
25 // TODO: https://github.com/ziglang/zig/issues/1544
26 // This cast could be implicit if we teach the compiler that
27 // u32 >> 30 -> u2
28 return @intCast(ShardKey, shard_key);
29 }
30
31 pub fn put(self: *Self, node: *Node) void {
32 const shard_key = Self.getShardKey(node.key);
33 node.next = self.shards[shard_key];
34 self.shards[shard_key] = node;
35 }
36
37 pub fn get(self: *Self, key: Key) ?*Node {
38 const shard_key = Self.getShardKey(key);
39 var maybe_node = self.shards[shard_key];
40 while (maybe_node) |node| : (maybe_node = node.next) {
41 if (node.key == key) return node;
42 }
43 return null;
44 }
45
46 pub const Node = struct {
47 key: Key,
48 value: V,
49 next: ?*Node,
50
51 pub fn init(self: *Node, key: Key, value: V) void {
52 self.key = key;
53 self.value = value;
54 self.next = null;
55 }
56 };
57 };
58}
59
60test "sharded table" {
61 // realistic 16-way sharding
62 testShardedTable(u32, 4, 8);
63
64 testShardedTable(u5, 0, 32); // ShardKey == u0
65 testShardedTable(u5, 2, 32);
66 testShardedTable(u5, 5, 32);
67
68 testShardedTable(u1, 0, 2);
69 testShardedTable(u1, 1, 2); // this does u1 >> u0
70
71 testShardedTable(u0, 0, 1);
72}
73fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void {
74 const Table = ShardedTable(Key, mask_bit_count, void);
75
76 var table = Table.create();
77 var node_buffer: [node_count]Table.Node = undefined;
78 for (node_buffer) |*node, i| {
79 const key = @intCast(Key, i);
80 assert(table.get(key) == null);
81 node.init(key, {});
82 table.put(node);
83 }
84
85 for (node_buffer) |*node, i| {
86 assert(table.get(@intCast(Key, i)) == node);
87 }
88}
test/cases/bitcast.zig deleted-37
...@@ -1,37 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const maxInt = std.math.maxInt;
4
5test "@bitCast i32 -> u32" {
6 testBitCast_i32_u32();
7 comptime testBitCast_i32_u32();
8}
9
10fn testBitCast_i32_u32() void {
11 assert(conv(-1) == maxInt(u32));
12 assert(conv2(maxInt(u32)) == -1);
13}
14
15fn conv(x: i32) u32 {
16 return @bitCast(u32, x);
17}
18fn conv2(x: u32) i32 {
19 return @bitCast(i32, x);
20}
21
22test "@bitCast extern enum to its integer type" {
23 const SOCK = extern enum {
24 A,
25 B,
26
27 fn testBitCastExternEnum() void {
28 var SOCK_DGRAM = @This().B;
29 var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
30 assert(sock_dgram == 1);
31 }
32 };
33
34 SOCK.testBitCastExternEnum();
35 comptime SOCK.testBitCastExternEnum();
36}
37
test/cases/bitreverse.zig deleted-81
...@@ -1,81 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const minInt = std.math.minInt;
4
5test "@bitreverse" {
6 comptime testBitReverse();
7 testBitReverse();
8}
9
10fn testBitReverse() void {
11 // using comptime_ints, unsigned
12 assert(@bitreverse(u0, 0) == 0);
13 assert(@bitreverse(u5, 0x12) == 0x9);
14 assert(@bitreverse(u8, 0x12) == 0x48);
15 assert(@bitreverse(u16, 0x1234) == 0x2c48);
16 assert(@bitreverse(u24, 0x123456) == 0x6a2c48);
17 assert(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
18 assert(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
19 assert(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
20 assert(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
21 assert(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
22 assert(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
23
24 // using runtime uints, unsigned
25 var num0: u0 = 0;
26 assert(@bitreverse(u0, num0) == 0);
27 var num5: u5 = 0x12;
28 assert(@bitreverse(u5, num5) == 0x9);
29 var num8: u8 = 0x12;
30 assert(@bitreverse(u8, num8) == 0x48);
31 var num16: u16 = 0x1234;
32 assert(@bitreverse(u16, num16) == 0x2c48);
33 var num24: u24 = 0x123456;
34 assert(@bitreverse(u24, num24) == 0x6a2c48);
35 var num32: u32 = 0x12345678;
36 assert(@bitreverse(u32, num32) == 0x1e6a2c48);
37 var num40: u40 = 0x123456789a;
38 assert(@bitreverse(u40, num40) == 0x591e6a2c48);
39 var num48: u48 = 0x123456789abc;
40 assert(@bitreverse(u48, num48) == 0x3d591e6a2c48);
41 var num56: u56 = 0x123456789abcde;
42 assert(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
43 var num64: u64 = 0x123456789abcdef1;
44 assert(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
45 var num128: u128 = 0x123456789abcdef11121314151617181;
46 assert(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
47
48 // using comptime_ints, signed, positive
49 assert(@bitreverse(i0, 0) == 0);
50 assert(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8( 0x49)));
51 assert(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16( 0x2c48)));
52 assert(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24( 0x6a2c48)));
53 assert(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32( 0x1e6a2c48)));
54 assert(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40( 0x591e6a2c48)));
55 assert(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48( 0x3d591e6a2c48)));
56 assert(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56( 0x7b3d591e6a2c48)));
57 assert(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64,u64(0x8f7b3d591e6a2c48)));
58 assert(@bitreverse(i128, @bitCast(i128,u128(0x123456789abcdef11121314151617181))) == @bitCast(i128,u128(0x818e868a828c84888f7b3d591e6a2c48)));
59
60 // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
61 var neg5: i5 = minInt(i5) + 1;
62 assert(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
63 var neg8: i8 = -18;
64 assert(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
65 var neg16: i16 = -32694;
66 assert(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
67 var neg24: i24 = -6773785;
68 assert(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
69 var neg32: i32 = -16773785;
70 assert(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
71 var neg40: i40 = minInt(i40) + 12345;
72 assert(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
73 var neg48: i48 = minInt(i48) + 12345;
74 assert(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
75 var neg56: i56 = minInt(i56) + 12345;
76 assert(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
77 var neg64: i64 = minInt(i64) + 12345;
78 assert(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
79 var neg128: i128 = minInt(i128) + 12345;
80 assert(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
81}
test/cases/bool.zig deleted-35
...@@ -1,35 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "bool literals" {
4 assert(true);
5 assert(!false);
6}
7
8test "cast bool to int" {
9 const t = true;
10 const f = false;
11 assert(@boolToInt(t) == u32(1));
12 assert(@boolToInt(f) == u32(0));
13 nonConstCastBoolToInt(t, f);
14}
15
16fn nonConstCastBoolToInt(t: bool, f: bool) void {
17 assert(@boolToInt(t) == u32(1));
18 assert(@boolToInt(f) == u32(0));
19}
20
21test "bool cmp" {
22 assert(testBoolCmp(true, false) == false);
23}
24fn testBoolCmp(a: bool, b: bool) bool {
25 return a == b;
26}
27
28const global_f = false;
29const global_t = true;
30const not_global_f = !global_f;
31const not_global_t = !global_t;
32test "compile time bool not" {
33 assert(not_global_f);
34 assert(!not_global_t);
35}
test/cases/bswap.zig deleted-32
...@@ -1,32 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "@bswap" {
5 comptime testByteSwap();
6 testByteSwap();
7}
8
9fn testByteSwap() void {
10 assert(@bswap(u0, 0) == 0);
11 assert(@bswap(u8, 0x12) == 0x12);
12 assert(@bswap(u16, 0x1234) == 0x3412);
13 assert(@bswap(u24, 0x123456) == 0x563412);
14 assert(@bswap(u32, 0x12345678) == 0x78563412);
15 assert(@bswap(u40, 0x123456789a) == 0x9a78563412);
16 assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
17 assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
18 assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
19 assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
20
21 assert(@bswap(i0, 0) == 0);
22 assert(@bswap(i8, -50) == -50);
23 assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
24 assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
25 assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
26 assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
27 assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
28 assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
29 assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
30 assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
31 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
32}
test/cases/bugs/1076.zig deleted-16
...@@ -1,16 +0,0 @@
1const std = @import("std");
2const mem = std.mem;
3const assert = std.debug.assert;
4
5test "comptime code should not modify constant data" {
6 testCastPtrOfArrayToSliceAndPtr();
7 comptime testCastPtrOfArrayToSliceAndPtr();
8}
9
10fn testCastPtrOfArrayToSliceAndPtr() void {
11 var array = "aoeu";
12 const x: [*]u8 = &array;
13 x[0] += 1;
14 assert(mem.eql(u8, array[0..], "boeu"));
15}
16
test/cases/bugs/1111.zig deleted-12
...@@ -1,12 +0,0 @@
1const Foo = extern enum {
2 Bar = -1,
3};
4
5test "issue 1111 fixed" {
6 const v = Foo.Bar;
7
8 switch (v) {
9 Foo.Bar => return,
10 else => return,
11 }
12}
test/cases/bugs/1277.zig deleted-15
...@@ -1,15 +0,0 @@
1const std = @import("std");
2
3const S = struct {
4 f: ?fn () i32,
5};
6
7const s = S{ .f = f };
8
9fn f() i32 {
10 return 1234;
11}
12
13test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
14 std.debug.assertOrPanic(s.f.?() == 1234);
15}
test/cases/bugs/1322.zig deleted-19
...@@ -1,19 +0,0 @@
1const std = @import("std");
2
3const B = union(enum) {
4 c: C,
5 None,
6};
7
8const A = struct {
9 b: B,
10};
11
12const C = struct {};
13
14test "tagged union with all void fields but a meaningful tag" {
15 var a: A = A{ .b = B{ .c = C{} } };
16 std.debug.assert(@TagType(B)(a.b) == @TagType(B).c);
17 a = A{ .b = B.None };
18 std.debug.assert(@TagType(B)(a.b) == @TagType(B).None);
19}
test/cases/bugs/1381.zig deleted-21
...@@ -1,21 +0,0 @@
1const std = @import("std");
2
3const B = union(enum) {
4 D: u8,
5 E: u16,
6};
7
8const A = union(enum) {
9 B: B,
10 C: u8,
11};
12
13test "union that needs padding bytes inside an array" {
14 var as = []A{
15 A{ .B = B{ .D = 1 } },
16 A{ .B = B{ .D = 1 } },
17 };
18
19 const a = as[0].B;
20 std.debug.assertOrPanic(a.D == 1);
21}
test/cases/bugs/1421.zig deleted-14
...@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5const S = struct {
6 fn method() builtin.TypeInfo {
7 return @typeInfo(S);
8 }
9};
10
11test "functions with return type required to be comptime are generic" {
12 const ti = S.method();
13 assert(builtin.TypeId(ti) == builtin.TypeId.Struct);
14}
test/cases/bugs/1442.zig deleted-11
...@@ -1,11 +0,0 @@
1const std = @import("std");
2
3const Union = union(enum) {
4 Text: []const u8,
5 Color: u32,
6};
7
8test "const error union field alignment" {
9 var union_or_err: anyerror!Union = Union{ .Color = 1234 };
10 std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
11}
test/cases/bugs/1486.zig deleted-11
...@@ -1,11 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 assert(&global == ptr);
9 assert(ptr.* == 1234);
10}
11
test/cases/bugs/394.zig deleted-18
...@@ -1,18 +0,0 @@
1const E = union(enum) {
2 A: [9]u8,
3 B: u64,
4};
5const S = struct {
6 x: u8,
7 y: E,
8};
9
10const assert = @import("std").debug.assert;
11
12test "bug 394 fixed" {
13 const x = S{
14 .x = 3,
15 .y = E{ .B = 1 },
16 };
17 assert(x.x == 3);
18}
test/cases/bugs/655.zig deleted-12
...@@ -1,12 +0,0 @@
1const std = @import("std");
2const other_file = @import("655_other_file.zig");
3
4test "function with *const parameter with type dereferenced by namespace" {
5 const x: other_file.Integer = 1234;
6 comptime std.debug.assert(@typeOf(&x) == *const other_file.Integer);
7 foo(&x);
8}
9
10fn foo(x: *const other_file.Integer) void {
11 std.debug.assert(x.* == 1234);
12}
test/cases/bugs/655_other_file.zig deleted-1
...@@ -1 +0,0 @@
1pub const Integer = u32;
test/cases/bugs/656.zig deleted-31
...@@ -1,31 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const PrefixOp = union(enum) {
4 Return,
5 AddrOf: Value,
6};
7
8const Value = struct {
9 align_expr: ?u32,
10};
11
12test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
13 foo(false, true);
14}
15
16fn foo(a: bool, b: bool) void {
17 var prefix_op = PrefixOp{
18 .AddrOf = Value{ .align_expr = 1234 },
19 };
20 if (a) {} else {
21 switch (prefix_op) {
22 PrefixOp.AddrOf => |addr_of_info| {
23 if (b) {}
24 if (addr_of_info.align_expr) |align_expr| {
25 assert(align_expr == 1234);
26 }
27 },
28 PrefixOp.Return => {},
29 }
30 }
31}
test/cases/bugs/726.zig deleted-16
...@@ -1,16 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "@ptrCast from const to nullable" {
4 const c: u8 = 4;
5 var x: ?*const u8 = @ptrCast(?*const u8, &c);
6 assert(x.?.* == 4);
7}
8
9test "@ptrCast from var in empty struct to nullable" {
10 const container = struct {
11 var c: u8 = 4;
12 };
13 var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
14 assert(x.?.* == 4);
15}
16
test/cases/bugs/828.zig deleted-33
...@@ -1,33 +0,0 @@
1const CountBy = struct {
2 a: usize,
3
4 const One = CountBy{ .a = 1 };
5
6 pub fn counter(self: *const CountBy) Counter {
7 return Counter{ .i = 0 };
8 }
9};
10
11const Counter = struct {
12 i: usize,
13
14 pub fn count(self: *Counter) bool {
15 self.i += 1;
16 return self.i <= 10;
17 }
18};
19
20fn constCount(comptime cb: *const CountBy, comptime unused: u32) void {
21 comptime {
22 var cnt = cb.counter();
23 if (cnt.i != 0) @compileError("Counter instance reused!");
24 while (cnt.count()) {}
25 }
26}
27
28test "comptime struct return should not return the same instance" {
29 //the first parameter must be passed by reference to trigger the bug
30 //a second parameter is required to trigger the bug
31 const ValA = constCount(&CountBy.One, 12);
32 const ValB = constCount(&CountBy.One, 15);
33}
test/cases/bugs/920.zig deleted-65
...@@ -1,65 +0,0 @@
1const std = @import("std");
2const math = std.math;
3const Random = std.rand.Random;
4
5const ZigTable = struct {
6 r: f64,
7 x: [257]f64,
8 f: [257]f64,
9
10 pdf: fn (f64) f64,
11 is_symmetric: bool,
12 zero_case: fn (*Random, f64) f64,
13};
14
15fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable {
16 var tables: ZigTable = undefined;
17
18 tables.is_symmetric = is_symmetric;
19 tables.r = r;
20 tables.pdf = f;
21 tables.zero_case = zero_case;
22
23 tables.x[0] = v / f(r);
24 tables.x[1] = r;
25
26 for (tables.x[2..256]) |*entry, i| {
27 const last = tables.x[2 + i - 1];
28 entry.* = f_inv(v / last + f(last));
29 }
30 tables.x[256] = 0;
31
32 for (tables.f[0..]) |*entry, i| {
33 entry.* = f(tables.x[i]);
34 }
35
36 return tables;
37}
38
39const norm_r = 3.6541528853610088;
40const norm_v = 0.00492867323399;
41
42fn norm_f(x: f64) f64 {
43 return math.exp(-x * x / 2.0);
44}
45fn norm_f_inv(y: f64) f64 {
46 return math.sqrt(-2.0 * math.ln(y));
47}
48fn norm_zero_case(random: *Random, u: f64) f64 {
49 return 0.0;
50}
51
52const NormalDist = blk: {
53 @setEvalBranchQuota(30000);
54 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
55};
56
57test "bug 920 fixed" {
58 const NormalDist1 = blk: {
59 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
60 };
61
62 for (NormalDist1.f) |_, i| {
63 std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]);
64 }
65}
test/cases/byval_arg_var.zig deleted-27
...@@ -1,27 +0,0 @@
1const std = @import("std");
2
3var result: []const u8 = "wrong";
4
5test "aoeu" {
6 start();
7 blowUpStack(10);
8
9 std.debug.assert(std.mem.eql(u8, result, "string literal"));
10}
11
12fn start() void {
13 foo("string literal");
14}
15
16fn foo(x: var) void {
17 bar(x);
18}
19
20fn bar(x: var) void {
21 result = x;
22}
23
24fn blowUpStack(x: u32) void {
25 if (x == 0) return;
26 blowUpStack(x - 1);
27}
test/cases/cancel.zig deleted-92
...@@ -1,92 +0,0 @@
1const std = @import("std");
2
3var defer_f1: bool = false;
4var defer_f2: bool = false;
5var defer_f3: bool = false;
6
7test "cancel forwards" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = async<&da.allocator> f1() catch unreachable;
12 cancel p;
13 std.debug.assert(defer_f1);
14 std.debug.assert(defer_f2);
15 std.debug.assert(defer_f3);
16}
17
18async fn f1() void {
19 defer {
20 defer_f1 = true;
21 }
22 await (async f2() catch unreachable);
23}
24
25async fn f2() void {
26 defer {
27 defer_f2 = true;
28 }
29 await (async f3() catch unreachable);
30}
31
32async fn f3() void {
33 defer {
34 defer_f3 = true;
35 }
36 suspend;
37}
38
39var defer_b1: bool = false;
40var defer_b2: bool = false;
41var defer_b3: bool = false;
42var defer_b4: bool = false;
43
44test "cancel backwards" {
45 var da = std.heap.DirectAllocator.init();
46 defer da.deinit();
47
48 const p = async<&da.allocator> b1() catch unreachable;
49 cancel p;
50 std.debug.assert(defer_b1);
51 std.debug.assert(defer_b2);
52 std.debug.assert(defer_b3);
53 std.debug.assert(defer_b4);
54}
55
56async fn b1() void {
57 defer {
58 defer_b1 = true;
59 }
60 await (async b2() catch unreachable);
61}
62
63var b4_handle: promise = undefined;
64
65async fn b2() void {
66 const b3_handle = async b3() catch unreachable;
67 resume b4_handle;
68 cancel b4_handle;
69 defer {
70 defer_b2 = true;
71 }
72 const value = await b3_handle;
73 @panic("unreachable");
74}
75
76async fn b3() i32 {
77 defer {
78 defer_b3 = true;
79 }
80 await (async b4() catch unreachable);
81 return 1234;
82}
83
84async fn b4() void {
85 defer {
86 defer_b4 = true;
87 }
88 suspend {
89 b4_handle = @handle();
90 }
91 suspend;
92}
test/cases/cast.zig deleted-472
...@@ -1,472 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5
6test "int to ptr cast" {
7 const x = usize(13);
8 const y = @intToPtr(*u8, x);
9 const z = @ptrToInt(y);
10 assert(z == 13);
11}
12
13test "integer literal to pointer cast" {
14 const vga_mem = @intToPtr(*u16, 0xB8000);
15 assert(@ptrToInt(vga_mem) == 0xB8000);
16}
17
18test "pointer reinterpret const float to int" {
19 const float: f64 = 5.99999999999994648725e-01;
20 const float_ptr = &float;
21 const int_ptr = @ptrCast(*const i32, float_ptr);
22 const int_val = int_ptr.*;
23 assert(int_val == 858993411);
24}
25
26test "implicitly cast indirect pointer to maybe-indirect pointer" {
27 const S = struct {
28 const Self = @This();
29 x: u8,
30 fn constConst(p: *const *const Self) u8 {
31 return p.*.x;
32 }
33 fn maybeConstConst(p: ?*const *const Self) u8 {
34 return p.?.*.x;
35 }
36 fn constConstConst(p: *const *const *const Self) u8 {
37 return p.*.*.x;
38 }
39 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
40 return p.?.*.*.x;
41 }
42 };
43 const s = S{ .x = 42 };
44 const p = &s;
45 const q = &p;
46 const r = &q;
47 assert(42 == S.constConst(q));
48 assert(42 == S.maybeConstConst(q));
49 assert(42 == S.constConstConst(r));
50 assert(42 == S.maybeConstConstConst(r));
51}
52
53test "explicit cast from integer to error type" {
54 testCastIntToErr(error.ItBroke);
55 comptime testCastIntToErr(error.ItBroke);
56}
57fn testCastIntToErr(err: anyerror) void {
58 const x = @errorToInt(err);
59 const y = @intToError(x);
60 assert(error.ItBroke == y);
61}
62
63test "peer resolve arrays of different size to const slice" {
64 assert(mem.eql(u8, boolToStr(true), "true"));
65 assert(mem.eql(u8, boolToStr(false), "false"));
66 comptime assert(mem.eql(u8, boolToStr(true), "true"));
67 comptime assert(mem.eql(u8, boolToStr(false), "false"));
68}
69fn boolToStr(b: bool) []const u8 {
70 return if (b) "true" else "false";
71}
72
73test "peer resolve array and const slice" {
74 testPeerResolveArrayConstSlice(true);
75 comptime testPeerResolveArrayConstSlice(true);
76}
77fn testPeerResolveArrayConstSlice(b: bool) void {
78 const value1 = if (b) "aoeu" else ([]const u8)("zz");
79 const value2 = if (b) ([]const u8)("zz") else "aoeu";
80 assert(mem.eql(u8, value1, "aoeu"));
81 assert(mem.eql(u8, value2, "zz"));
82}
83
84test "implicitly cast from T to anyerror!?T" {
85 castToOptionalTypeError(1);
86 comptime castToOptionalTypeError(1);
87}
88const A = struct {
89 a: i32,
90};
91fn castToOptionalTypeError(z: i32) void {
92 const x = i32(1);
93 const y: anyerror!?i32 = x;
94 assert((try y).? == 1);
95
96 const f = z;
97 const g: anyerror!?i32 = f;
98
99 const a = A{ .a = z };
100 const b: anyerror!?A = a;
101 assert((b catch unreachable).?.a == 1);
102}
103
104test "implicitly cast from int to anyerror!?T" {
105 implicitIntLitToOptional();
106 comptime implicitIntLitToOptional();
107}
108fn implicitIntLitToOptional() void {
109 const f: ?i32 = 1;
110 const g: anyerror!?i32 = 1;
111}
112
113test "return null from fn() anyerror!?&T" {
114 const a = returnNullFromOptionalTypeErrorRef();
115 const b = returnNullLitFromOptionalTypeErrorRef();
116 assert((try a) == null and (try b) == null);
117}
118fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
119 const a: ?*A = null;
120 return a;
121}
122fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
123 return null;
124}
125
126test "peer type resolution: ?T and T" {
127 assert(peerTypeTAndOptionalT(true, false).? == 0);
128 assert(peerTypeTAndOptionalT(false, false).? == 3);
129 comptime {
130 assert(peerTypeTAndOptionalT(true, false).? == 0);
131 assert(peerTypeTAndOptionalT(false, false).? == 3);
132 }
133}
134fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
135 if (c) {
136 return if (b) null else usize(0);
137 }
138
139 return usize(3);
140}
141
142test "peer type resolution: [0]u8 and []const u8" {
143 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
144 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
145 comptime {
146 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
147 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
148 }
149}
150fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
151 if (a) {
152 return []const u8{};
153 }
154
155 return slice[0..1];
156}
157
158test "implicitly cast from [N]T to ?[]const T" {
159 assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
160 comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
161}
162
163fn castToOptionalSlice() ?[]const u8 {
164 return "hi";
165}
166
167test "implicitly cast from [0]T to anyerror![]T" {
168 testCastZeroArrayToErrSliceMut();
169 comptime testCastZeroArrayToErrSliceMut();
170}
171
172fn testCastZeroArrayToErrSliceMut() void {
173 assert((gimmeErrOrSlice() catch unreachable).len == 0);
174}
175
176fn gimmeErrOrSlice() anyerror![]u8 {
177 return []u8{};
178}
179
180test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
181 {
182 var data = "hi";
183 const slice = data[0..];
184 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
185 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
186 }
187 comptime {
188 var data = "hi";
189 const slice = data[0..];
190 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
191 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
192 }
193}
194fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
195 if (a) {
196 return []u8{};
197 }
198
199 return slice[0..1];
200}
201
202test "resolve undefined with integer" {
203 testResolveUndefWithInt(true, 1234);
204 comptime testResolveUndefWithInt(true, 1234);
205}
206fn testResolveUndefWithInt(b: bool, x: i32) void {
207 const value = if (b) x else undefined;
208 if (b) {
209 assert(value == x);
210 }
211}
212
213test "implicit cast from &const [N]T to []const T" {
214 testCastConstArrayRefToConstSlice();
215 comptime testCastConstArrayRefToConstSlice();
216}
217
218fn testCastConstArrayRefToConstSlice() void {
219 const blah = "aoeu";
220 const const_array_ref = &blah;
221 assert(@typeOf(const_array_ref) == *const [4]u8);
222 const slice: []const u8 = const_array_ref;
223 assert(mem.eql(u8, slice, "aoeu"));
224}
225
226test "peer type resolution: error and [N]T" {
227 // TODO: implicit error!T to error!U where T can implicitly cast to U
228 //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
229 //comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
230 assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
231 comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
232}
233
234//fn testPeerErrorAndArray(x: u8) error![]const u8 {
235// return switch (x) {
236// 0x00 => "OK",
237// else => error.BadValue,
238// };
239//}
240fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
241 return switch (x) {
242 0x00 => "OK",
243 0x01 => "OKK",
244 else => error.BadValue,
245 };
246}
247
248test "@floatToInt" {
249 testFloatToInts();
250 comptime testFloatToInts();
251}
252
253fn testFloatToInts() void {
254 const x = i32(1e4);
255 assert(x == 10000);
256 const y = @floatToInt(i32, f32(1e4));
257 assert(y == 10000);
258 expectFloatToInt(f16, 255.1, u8, 255);
259 expectFloatToInt(f16, 127.2, i8, 127);
260 expectFloatToInt(f16, -128.2, i8, -128);
261 expectFloatToInt(f32, 255.1, u8, 255);
262 expectFloatToInt(f32, 127.2, i8, 127);
263 expectFloatToInt(f32, -128.2, i8, -128);
264 expectFloatToInt(comptime_int, 1234, i16, 1234);
265}
266
267fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {
268 assert(@floatToInt(I, f) == i);
269}
270
271test "cast u128 to f128 and back" {
272 comptime testCast128();
273 testCast128();
274}
275
276fn testCast128() void {
277 assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
278}
279
280fn cast128Int(x: f128) u128 {
281 return @bitCast(u128, x);
282}
283
284fn cast128Float(x: u128) f128 {
285 return @bitCast(f128, x);
286}
287
288test "const slice widen cast" {
289 const bytes align(4) = []u8{
290 0x12,
291 0x12,
292 0x12,
293 0x12,
294 };
295
296 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
297 assert(u32_value == 0x12121212);
298
299 assert(@bitCast(u32, bytes) == 0x12121212);
300}
301
302test "single-item pointer of array to slice and to unknown length pointer" {
303 testCastPtrOfArrayToSliceAndPtr();
304 comptime testCastPtrOfArrayToSliceAndPtr();
305}
306
307fn testCastPtrOfArrayToSliceAndPtr() void {
308 var array = "aoeu";
309 const x: [*]u8 = &array;
310 x[0] += 1;
311 assert(mem.eql(u8, array[0..], "boeu"));
312 const y: []u8 = &array;
313 y[0] += 1;
314 assert(mem.eql(u8, array[0..], "coeu"));
315}
316
317test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
318 const window_name = [1][*]const u8{c"window name"};
319 const x: [*]const ?[*]const u8 = &window_name;
320 assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
321}
322
323test "@intCast comptime_int" {
324 const result = @intCast(i32, 1234);
325 assert(@typeOf(result) == i32);
326 assert(result == 1234);
327}
328
329test "@floatCast comptime_int and comptime_float" {
330 {
331 const result = @floatCast(f16, 1234);
332 assert(@typeOf(result) == f16);
333 assert(result == 1234.0);
334 }
335 {
336 const result = @floatCast(f16, 1234.0);
337 assert(@typeOf(result) == f16);
338 assert(result == 1234.0);
339 }
340 {
341 const result = @floatCast(f32, 1234);
342 assert(@typeOf(result) == f32);
343 assert(result == 1234.0);
344 }
345 {
346 const result = @floatCast(f32, 1234.0);
347 assert(@typeOf(result) == f32);
348 assert(result == 1234.0);
349 }
350}
351
352test "comptime_int @intToFloat" {
353 {
354 const result = @intToFloat(f16, 1234);
355 assert(@typeOf(result) == f16);
356 assert(result == 1234.0);
357 }
358 {
359 const result = @intToFloat(f32, 1234);
360 assert(@typeOf(result) == f32);
361 assert(result == 1234.0);
362 }
363}
364
365test "@bytesToSlice keeps pointer alignment" {
366 var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
367 const numbers = @bytesToSlice(u32, bytes[0..]);
368 comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
369}
370
371test "@intCast i32 to u7" {
372 var x: u128 = maxInt(u128);
373 var y: i32 = 120;
374 var z = x >> @intCast(u7, y);
375 assert(z == 0xff);
376}
377
378test "implicit cast undefined to optional" {
379 assert(MakeType(void).getNull() == null);
380 assert(MakeType(void).getNonNull() != null);
381}
382
383fn MakeType(comptime T: type) type {
384 return struct {
385 fn getNull() ?T {
386 return null;
387 }
388
389 fn getNonNull() ?T {
390 return T(undefined);
391 }
392 };
393}
394
395test "implicit cast from *[N]T to ?[*]T" {
396 var x: ?[*]u16 = null;
397 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
398
399 x = &y;
400 assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
401 x.?[0] = 8;
402 y[3] = 6;
403 assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
404}
405
406test "implicit cast from *T to ?*c_void" {
407 var a: u8 = 1;
408 incrementVoidPtrValue(&a);
409 std.debug.assert(a == 2);
410}
411
412fn incrementVoidPtrValue(value: ?*c_void) void {
413 @ptrCast(*u8, value.?).* += 1;
414}
415
416test "implicit cast from [*]T to ?*c_void" {
417 var a = []u8{ 3, 2, 1 };
418 incrementVoidPtrArray(a[0..].ptr, 3);
419 assert(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
420}
421
422fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
423 var n: usize = 0;
424 while (n < len) : (n += 1) {
425 @ptrCast([*]u8, array.?)[n] += 1;
426 }
427}
428
429test "*usize to *void" {
430 var i = usize(0);
431 var v = @ptrCast(*void, &i);
432 v.* = {};
433}
434
435test "compile time int to ptr of function" {
436 foobar(FUNCTION_CONSTANT);
437}
438
439pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
440pub const PFN_void = extern fn (*c_void) void;
441
442fn foobar(func: PFN_void) void {
443 std.debug.assert(@ptrToInt(func) == maxInt(usize));
444}
445
446test "implicit ptr to *c_void" {
447 var a: u32 = 1;
448 var ptr: *c_void = &a;
449 var b: *u32 = @ptrCast(*u32, ptr);
450 assert(b.* == 1);
451 var ptr2: ?*c_void = &a;
452 var c: *u32 = @ptrCast(*u32, ptr2.?);
453 assert(c.* == 1);
454}
455
456test "@intCast to comptime_int" {
457 assert(@intCast(comptime_int, 0) == 0);
458}
459
460test "implicit cast comptime numbers to any type when the value fits" {
461 const a: u64 = 255;
462 var b: u8 = a;
463 assert(b == 255);
464}
465
466test "@intToEnum passed a comptime_int to an enum with one item" {
467 const E = enum {
468 A,
469 };
470 const x = @intToEnum(E, 0);
471 assert(x == E.A);
472}
test/cases/const_slice_child.zig deleted-45
...@@ -1,45 +0,0 @@
1const debug = @import("std").debug;
2const assert = debug.assert;
3
4var argv: [*]const [*]const u8 = undefined;
5
6test "const slice child" {
7 const strs = ([][*]const u8){
8 c"one",
9 c"two",
10 c"three",
11 };
12 // TODO this should implicitly cast
13 argv = @ptrCast([*]const [*]const u8, &strs);
14 bar(strs.len);
15}
16
17fn foo(args: [][]const u8) void {
18 assert(args.len == 3);
19 assert(streql(args[0], "one"));
20 assert(streql(args[1], "two"));
21 assert(streql(args[2], "three"));
22}
23
24fn bar(argc: usize) void {
25 const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable;
26 for (args) |_, i| {
27 const ptr = argv[i];
28 args[i] = ptr[0..strlen(ptr)];
29 }
30 foo(args);
31}
32
33fn strlen(ptr: [*]const u8) usize {
34 var count: usize = 0;
35 while (ptr[count] != 0) : (count += 1) {}
36 return count;
37}
38
39fn streql(a: []const u8, b: []const u8) bool {
40 if (a.len != b.len) return false;
41 for (a) |item, index| {
42 if (b[index] != item) return false;
43 }
44 return true;
45}
test/cases/coroutine_await_struct.zig deleted-47
...@@ -1,47 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: promise = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 var da = std.heap.DirectAllocator.init();
14 defer da.deinit();
15
16 await_seq('a');
17 const p = async<&da.allocator> await_amain() catch unreachable;
18 await_seq('f');
19 resume await_a_promise;
20 await_seq('i');
21 assert(await_final_result.x == 1234);
22 assert(std.mem.eql(u8, await_points, "abcdefghi"));
23}
24async fn await_amain() void {
25 await_seq('b');
26 const p = async await_another() catch unreachable;
27 await_seq('e');
28 await_final_result = await p;
29 await_seq('h');
30}
31async fn await_another() Foo {
32 await_seq('c');
33 suspend {
34 await_seq('d');
35 await_a_promise = @handle();
36 }
37 await_seq('g');
38 return Foo{ .x = 1234 };
39}
40
41var await_points = []u8{0} ** "abcdefghi".len;
42var await_seq_index: usize = 0;
43
44fn await_seq(c: u8) void {
45 await_points[await_seq_index] = c;
46 await_seq_index += 1;
47}
test/cases/coroutines.zig deleted-258
...@@ -1,258 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5var x: i32 = 1;
6
7test "create a coroutine and cancel it" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = try async<&da.allocator> simpleAsyncFn();
12 comptime assert(@typeOf(p) == promise->void);
13 cancel p;
14 assert(x == 2);
15}
16async fn simpleAsyncFn() void {
17 x += 1;
18 suspend;
19 x += 1;
20}
21
22test "coroutine suspend, resume, cancel" {
23 var da = std.heap.DirectAllocator.init();
24 defer da.deinit();
25
26 seq('a');
27 const p = try async<&da.allocator> testAsyncSeq();
28 seq('c');
29 resume p;
30 seq('f');
31 cancel p;
32 seq('g');
33
34 assert(std.mem.eql(u8, points, "abcdefg"));
35}
36async fn testAsyncSeq() void {
37 defer seq('e');
38
39 seq('b');
40 suspend;
41 seq('d');
42}
43var points = []u8{0} ** "abcdefg".len;
44var index: usize = 0;
45
46fn seq(c: u8) void {
47 points[index] = c;
48 index += 1;
49}
50
51test "coroutine suspend with block" {
52 var da = std.heap.DirectAllocator.init();
53 defer da.deinit();
54
55 const p = try async<&da.allocator> testSuspendBlock();
56 std.debug.assert(!result);
57 resume a_promise;
58 std.debug.assert(result);
59 cancel p;
60}
61
62var a_promise: promise = undefined;
63var result = false;
64async fn testSuspendBlock() void {
65 suspend {
66 comptime assert(@typeOf(@handle()) == promise->void);
67 a_promise = @handle();
68 }
69
70 //Test to make sure that @handle() works as advertised (issue #1296)
71 //var our_handle: promise = @handle();
72 assert( a_promise == @handle() );
73
74 result = true;
75}
76
77var await_a_promise: promise = undefined;
78var await_final_result: i32 = 0;
79
80test "coroutine await" {
81 var da = std.heap.DirectAllocator.init();
82 defer da.deinit();
83
84 await_seq('a');
85 const p = async<&da.allocator> await_amain() catch unreachable;
86 await_seq('f');
87 resume await_a_promise;
88 await_seq('i');
89 assert(await_final_result == 1234);
90 assert(std.mem.eql(u8, await_points, "abcdefghi"));
91}
92async fn await_amain() void {
93 await_seq('b');
94 const p = async await_another() catch unreachable;
95 await_seq('e');
96 await_final_result = await p;
97 await_seq('h');
98}
99async fn await_another() i32 {
100 await_seq('c');
101 suspend {
102 await_seq('d');
103 await_a_promise = @handle();
104 }
105 await_seq('g');
106 return 1234;
107}
108
109var await_points = []u8{0} ** "abcdefghi".len;
110var await_seq_index: usize = 0;
111
112fn await_seq(c: u8) void {
113 await_points[await_seq_index] = c;
114 await_seq_index += 1;
115}
116
117var early_final_result: i32 = 0;
118
119test "coroutine await early return" {
120 var da = std.heap.DirectAllocator.init();
121 defer da.deinit();
122
123 early_seq('a');
124 const p = async<&da.allocator> early_amain() catch @panic("out of memory");
125 early_seq('f');
126 assert(early_final_result == 1234);
127 assert(std.mem.eql(u8, early_points, "abcdef"));
128}
129async fn early_amain() void {
130 early_seq('b');
131 const p = async early_another() catch @panic("out of memory");
132 early_seq('d');
133 early_final_result = await p;
134 early_seq('e');
135}
136async fn early_another() i32 {
137 early_seq('c');
138 return 1234;
139}
140
141var early_points = []u8{0} ** "abcdef".len;
142var early_seq_index: usize = 0;
143
144fn early_seq(c: u8) void {
145 early_points[early_seq_index] = c;
146 early_seq_index += 1;
147}
148
149test "coro allocation failure" {
150 var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0);
151 if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) {
152 @panic("expected allocation failure");
153 } else |err| switch (err) {
154 error.OutOfMemory => {},
155 }
156}
157async fn asyncFuncThatNeverGetsRun() void {
158 @panic("coro frame allocation should fail");
159}
160
161test "async function with dot syntax" {
162 const S = struct {
163 var y: i32 = 1;
164 async fn foo() void {
165 y += 1;
166 suspend;
167 }
168 };
169 var da = std.heap.DirectAllocator.init();
170 defer da.deinit();
171 const p = try async<&da.allocator> S.foo();
172 cancel p;
173 assert(S.y == 2);
174}
175
176test "async fn pointer in a struct field" {
177 var data: i32 = 1;
178 const Foo = struct {
179 bar: async<*std.mem.Allocator> fn (*i32) void,
180 };
181 var foo = Foo{ .bar = simpleAsyncFn2 };
182 var da = std.heap.DirectAllocator.init();
183 defer da.deinit();
184 const p = (async<&da.allocator> foo.bar(&data)) catch unreachable;
185 assert(data == 2);
186 cancel p;
187 assert(data == 4);
188}
189async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
190 defer y.* += 2;
191 y.* += 1;
192 suspend;
193}
194
195test "async fn with inferred error set" {
196 var da = std.heap.DirectAllocator.init();
197 defer da.deinit();
198 const p = (async<&da.allocator> failing()) catch unreachable;
199 resume p;
200 cancel p;
201}
202async fn failing() !void {
203 suspend;
204 return error.Fail;
205}
206
207test "error return trace across suspend points - early return" {
208 const p = nonFailing();
209 resume p;
210 var da = std.heap.DirectAllocator.init();
211 defer da.deinit();
212 const p2 = try async<&da.allocator> printTrace(p);
213 cancel p2;
214}
215
216test "error return trace across suspend points - async return" {
217 const p = nonFailing();
218 const p2 = try async<std.debug.global_allocator> printTrace(p);
219 resume p;
220 cancel p2;
221}
222
223// TODO https://github.com/ziglang/zig/issues/760
224fn nonFailing() promise->(anyerror!void) {
225 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
226}
227async fn suspendThenFail() anyerror!void {
228 suspend;
229 return error.Fail;
230}
231async fn printTrace(p: promise->(anyerror!void)) void {
232 (await p) catch |e| {
233 std.debug.assert(e == error.Fail);
234 if (@errorReturnTrace()) |trace| {
235 assert(trace.index == 1);
236 } else switch (builtin.mode) {
237 builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
238 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
239 }
240 };
241}
242
243test "break from suspend" {
244 var buf: [500]u8 = undefined;
245 var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
246 var my_result: i32 = 1;
247 const p = try async<a> testBreakFromSuspend(&my_result);
248 cancel p;
249 std.debug.assert(my_result == 2);
250}
251async fn testBreakFromSuspend(my_result: *i32) void {
252 suspend {
253 resume @handle();
254 }
255 my_result.* += 1;
256 suspend;
257 my_result.* += 1;
258}
test/cases/defer.zig deleted-78
...@@ -1,78 +0,0 @@
1const assert = @import("std").debug.assert;
2
3var result: [3]u8 = undefined;
4var index: usize = undefined;
5
6fn runSomeErrorDefers(x: bool) !bool {
7 index = 0;
8 defer {
9 result[index] = 'a';
10 index += 1;
11 }
12 errdefer {
13 result[index] = 'b';
14 index += 1;
15 }
16 defer {
17 result[index] = 'c';
18 index += 1;
19 }
20 return if (x) x else error.FalseNotAllowed;
21}
22
23test "mixing normal and error defers" {
24 assert(runSomeErrorDefers(true) catch unreachable);
25 assert(result[0] == 'c');
26 assert(result[1] == 'a');
27
28 const ok = runSomeErrorDefers(false) catch |err| x: {
29 assert(err == error.FalseNotAllowed);
30 break :x true;
31 };
32 assert(ok);
33 assert(result[0] == 'c');
34 assert(result[1] == 'b');
35 assert(result[2] == 'a');
36}
37
38test "break and continue inside loop inside defer expression" {
39 testBreakContInDefer(10);
40 comptime testBreakContInDefer(10);
41}
42
43fn testBreakContInDefer(x: usize) void {
44 defer {
45 var i: usize = 0;
46 while (i < x) : (i += 1) {
47 if (i < 5) continue;
48 if (i == 5) break;
49 }
50 assert(i == 5);
51 }
52}
53
54test "defer and labeled break" {
55 var i = usize(0);
56
57 blk: {
58 defer i += 1;
59 break :blk;
60 }
61
62 assert(i == 1);
63}
64
65test "errdefer does not apply to fn inside fn" {
66 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad);
67}
68
69fn testNestedFnErrDefer() anyerror!void {
70 var a: i32 = 0;
71 errdefer a += 1;
72 const S = struct {
73 fn baz() anyerror {
74 return error.Bad;
75 }
76 };
77 return S.baz();
78}
test/cases/enum.zig deleted-894
...@@ -1,894 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4test "enum type" {
5 const foo1 = Foo{ .One = 13 };
6 const foo2 = Foo{
7 .Two = Point{
8 .x = 1234,
9 .y = 5678,
10 },
11 };
12 const bar = Bar.B;
13
14 assert(bar == Bar.B);
15 assert(@memberCount(Foo) == 3);
16 assert(@memberCount(Bar) == 4);
17 assert(@sizeOf(Foo) == @sizeOf(FooNoVoid));
18 assert(@sizeOf(Bar) == 1);
19}
20
21test "enum as return value" {
22 switch (returnAnInt(13)) {
23 Foo.One => |value| assert(value == 13),
24 else => unreachable,
25 }
26}
27
28const Point = struct {
29 x: u64,
30 y: u64,
31};
32const Foo = union(enum) {
33 One: i32,
34 Two: Point,
35 Three: void,
36};
37const FooNoVoid = union(enum) {
38 One: i32,
39 Two: Point,
40};
41const Bar = enum {
42 A,
43 B,
44 C,
45 D,
46};
47
48fn returnAnInt(x: i32) Foo {
49 return Foo{ .One = x };
50}
51
52test "constant enum with payload" {
53 var empty = AnEnumWithPayload{ .Empty = {} };
54 var full = AnEnumWithPayload{ .Full = 13 };
55 shouldBeEmpty(empty);
56 shouldBeNotEmpty(full);
57}
58
59fn shouldBeEmpty(x: AnEnumWithPayload) void {
60 switch (x) {
61 AnEnumWithPayload.Empty => {},
62 else => unreachable,
63 }
64}
65
66fn shouldBeNotEmpty(x: AnEnumWithPayload) void {
67 switch (x) {
68 AnEnumWithPayload.Empty => unreachable,
69 else => {},
70 }
71}
72
73const AnEnumWithPayload = union(enum) {
74 Empty: void,
75 Full: i32,
76};
77
78const Number = enum {
79 Zero,
80 One,
81 Two,
82 Three,
83 Four,
84};
85
86test "enum to int" {
87 shouldEqual(Number.Zero, 0);
88 shouldEqual(Number.One, 1);
89 shouldEqual(Number.Two, 2);
90 shouldEqual(Number.Three, 3);
91 shouldEqual(Number.Four, 4);
92}
93
94fn shouldEqual(n: Number, expected: u3) void {
95 assert(@enumToInt(n) == expected);
96}
97
98test "int to enum" {
99 testIntToEnumEval(3);
100}
101fn testIntToEnumEval(x: i32) void {
102 assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
103}
104const IntToEnumNumber = enum {
105 Zero,
106 One,
107 Two,
108 Three,
109 Four,
110};
111
112test "@tagName" {
113 assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
115}
116
117fn testEnumTagNameBare(n: BareNumber) []const u8 {
118 return @tagName(n);
119}
120
121const BareNumber = enum {
122 One,
123 Two,
124 Three,
125};
126
127test "enum alignment" {
128 comptime {
129 assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
130 assert(@alignOf(AlignTestEnum) >= @alignOf(u64));
131 }
132}
133
134const AlignTestEnum = union(enum) {
135 A: [9]u8,
136 B: u64,
137};
138
139const ValueCount1 = enum {
140 I0,
141};
142const ValueCount2 = enum {
143 I0,
144 I1,
145};
146const ValueCount256 = enum {
147 I0,
148 I1,
149 I2,
150 I3,
151 I4,
152 I5,
153 I6,
154 I7,
155 I8,
156 I9,
157 I10,
158 I11,
159 I12,
160 I13,
161 I14,
162 I15,
163 I16,
164 I17,
165 I18,
166 I19,
167 I20,
168 I21,
169 I22,
170 I23,
171 I24,
172 I25,
173 I26,
174 I27,
175 I28,
176 I29,
177 I30,
178 I31,
179 I32,
180 I33,
181 I34,
182 I35,
183 I36,
184 I37,
185 I38,
186 I39,
187 I40,
188 I41,
189 I42,
190 I43,
191 I44,
192 I45,
193 I46,
194 I47,
195 I48,
196 I49,
197 I50,
198 I51,
199 I52,
200 I53,
201 I54,
202 I55,
203 I56,
204 I57,
205 I58,
206 I59,
207 I60,
208 I61,
209 I62,
210 I63,
211 I64,
212 I65,
213 I66,
214 I67,
215 I68,
216 I69,
217 I70,
218 I71,
219 I72,
220 I73,
221 I74,
222 I75,
223 I76,
224 I77,
225 I78,
226 I79,
227 I80,
228 I81,
229 I82,
230 I83,
231 I84,
232 I85,
233 I86,
234 I87,
235 I88,
236 I89,
237 I90,
238 I91,
239 I92,
240 I93,
241 I94,
242 I95,
243 I96,
244 I97,
245 I98,
246 I99,
247 I100,
248 I101,
249 I102,
250 I103,
251 I104,
252 I105,
253 I106,
254 I107,
255 I108,
256 I109,
257 I110,
258 I111,
259 I112,
260 I113,
261 I114,
262 I115,
263 I116,
264 I117,
265 I118,
266 I119,
267 I120,
268 I121,
269 I122,
270 I123,
271 I124,
272 I125,
273 I126,
274 I127,
275 I128,
276 I129,
277 I130,
278 I131,
279 I132,
280 I133,
281 I134,
282 I135,
283 I136,
284 I137,
285 I138,
286 I139,
287 I140,
288 I141,
289 I142,
290 I143,
291 I144,
292 I145,
293 I146,
294 I147,
295 I148,
296 I149,
297 I150,
298 I151,
299 I152,
300 I153,
301 I154,
302 I155,
303 I156,
304 I157,
305 I158,
306 I159,
307 I160,
308 I161,
309 I162,
310 I163,
311 I164,
312 I165,
313 I166,
314 I167,
315 I168,
316 I169,
317 I170,
318 I171,
319 I172,
320 I173,
321 I174,
322 I175,
323 I176,
324 I177,
325 I178,
326 I179,
327 I180,
328 I181,
329 I182,
330 I183,
331 I184,
332 I185,
333 I186,
334 I187,
335 I188,
336 I189,
337 I190,
338 I191,
339 I192,
340 I193,
341 I194,
342 I195,
343 I196,
344 I197,
345 I198,
346 I199,
347 I200,
348 I201,
349 I202,
350 I203,
351 I204,
352 I205,
353 I206,
354 I207,
355 I208,
356 I209,
357 I210,
358 I211,
359 I212,
360 I213,
361 I214,
362 I215,
363 I216,
364 I217,
365 I218,
366 I219,
367 I220,
368 I221,
369 I222,
370 I223,
371 I224,
372 I225,
373 I226,
374 I227,
375 I228,
376 I229,
377 I230,
378 I231,
379 I232,
380 I233,
381 I234,
382 I235,
383 I236,
384 I237,
385 I238,
386 I239,
387 I240,
388 I241,
389 I242,
390 I243,
391 I244,
392 I245,
393 I246,
394 I247,
395 I248,
396 I249,
397 I250,
398 I251,
399 I252,
400 I253,
401 I254,
402 I255,
403};
404const ValueCount257 = enum {
405 I0,
406 I1,
407 I2,
408 I3,
409 I4,
410 I5,
411 I6,
412 I7,
413 I8,
414 I9,
415 I10,
416 I11,
417 I12,
418 I13,
419 I14,
420 I15,
421 I16,
422 I17,
423 I18,
424 I19,
425 I20,
426 I21,
427 I22,
428 I23,
429 I24,
430 I25,
431 I26,
432 I27,
433 I28,
434 I29,
435 I30,
436 I31,
437 I32,
438 I33,
439 I34,
440 I35,
441 I36,
442 I37,
443 I38,
444 I39,
445 I40,
446 I41,
447 I42,
448 I43,
449 I44,
450 I45,
451 I46,
452 I47,
453 I48,
454 I49,
455 I50,
456 I51,
457 I52,
458 I53,
459 I54,
460 I55,
461 I56,
462 I57,
463 I58,
464 I59,
465 I60,
466 I61,
467 I62,
468 I63,
469 I64,
470 I65,
471 I66,
472 I67,
473 I68,
474 I69,
475 I70,
476 I71,
477 I72,
478 I73,
479 I74,
480 I75,
481 I76,
482 I77,
483 I78,
484 I79,
485 I80,
486 I81,
487 I82,
488 I83,
489 I84,
490 I85,
491 I86,
492 I87,
493 I88,
494 I89,
495 I90,
496 I91,
497 I92,
498 I93,
499 I94,
500 I95,
501 I96,
502 I97,
503 I98,
504 I99,
505 I100,
506 I101,
507 I102,
508 I103,
509 I104,
510 I105,
511 I106,
512 I107,
513 I108,
514 I109,
515 I110,
516 I111,
517 I112,
518 I113,
519 I114,
520 I115,
521 I116,
522 I117,
523 I118,
524 I119,
525 I120,
526 I121,
527 I122,
528 I123,
529 I124,
530 I125,
531 I126,
532 I127,
533 I128,
534 I129,
535 I130,
536 I131,
537 I132,
538 I133,
539 I134,
540 I135,
541 I136,
542 I137,
543 I138,
544 I139,
545 I140,
546 I141,
547 I142,
548 I143,
549 I144,
550 I145,
551 I146,
552 I147,
553 I148,
554 I149,
555 I150,
556 I151,
557 I152,
558 I153,
559 I154,
560 I155,
561 I156,
562 I157,
563 I158,
564 I159,
565 I160,
566 I161,
567 I162,
568 I163,
569 I164,
570 I165,
571 I166,
572 I167,
573 I168,
574 I169,
575 I170,
576 I171,
577 I172,
578 I173,
579 I174,
580 I175,
581 I176,
582 I177,
583 I178,
584 I179,
585 I180,
586 I181,
587 I182,
588 I183,
589 I184,
590 I185,
591 I186,
592 I187,
593 I188,
594 I189,
595 I190,
596 I191,
597 I192,
598 I193,
599 I194,
600 I195,
601 I196,
602 I197,
603 I198,
604 I199,
605 I200,
606 I201,
607 I202,
608 I203,
609 I204,
610 I205,
611 I206,
612 I207,
613 I208,
614 I209,
615 I210,
616 I211,
617 I212,
618 I213,
619 I214,
620 I215,
621 I216,
622 I217,
623 I218,
624 I219,
625 I220,
626 I221,
627 I222,
628 I223,
629 I224,
630 I225,
631 I226,
632 I227,
633 I228,
634 I229,
635 I230,
636 I231,
637 I232,
638 I233,
639 I234,
640 I235,
641 I236,
642 I237,
643 I238,
644 I239,
645 I240,
646 I241,
647 I242,
648 I243,
649 I244,
650 I245,
651 I246,
652 I247,
653 I248,
654 I249,
655 I250,
656 I251,
657 I252,
658 I253,
659 I254,
660 I255,
661 I256,
662};
663
664test "enum sizes" {
665 comptime {
666 assert(@sizeOf(ValueCount1) == 0);
667 assert(@sizeOf(ValueCount2) == 1);
668 assert(@sizeOf(ValueCount256) == 1);
669 assert(@sizeOf(ValueCount257) == 2);
670 }
671}
672
673const Small2 = enum(u2) {
674 One,
675 Two,
676};
677const Small = enum(u2) {
678 One,
679 Two,
680 Three,
681 Four,
682};
683
684test "set enum tag type" {
685 {
686 var x = Small.One;
687 x = Small.Two;
688 comptime assert(@TagType(Small) == u2);
689 }
690 {
691 var x = Small2.One;
692 x = Small2.Two;
693 comptime assert(@TagType(Small2) == u2);
694 }
695}
696
697const A = enum(u3) {
698 One,
699 Two,
700 Three,
701 Four,
702 One2,
703 Two2,
704 Three2,
705 Four2,
706};
707
708const B = enum(u3) {
709 One3,
710 Two3,
711 Three3,
712 Four3,
713 One23,
714 Two23,
715 Three23,
716 Four23,
717};
718
719const C = enum(u2) {
720 One4,
721 Two4,
722 Three4,
723 Four4,
724};
725
726const BitFieldOfEnums = packed struct {
727 a: A,
728 b: B,
729 c: C,
730};
731
732const bit_field_1 = BitFieldOfEnums{
733 .a = A.Two,
734 .b = B.Three3,
735 .c = C.Four4,
736};
737
738test "bit field access with enum fields" {
739 var data = bit_field_1;
740 assert(getA(&data) == A.Two);
741 assert(getB(&data) == B.Three3);
742 assert(getC(&data) == C.Four4);
743 comptime assert(@sizeOf(BitFieldOfEnums) == 1);
744
745 data.b = B.Four3;
746 assert(data.b == B.Four3);
747
748 data.a = A.Three;
749 assert(data.a == A.Three);
750 assert(data.b == B.Four3);
751}
752
753fn getA(data: *const BitFieldOfEnums) A {
754 return data.a;
755}
756
757fn getB(data: *const BitFieldOfEnums) B {
758 return data.b;
759}
760
761fn getC(data: *const BitFieldOfEnums) C {
762 return data.c;
763}
764
765test "casting enum to its tag type" {
766 testCastEnumToTagType(Small2.Two);
767 comptime testCastEnumToTagType(Small2.Two);
768}
769
770fn testCastEnumToTagType(value: Small2) void {
771 assert(@enumToInt(value) == 1);
772}
773
774const MultipleChoice = enum(u32) {
775 A = 20,
776 B = 40,
777 C = 60,
778 D = 1000,
779};
780
781test "enum with specified tag values" {
782 testEnumWithSpecifiedTagValues(MultipleChoice.C);
783 comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
784}
785
786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
787 assert(@enumToInt(x) == 60);
788 assert(1234 == switch (x) {
789 MultipleChoice.A => 1,
790 MultipleChoice.B => 2,
791 MultipleChoice.C => u32(1234),
792 MultipleChoice.D => 4,
793 });
794}
795
796const MultipleChoice2 = enum(u32) {
797 Unspecified1,
798 A = 20,
799 Unspecified2,
800 B = 40,
801 Unspecified3,
802 C = 60,
803 Unspecified4,
804 D = 1000,
805 Unspecified5,
806};
807
808test "enum with specified and unspecified tag values" {
809 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
810 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
811}
812
813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
814 assert(@enumToInt(x) == 1000);
815 assert(1234 == switch (x) {
816 MultipleChoice2.A => 1,
817 MultipleChoice2.B => 2,
818 MultipleChoice2.C => 3,
819 MultipleChoice2.D => u32(1234),
820 MultipleChoice2.Unspecified1 => 5,
821 MultipleChoice2.Unspecified2 => 6,
822 MultipleChoice2.Unspecified3 => 7,
823 MultipleChoice2.Unspecified4 => 8,
824 MultipleChoice2.Unspecified5 => 9,
825 });
826}
827
828test "cast integer literal to enum" {
829 assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
831}
832
833const EnumWithOneMember = enum {
834 Eof,
835};
836
837fn doALoopThing(id: EnumWithOneMember) void {
838 while (true) {
839 if (id == EnumWithOneMember.Eof) {
840 break;
841 }
842 @compileError("above if condition should be comptime");
843 }
844}
845
846test "comparison operator on enum with one member is comptime known" {
847 doALoopThing(EnumWithOneMember.Eof);
848}
849
850const State = enum {
851 Start,
852};
853test "switch on enum with one member is comptime known" {
854 var state = State.Start;
855 switch (state) {
856 State.Start => return,
857 }
858 @compileError("analysis should not reach here");
859}
860
861const EnumWithTagValues = enum(u4) {
862 A = 1 << 0,
863 B = 1 << 1,
864 C = 1 << 2,
865 D = 1 << 3,
866};
867test "enum with tag values don't require parens" {
868 assert(@enumToInt(EnumWithTagValues.C) == 0b0100);
869}
870
871test "enum with 1 field but explicit tag type should still have the tag type" {
872 const Enum = enum(u8) {
873 B = 2,
874 };
875 comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8));
876}
877
878test "empty extern enum with members" {
879 const E = extern enum {
880 A,
881 B,
882 C,
883 };
884 assert(@sizeOf(E) == @sizeOf(c_int));
885}
886
887test "aoeu" {
888 const LocalFoo = enum {
889 A = 1,
890 B = 0,
891 };
892 var b = LocalFoo.B;
893 assert(mem.eql(u8, @tagName(b), "B"));
894}
test/cases/enum_with_members.zig deleted-27
...@@ -1,27 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const fmt = @import("std").fmt;
4
5const ET = union(enum) {
6 SINT: i32,
7 UINT: u32,
8
9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
10 return switch (a.*) {
11 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
13 };
14 }
15};
16
17test "enum with members" {
18 const a = ET{ .SINT = -42 };
19 const b = ET{ .UINT = 42 };
20 var buf: [20]u8 = undefined;
21
22 assert((a.print(buf[0..]) catch unreachable) == 3);
23 assert(mem.eql(u8, buf[0..3], "-42"));
24
25 assert((b.print(buf[0..]) catch unreachable) == 2);
26 assert(mem.eql(u8, buf[0..2], "42"));
27}
test/cases/error.zig deleted-245
...@@ -1,245 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4const builtin = @import("builtin");
5
6pub fn foo() anyerror!i32 {
7 const x = try bar();
8 return x + 1;
9}
10
11pub fn bar() anyerror!i32 {
12 return 13;
13}
14
15pub fn baz() anyerror!i32 {
16 const y = foo() catch 1234;
17 return y + 1;
18}
19
20test "error wrapping" {
21 assert((baz() catch unreachable) == 15);
22}
23
24fn gimmeItBroke() []const u8 {
25 return @errorName(error.ItBroke);
26}
27
28test "@errorName" {
29 assert(mem.eql(u8, @errorName(error.AnError), "AnError"));
30 assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
31}
32
33test "error values" {
34 const a = @errorToInt(error.err1);
35 const b = @errorToInt(error.err2);
36 assert(a != b);
37}
38
39test "redefinition of error values allowed" {
40 shouldBeNotEqual(error.AnError, error.SecondError);
41}
42fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
43 if (a == b) unreachable;
44}
45
46test "error binary operator" {
47 const a = errBinaryOperatorG(true) catch 3;
48 const b = errBinaryOperatorG(false) catch 3;
49 assert(a == 3);
50 assert(b == 10);
51}
52fn errBinaryOperatorG(x: bool) anyerror!isize {
53 return if (x) error.ItBroke else isize(10);
54}
55
56test "unwrap simple value from error" {
57 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
58 assert(i == 13);
59}
60fn unwrapSimpleValueFromErrorDo() anyerror!isize {
61 return 13;
62}
63
64test "error return in assignment" {
65 doErrReturnInAssignment() catch unreachable;
66}
67
68fn doErrReturnInAssignment() anyerror!void {
69 var x: i32 = undefined;
70 x = try makeANonErr();
71}
72
73fn makeANonErr() anyerror!i32 {
74 return 1;
75}
76
77test "error union type " {
78 testErrorUnionType();
79 comptime testErrorUnionType();
80}
81
82fn testErrorUnionType() void {
83 const x: anyerror!i32 = 1234;
84 if (x) |value| assert(value == 1234) else |_| unreachable;
85 assert(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
86 assert(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
87 assert(@typeOf(x).ErrorSet == anyerror);
88}
89
90test "error set type " {
91 testErrorSetType();
92 comptime testErrorSetType();
93}
94
95const MyErrSet = error{
96 OutOfMemory,
97 FileNotFound,
98};
99
100fn testErrorSetType() void {
101 assert(@memberCount(MyErrSet) == 2);
102
103 const a: MyErrSet!i32 = 5678;
104 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
105
106 if (a) |value| assert(value == 5678) else |err| switch (err) {
107 error.OutOfMemory => unreachable,
108 error.FileNotFound => unreachable,
109 }
110}
111
112test "explicit error set cast" {
113 testExplicitErrorSetCast(Set1.A);
114 comptime testExplicitErrorSetCast(Set1.A);
115}
116
117const Set1 = error{
118 A,
119 B,
120};
121const Set2 = error{
122 A,
123 C,
124};
125
126fn testExplicitErrorSetCast(set1: Set1) void {
127 var x = @errSetCast(Set2, set1);
128 var y = @errSetCast(Set1, x);
129 assert(y == error.A);
130}
131
132test "comptime test error for empty error set" {
133 testComptimeTestErrorEmptySet(1234);
134 comptime testComptimeTestErrorEmptySet(1234);
135}
136
137const EmptyErrorSet = error{};
138
139fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
140 if (x) |v| assert(v == 1234) else |err| @compileError("bad");
141}
142
143test "syntax: optional operator in front of error union operator" {
144 comptime {
145 assert(?(anyerror!i32) == ?(anyerror!i32));
146 }
147}
148
149test "comptime err to int of error set with only 1 possible value" {
150 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
151 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152}
153fn testErrToIntWithOnePossibleValue(
154 x: error{A},
155 comptime value: u32,
156) void {
157 if (@errorToInt(x) != value) {
158 @compileError("bad");
159 }
160}
161
162test "error union peer type resolution" {
163 testErrorUnionPeerTypeResolution(1);
164 comptime testErrorUnionPeerTypeResolution(1);
165}
166
167fn testErrorUnionPeerTypeResolution(x: i32) void {
168 const y = switch (x) {
169 1 => bar_1(),
170 2 => baz_1(),
171 else => quux_1(),
172 };
173}
174
175fn bar_1() anyerror {
176 return error.A;
177}
178
179fn baz_1() !i32 {
180 return error.B;
181}
182
183fn quux_1() !i32 {
184 return error.C;
185}
186
187test "error: fn returning empty error set can be passed as fn returning any error" {
188 entry();
189 comptime entry();
190}
191
192fn entry() void {
193 foo2(bar2);
194}
195
196fn foo2(f: fn () anyerror!void) void {
197 const x = f();
198}
199
200fn bar2() (error{}!void) {}
201
202test "error: Zero sized error set returned with value payload crash" {
203 _ = foo3(0);
204 _ = comptime foo3(0);
205}
206
207const Error = error{};
208fn foo3(b: usize) Error!usize {
209 return b;
210}
211
212test "error: Infer error set from literals" {
213 _ = nullLiteral("n") catch |err| handleErrors(err);
214 _ = floatLiteral("n") catch |err| handleErrors(err);
215 _ = intLiteral("n") catch |err| handleErrors(err);
216 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
217 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
218 _ = comptime intLiteral("n") catch |err| handleErrors(err);
219}
220
221fn handleErrors(err: var) noreturn {
222 switch (err) {
223 error.T => {},
224 }
225
226 unreachable;
227}
228
229fn nullLiteral(str: []const u8) !?i64 {
230 if (str[0] == 'n') return null;
231
232 return error.T;
233}
234
235fn floatLiteral(str: []const u8) !?f64 {
236 if (str[0] == 'n') return 1.0;
237
238 return error.T;
239}
240
241fn intLiteral(str: []const u8) !?i64 {
242 if (str[0] == 'n') return 1;
243
244 return error.T;
245}
test/cases/eval.zig deleted-782
...@@ -1,782 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4
5test "compile time recursion" {
6 assert(some_data.len == 21);
7}
8var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
9fn fibonacci(x: i32) i32 {
10 if (x <= 1) return 1;
11 return fibonacci(x - 1) + fibonacci(x - 2);
12}
13
14fn unwrapAndAddOne(blah: ?i32) i32 {
15 return blah.? + 1;
16}
17const should_be_1235 = unwrapAndAddOne(1234);
18test "static add one" {
19 assert(should_be_1235 == 1235);
20}
21
22test "inlined loop" {
23 comptime var i = 0;
24 comptime var sum = 0;
25 inline while (i <= 5) : (i += 1)
26 sum += i;
27 assert(sum == 15);
28}
29
30fn gimme1or2(comptime a: bool) i32 {
31 const x: i32 = 1;
32 const y: i32 = 2;
33 comptime var z: i32 = if (a) x else y;
34 return z;
35}
36test "inline variable gets result of const if" {
37 assert(gimme1or2(true) == 1);
38 assert(gimme1or2(false) == 2);
39}
40
41test "static function evaluation" {
42 assert(statically_added_number == 3);
43}
44const statically_added_number = staticAdd(1, 2);
45fn staticAdd(a: i32, b: i32) i32 {
46 return a + b;
47}
48
49test "const expr eval on single expr blocks" {
50 assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
51}
52
53fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
54 const literal = 3;
55
56 const result = if (b) b: {
57 break :b literal;
58 } else b: {
59 break :b x;
60 };
61
62 return result;
63}
64
65test "statically initialized list" {
66 assert(static_point_list[0].x == 1);
67 assert(static_point_list[0].y == 2);
68 assert(static_point_list[1].x == 3);
69 assert(static_point_list[1].y == 4);
70}
71const Point = struct {
72 x: i32,
73 y: i32,
74};
75const static_point_list = []Point{
76 makePoint(1, 2),
77 makePoint(3, 4),
78};
79fn makePoint(x: i32, y: i32) Point {
80 return Point{
81 .x = x,
82 .y = y,
83 };
84}
85
86test "static eval list init" {
87 assert(static_vec3.data[2] == 1.0);
88 assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
89}
90const static_vec3 = vec3(0.0, 0.0, 1.0);
91pub const Vec3 = struct {
92 data: [3]f32,
93};
94pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
95 return Vec3{ .data = []f32{
96 x,
97 y,
98 z,
99 } };
100}
101
102test "constant expressions" {
103 var array: [array_size]u8 = undefined;
104 assert(@sizeOf(@typeOf(array)) == 20);
105}
106const array_size: u8 = 20;
107
108test "constant struct with negation" {
109 assert(vertices[0].x == -0.6);
110}
111const Vertex = struct {
112 x: f32,
113 y: f32,
114 r: f32,
115 g: f32,
116 b: f32,
117};
118const vertices = []Vertex{
119 Vertex{
120 .x = -0.6,
121 .y = -0.4,
122 .r = 1.0,
123 .g = 0.0,
124 .b = 0.0,
125 },
126 Vertex{
127 .x = 0.6,
128 .y = -0.4,
129 .r = 0.0,
130 .g = 1.0,
131 .b = 0.0,
132 },
133 Vertex{
134 .x = 0.0,
135 .y = 0.6,
136 .r = 0.0,
137 .g = 0.0,
138 .b = 1.0,
139 },
140};
141
142test "statically initialized struct" {
143 st_init_str_foo.x += 1;
144 assert(st_init_str_foo.x == 14);
145}
146const StInitStrFoo = struct {
147 x: i32,
148 y: bool,
149};
150var st_init_str_foo = StInitStrFoo{
151 .x = 13,
152 .y = true,
153};
154
155test "statically initalized array literal" {
156 const y: [4]u8 = st_init_arr_lit_x;
157 assert(y[3] == 4);
158}
159const st_init_arr_lit_x = []u8{
160 1,
161 2,
162 3,
163 4,
164};
165
166test "const slice" {
167 comptime {
168 const a = "1234567890";
169 assert(a.len == 10);
170 const b = a[1..2];
171 assert(b.len == 1);
172 assert(b[0] == '2');
173 }
174}
175
176test "try to trick eval with runtime if" {
177 assert(testTryToTrickEvalWithRuntimeIf(true) == 10);
178}
179
180fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
181 comptime var i: usize = 0;
182 inline while (i < 10) : (i += 1) {
183 const result = if (b) false else true;
184 }
185 comptime {
186 return i;
187 }
188}
189
190fn max(comptime T: type, a: T, b: T) T {
191 if (T == bool) {
192 return a or b;
193 } else if (a > b) {
194 return a;
195 } else {
196 return b;
197 }
198}
199fn letsTryToCompareBools(a: bool, b: bool) bool {
200 return max(bool, a, b);
201}
202test "inlined block and runtime block phi" {
203 assert(letsTryToCompareBools(true, true));
204 assert(letsTryToCompareBools(true, false));
205 assert(letsTryToCompareBools(false, true));
206 assert(!letsTryToCompareBools(false, false));
207
208 comptime {
209 assert(letsTryToCompareBools(true, true));
210 assert(letsTryToCompareBools(true, false));
211 assert(letsTryToCompareBools(false, true));
212 assert(!letsTryToCompareBools(false, false));
213 }
214}
215
216const CmdFn = struct {
217 name: []const u8,
218 func: fn (i32) i32,
219};
220
221const cmd_fns = []CmdFn{
222 CmdFn{
223 .name = "one",
224 .func = one,
225 },
226 CmdFn{
227 .name = "two",
228 .func = two,
229 },
230 CmdFn{
231 .name = "three",
232 .func = three,
233 },
234};
235fn one(value: i32) i32 {
236 return value + 1;
237}
238fn two(value: i32) i32 {
239 return value + 2;
240}
241fn three(value: i32) i32 {
242 return value + 3;
243}
244
245fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
246 var result: i32 = start_value;
247 comptime var i = 0;
248 inline while (i < cmd_fns.len) : (i += 1) {
249 if (cmd_fns[i].name[0] == prefix_char) {
250 result = cmd_fns[i].func(result);
251 }
252 }
253 return result;
254}
255
256test "comptime iterate over fn ptr list" {
257 assert(performFn('t', 1) == 6);
258 assert(performFn('o', 0) == 1);
259 assert(performFn('w', 99) == 99);
260}
261
262test "eval @setRuntimeSafety at compile-time" {
263 const result = comptime fnWithSetRuntimeSafety();
264 assert(result == 1234);
265}
266
267fn fnWithSetRuntimeSafety() i32 {
268 @setRuntimeSafety(true);
269 return 1234;
270}
271
272test "eval @setFloatMode at compile-time" {
273 const result = comptime fnWithFloatMode();
274 assert(result == 1234.0);
275}
276
277fn fnWithFloatMode() f32 {
278 @setFloatMode(builtin.FloatMode.Strict);
279 return 1234.0;
280}
281
282const SimpleStruct = struct {
283 field: i32,
284
285 fn method(self: *const SimpleStruct) i32 {
286 return self.field + 3;
287 }
288};
289
290var simple_struct = SimpleStruct{ .field = 1234 };
291
292const bound_fn = simple_struct.method;
293
294test "call method on bound fn referring to var instance" {
295 assert(bound_fn() == 1237);
296}
297
298test "ptr to local array argument at comptime" {
299 comptime {
300 var bytes: [10]u8 = undefined;
301 modifySomeBytes(bytes[0..]);
302 assert(bytes[0] == 'a');
303 assert(bytes[9] == 'b');
304 }
305}
306
307fn modifySomeBytes(bytes: []u8) void {
308 bytes[0] = 'a';
309 bytes[9] = 'b';
310}
311
312test "comparisons 0 <= uint and 0 > uint should be comptime" {
313 testCompTimeUIntComparisons(1234);
314}
315fn testCompTimeUIntComparisons(x: u32) void {
316 if (!(0 <= x)) {
317 @compileError("this condition should be comptime known");
318 }
319 if (0 > x) {
320 @compileError("this condition should be comptime known");
321 }
322 if (!(x >= 0)) {
323 @compileError("this condition should be comptime known");
324 }
325 if (x < 0) {
326 @compileError("this condition should be comptime known");
327 }
328}
329
330test "const ptr to variable data changes at runtime" {
331 assert(foo_ref.name[0] == 'a');
332 foo_ref.name = "b";
333 assert(foo_ref.name[0] == 'b');
334}
335
336const Foo = struct {
337 name: []const u8,
338};
339
340var foo_contents = Foo{ .name = "a" };
341const foo_ref = &foo_contents;
342
343test "create global array with for loop" {
344 assert(global_array[5] == 5 * 5);
345 assert(global_array[9] == 9 * 9);
346}
347
348const global_array = x: {
349 var result: [10]usize = undefined;
350 for (result) |*item, index| {
351 item.* = index * index;
352 }
353 break :x result;
354};
355
356test "compile-time downcast when the bits fit" {
357 comptime {
358 const spartan_count: u16 = 255;
359 const byte = @intCast(u8, spartan_count);
360 assert(byte == 255);
361 }
362}
363
364const hi1 = "hi";
365const hi2 = hi1;
366test "const global shares pointer with other same one" {
367 assertEqualPtrs(&hi1[0], &hi2[0]);
368 comptime assert(&hi1[0] == &hi2[0]);
369}
370fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void {
371 assert(ptr1 == ptr2);
372}
373
374test "@setEvalBranchQuota" {
375 comptime {
376 // 1001 for the loop and then 1 more for the assert fn call
377 @setEvalBranchQuota(1002);
378 var i = 0;
379 var sum = 0;
380 while (i < 1001) : (i += 1) {
381 sum += i;
382 }
383 assert(sum == 500500);
384 }
385}
386
387// TODO test "float literal at compile time not lossy" {
388// TODO assert(16777216.0 + 1.0 == 16777217.0);
389// TODO assert(9007199254740992.0 + 1.0 == 9007199254740993.0);
390// TODO }
391
392test "f32 at compile time is lossy" {
393 assert(f32(1 << 24) + 1 == 1 << 24);
394}
395
396test "f64 at compile time is lossy" {
397 assert(f64(1 << 53) + 1 == 1 << 53);
398}
399
400test "f128 at compile time is lossy" {
401 assert(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
402}
403
404// TODO need a better implementation of bigfloat_init_bigint
405// assert(f128(1 << 113) == 10384593717069655257060992658440192);
406
407pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
408 return struct {
409 pub const Node = struct {};
410 };
411}
412
413test "string literal used as comptime slice is memoized" {
414 const a = "link";
415 const b = "link";
416 comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
417 comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
418}
419
420test "comptime slice of undefined pointer of length 0" {
421 const slice1 = ([*]i32)(undefined)[0..0];
422 assert(slice1.len == 0);
423 const slice2 = ([*]i32)(undefined)[100..100];
424 assert(slice2.len == 0);
425}
426
427fn copyWithPartialInline(s: []u32, b: []u8) void {
428 comptime var i: usize = 0;
429 inline while (i < 4) : (i += 1) {
430 s[i] = 0;
431 s[i] |= u32(b[i * 4 + 0]) << 24;
432 s[i] |= u32(b[i * 4 + 1]) << 16;
433 s[i] |= u32(b[i * 4 + 2]) << 8;
434 s[i] |= u32(b[i * 4 + 3]) << 0;
435 }
436}
437
438test "binary math operator in partially inlined function" {
439 var s: [4]u32 = undefined;
440 var b: [16]u8 = undefined;
441
442 for (b) |*r, i|
443 r.* = @intCast(u8, i + 1);
444
445 copyWithPartialInline(s[0..], b[0..]);
446 assert(s[0] == 0x1020304);
447 assert(s[1] == 0x5060708);
448 assert(s[2] == 0x90a0b0c);
449 assert(s[3] == 0xd0e0f10);
450}
451
452test "comptime function with the same args is memoized" {
453 comptime {
454 assert(MakeType(i32) == MakeType(i32));
455 assert(MakeType(i32) != MakeType(f64));
456 }
457}
458
459fn MakeType(comptime T: type) type {
460 return struct {
461 field: T,
462 };
463}
464
465test "comptime function with mutable pointer is not memoized" {
466 comptime {
467 var x: i32 = 1;
468 const ptr = &x;
469 increment(ptr);
470 increment(ptr);
471 assert(x == 3);
472 }
473}
474
475fn increment(value: *i32) void {
476 value.* += 1;
477}
478
479fn generateTable(comptime T: type) [1010]T {
480 var res: [1010]T = undefined;
481 var i: usize = 0;
482 while (i < 1010) : (i += 1) {
483 res[i] = @intCast(T, i);
484 }
485 return res;
486}
487
488fn doesAlotT(comptime T: type, value: usize) T {
489 @setEvalBranchQuota(5000);
490 const table = comptime blk: {
491 break :blk generateTable(T);
492 };
493 return table[value];
494}
495
496test "@setEvalBranchQuota at same scope as generic function call" {
497 assert(doesAlotT(u32, 2) == 2);
498}
499
500test "comptime slice of slice preserves comptime var" {
501 comptime {
502 var buff: [10]u8 = undefined;
503 buff[0..][0..][0] = 1;
504 assert(buff[0..][0..][0] == 1);
505 }
506}
507
508test "comptime slice of pointer preserves comptime var" {
509 comptime {
510 var buff: [10]u8 = undefined;
511 var a = buff[0..].ptr;
512 a[0..1][0] = 1;
513 assert(buff[0..][0..][0] == 1);
514 }
515}
516
517const SingleFieldStruct = struct {
518 x: i32,
519
520 fn read_x(self: *const SingleFieldStruct) i32 {
521 return self.x;
522 }
523};
524test "const ptr to comptime mutable data is not memoized" {
525 comptime {
526 var foo = SingleFieldStruct{ .x = 1 };
527 assert(foo.read_x() == 1);
528 foo.x = 2;
529 assert(foo.read_x() == 2);
530 }
531}
532
533test "array concat of slices gives slice" {
534 comptime {
535 var a: []const u8 = "aoeu";
536 var b: []const u8 = "asdf";
537 const c = a ++ b;
538 assert(std.mem.eql(u8, c, "aoeuasdf"));
539 }
540}
541
542test "comptime shlWithOverflow" {
543 const ct_shifted: u64 = comptime amt: {
544 var amt = u64(0);
545 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
546 break :amt amt;
547 };
548
549 const rt_shifted: u64 = amt: {
550 var amt = u64(0);
551 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
552 break :amt amt;
553 };
554
555 assert(ct_shifted == rt_shifted);
556}
557
558test "runtime 128 bit integer division" {
559 var a: u128 = 152313999999999991610955792383;
560 var b: u128 = 10000000000000000000;
561 var c = a / b;
562 assert(c == 15231399999);
563}
564
565pub const Info = struct {
566 version: u8,
567};
568
569pub const diamond_info = Info{ .version = 0 };
570
571test "comptime modification of const struct field" {
572 comptime {
573 var res = diamond_info;
574 res.version = 1;
575 assert(diamond_info.version == 0);
576 assert(res.version == 1);
577 }
578}
579
580test "pointer to type" {
581 comptime {
582 var T: type = i32;
583 assert(T == i32);
584 var ptr = &T;
585 assert(@typeOf(ptr) == *type);
586 ptr.* = f32;
587 assert(T == f32);
588 assert(*T == *f32);
589 }
590}
591
592test "slice of type" {
593 comptime {
594 var types_array = []type{ i32, f64, type };
595 for (types_array) |T, i| {
596 switch (i) {
597 0 => assert(T == i32),
598 1 => assert(T == f64),
599 2 => assert(T == type),
600 else => unreachable,
601 }
602 }
603 for (types_array[0..]) |T, i| {
604 switch (i) {
605 0 => assert(T == i32),
606 1 => assert(T == f64),
607 2 => assert(T == type),
608 else => unreachable,
609 }
610 }
611 }
612}
613
614const Wrapper = struct {
615 T: type,
616};
617
618fn wrap(comptime T: type) Wrapper {
619 return Wrapper{ .T = T };
620}
621
622test "function which returns struct with type field causes implicit comptime" {
623 const ty = wrap(i32).T;
624 assert(ty == i32);
625}
626
627test "call method with comptime pass-by-non-copying-value self parameter" {
628 const S = struct {
629 a: u8,
630
631 fn b(comptime s: @This()) u8 {
632 return s.a;
633 }
634 };
635
636 const s = S{ .a = 2 };
637 var b = s.b();
638 assert(b == 2);
639}
640
641test "@tagName of @typeId" {
642 const str = @tagName(@typeId(u8));
643 assert(std.mem.eql(u8, str, "Int"));
644}
645
646test "setting backward branch quota just before a generic fn call" {
647 @setEvalBranchQuota(1001);
648 loopNTimes(1001);
649}
650
651fn loopNTimes(comptime n: usize) void {
652 comptime var i = 0;
653 inline while (i < n) : (i += 1) {}
654}
655
656test "variable inside inline loop that has different types on different iterations" {
657 testVarInsideInlineLoop(true, u32(42));
658}
659
660fn testVarInsideInlineLoop(args: ...) void {
661 comptime var i = 0;
662 inline while (i < args.len) : (i += 1) {
663 const x = args[i];
664 if (i == 0) assert(x);
665 if (i == 1) assert(x == 42);
666 }
667}
668
669test "inline for with same type but different values" {
670 var res: usize = 0;
671 inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| {
672 var a: T = undefined;
673 res += a.len;
674 }
675 assert(res == 5);
676}
677
678test "refer to the type of a generic function" {
679 const Func = fn (type) void;
680 const f: Func = doNothingWithType;
681 f(i32);
682}
683
684fn doNothingWithType(comptime T: type) void {}
685
686test "zero extend from u0 to u1" {
687 var zero_u0: u0 = 0;
688 var zero_u1: u1 = zero_u0;
689 assert(zero_u1 == 0);
690}
691
692test "bit shift a u1" {
693 var x: u1 = 1;
694 var y = x << 0;
695 assert(y == 1);
696}
697
698test "@intCast to a u0" {
699 var x: u8 = 0;
700 var y: u0 = @intCast(u0, x);
701 assert(y == 0);
702}
703
704test "@bytesToslice on a packed struct" {
705 const F = packed struct {
706 a: u8,
707 };
708
709 var b = [1]u8{9};
710 var f = @bytesToSlice(F, b);
711 assert(f[0].a == 9);
712}
713
714test "comptime pointer cast array and then slice" {
715 const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
716
717 const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
718 const sliceA: []const u8 = ptrA[0..2];
719
720 const ptrB: [*]const u8 = &array;
721 const sliceB: []const u8 = ptrB[0..2];
722
723 assert(sliceA[1] == 2);
724 assert(sliceB[1] == 2);
725}
726
727test "slice bounds in comptime concatenation" {
728 const bs = comptime blk: {
729 const b = c"11";
730 break :blk b[0..1];
731 };
732 const str = "" ++ bs;
733 assert(str.len == 1);
734 assert(std.mem.eql(u8, str, "1"));
735
736 const str2 = bs ++ "";
737 assert(str2.len == 1);
738 assert(std.mem.eql(u8, str2, "1"));
739}
740
741test "comptime bitwise operators" {
742 comptime {
743 assert(3 & 1 == 1);
744 assert(3 & -1 == 3);
745 assert(-3 & -1 == -3);
746 assert(3 | -1 == -1);
747 assert(-3 | -1 == -1);
748 assert(3 ^ -1 == -4);
749 assert(-3 ^ -1 == 2);
750 assert(~i8(-1) == 0);
751 assert(~i128(-1) == 0);
752 assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
753 assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
754 assert(~u128(0) == 0xffffffffffffffffffffffffffffffff);
755 }
756}
757
758test "*align(1) u16 is the same as *align(1:0:2) u16" {
759 comptime {
760 assert(*align(1:0:2) u16 == *align(1) u16);
761 // TODO add parsing support for this syntax
762 //assert(*align(:0:2) u16 == *u16);
763 }
764}
765
766test "array concatenation forces comptime" {
767 var a = oneItem(3) ++ oneItem(4);
768 assert(std.mem.eql(i32, a, []i32{3, 4}));
769}
770
771test "array multiplication forces comptime" {
772 var a = oneItem(3) ** scalar(2);
773 assert(std.mem.eql(i32, a, []i32{3, 3}));
774}
775
776fn oneItem(x: i32) [1]i32 {
777 return []i32{x};
778}
779
780fn scalar(x: u32) u32 {
781 return x;
782}
test/cases/field_parent_ptr.zig deleted-41
...@@ -1,41 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "@fieldParentPtr non-first field" {
4 testParentFieldPtr(&foo.c);
5 comptime testParentFieldPtr(&foo.c);
6}
7
8test "@fieldParentPtr first field" {
9 testParentFieldPtrFirst(&foo.a);
10 comptime testParentFieldPtrFirst(&foo.a);
11}
12
13const Foo = struct {
14 a: bool,
15 b: f32,
16 c: i32,
17 d: i32,
18};
19
20const foo = Foo{
21 .a = true,
22 .b = 0.123,
23 .c = 1234,
24 .d = -10,
25};
26
27fn testParentFieldPtr(c: *const i32) void {
28 assert(c == &foo.c);
29
30 const base = @fieldParentPtr(Foo, "c", c);
31 assert(base == &foo);
32 assert(&base.c == c);
33}
34
35fn testParentFieldPtrFirst(a: *const bool) void {
36 assert(a == &foo.a);
37
38 const base = @fieldParentPtr(Foo, "a", a);
39 assert(base == &foo);
40 assert(&base.a == a);
41}
test/cases/fn.zig deleted-207
...@@ -1,207 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "params" {
4 assert(testParamsAdd(22, 11) == 33);
5}
6fn testParamsAdd(a: i32, b: i32) i32 {
7 return a + b;
8}
9
10test "local variables" {
11 testLocVars(2);
12}
13fn testLocVars(b: i32) void {
14 const a: i32 = 1;
15 if (a + b != 3) unreachable;
16}
17
18test "void parameters" {
19 voidFun(1, void{}, 2, {});
20}
21fn voidFun(a: i32, b: void, c: i32, d: void) void {
22 const v = b;
23 const vv: void = if (a == 1) v else {};
24 assert(a + c == 3);
25 return vv;
26}
27
28test "mutable local variables" {
29 var zero: i32 = 0;
30 assert(zero == 0);
31
32 var i = i32(0);
33 while (i != 3) {
34 i += 1;
35 }
36 assert(i == 3);
37}
38
39test "separate block scopes" {
40 {
41 const no_conflict: i32 = 5;
42 assert(no_conflict == 5);
43 }
44
45 const c = x: {
46 const no_conflict = i32(10);
47 break :x no_conflict;
48 };
49 assert(c == 10);
50}
51
52test "call function with empty string" {
53 acceptsString("");
54}
55
56fn acceptsString(foo: []u8) void {}
57
58fn @"weird function name"() i32 {
59 return 1234;
60}
61test "weird function name" {
62 assert(@"weird function name"() == 1234);
63}
64
65test "implicit cast function unreachable return" {
66 wantsFnWithVoid(fnWithUnreachable);
67}
68
69fn wantsFnWithVoid(f: fn () void) void {}
70
71fn fnWithUnreachable() noreturn {
72 unreachable;
73}
74
75test "function pointers" {
76 const fns = []@typeOf(fn1){
77 fn1,
78 fn2,
79 fn3,
80 fn4,
81 };
82 for (fns) |f, i| {
83 assert(f() == @intCast(u32, i) + 5);
84 }
85}
86fn fn1() u32 {
87 return 5;
88}
89fn fn2() u32 {
90 return 6;
91}
92fn fn3() u32 {
93 return 7;
94}
95fn fn4() u32 {
96 return 8;
97}
98
99test "inline function call" {
100 assert(@inlineCall(add, 3, 9) == 12);
101}
102
103fn add(a: i32, b: i32) i32 {
104 return a + b;
105}
106
107test "number literal as an argument" {
108 numberLiteralArg(3);
109 comptime numberLiteralArg(3);
110}
111
112fn numberLiteralArg(a: var) void {
113 assert(a == 3);
114}
115
116test "assign inline fn to const variable" {
117 const a = inlineFn;
118 a();
119}
120
121inline fn inlineFn() void {}
122
123test "pass by non-copying value" {
124 assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
125}
126
127const Point = struct {
128 x: i32,
129 y: i32,
130};
131
132fn addPointCoords(pt: Point) i32 {
133 return pt.x + pt.y;
134}
135
136test "pass by non-copying value through var arg" {
137 assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
138}
139
140fn addPointCoordsVar(pt: var) i32 {
141 comptime assert(@typeOf(pt) == Point);
142 return pt.x + pt.y;
143}
144
145test "pass by non-copying value as method" {
146 var pt = Point2{ .x = 1, .y = 2 };
147 assert(pt.addPointCoords() == 3);
148}
149
150const Point2 = struct {
151 x: i32,
152 y: i32,
153
154 fn addPointCoords(self: Point2) i32 {
155 return self.x + self.y;
156 }
157};
158
159test "pass by non-copying value as method, which is generic" {
160 var pt = Point3{ .x = 1, .y = 2 };
161 assert(pt.addPointCoords(i32) == 3);
162}
163
164const Point3 = struct {
165 x: i32,
166 y: i32,
167
168 fn addPointCoords(self: Point3, comptime T: type) i32 {
169 return self.x + self.y;
170 }
171};
172
173test "pass by non-copying value as method, at comptime" {
174 comptime {
175 var pt = Point2{ .x = 1, .y = 2 };
176 assert(pt.addPointCoords() == 3);
177 }
178}
179
180fn outer(y: u32) fn (u32) u32 {
181 const Y = @typeOf(y);
182 const st = struct {
183 fn get(z: u32) u32 {
184 return z + @sizeOf(Y);
185 }
186 };
187 return st.get;
188}
189
190test "return inner function which references comptime variable of outer function" {
191 var func = outer(10);
192 assert(func(3) == 7);
193}
194
195test "extern struct with stdcallcc fn pointer" {
196 const S = extern struct {
197 ptr: stdcallcc fn () i32,
198
199 stdcallcc fn foo() i32 {
200 return 1234;
201 }
202 };
203
204 var s: S = undefined;
205 s.ptr = S.foo;
206 assert(s.ptr() == 1234);
207}
test/cases/fn_in_struct_in_comptime.zig deleted-17
...@@ -1,17 +0,0 @@
1const assert = @import("std").debug.assert;
2
3fn get_foo() fn (*u8) usize {
4 comptime {
5 return struct {
6 fn func(ptr: *u8) usize {
7 var u = @ptrToInt(ptr);
8 return u;
9 }
10 }.func;
11 }
12}
13
14test "define a function in an anonymous struct in comptime" {
15 const foo = get_foo();
16 assert(foo(@intToPtr(*u8, 12345)) == 12345);
17}
test/cases/for.zig deleted-106
...@@ -1,106 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4
5test "continue in for loop" {
6 const array = []i32{
7 1,
8 2,
9 3,
10 4,
11 5,
12 };
13 var sum: i32 = 0;
14 for (array) |x| {
15 sum += x;
16 if (x < 3) {
17 continue;
18 }
19 break;
20 }
21 if (sum != 6) unreachable;
22}
23
24test "for loop with pointer elem var" {
25 const source = "abcdefg";
26 var target: [source.len]u8 = undefined;
27 mem.copy(u8, target[0..], source);
28 mangleString(target[0..]);
29 assert(mem.eql(u8, target, "bcdefgh"));
30}
31fn mangleString(s: []u8) void {
32 for (s) |*c| {
33 c.* += 1;
34 }
35}
36
37test "basic for loop" {
38 const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
39
40 var buffer: [expected_result.len]u8 = undefined;
41 var buf_index: usize = 0;
42
43 const array = []u8{ 9, 8, 7, 6 };
44 for (array) |item| {
45 buffer[buf_index] = item;
46 buf_index += 1;
47 }
48 for (array) |item, index| {
49 buffer[buf_index] = @intCast(u8, index);
50 buf_index += 1;
51 }
52 const array_ptr = &array;
53 for (array_ptr) |item| {
54 buffer[buf_index] = item;
55 buf_index += 1;
56 }
57 for (array_ptr) |item, index| {
58 buffer[buf_index] = @intCast(u8, index);
59 buf_index += 1;
60 }
61 const unknown_size: []const u8 = array;
62 for (unknown_size) |item| {
63 buffer[buf_index] = item;
64 buf_index += 1;
65 }
66 for (unknown_size) |item, index| {
67 buffer[buf_index] = @intCast(u8, index);
68 buf_index += 1;
69 }
70
71 assert(mem.eql(u8, buffer[0..buf_index], expected_result));
72}
73
74test "break from outer for loop" {
75 testBreakOuter();
76 comptime testBreakOuter();
77}
78
79fn testBreakOuter() void {
80 var array = "aoeu";
81 var count: usize = 0;
82 outer: for (array) |_| {
83 for (array) |_| {
84 count += 1;
85 break :outer;
86 }
87 }
88 assert(count == 1);
89}
90
91test "continue outer for loop" {
92 testContinueOuter();
93 comptime testContinueOuter();
94}
95
96fn testContinueOuter() void {
97 var array = "aoeu";
98 var counter: usize = 0;
99 outer: for (array) |_| {
100 for (array) |_| {
101 counter += 1;
102 continue :outer;
103 }
104 }
105 assert(counter == array.len);
106}
test/cases/generics.zig deleted-151
...@@ -1,151 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "simple generic fn" {
4 assert(max(i32, 3, -1) == 3);
5 assert(max(f32, 0.123, 0.456) == 0.456);
6 assert(add(2, 3) == 5);
7}
8
9fn max(comptime T: type, a: T, b: T) T {
10 return if (a > b) a else b;
11}
12
13fn add(comptime a: i32, b: i32) i32 {
14 return (comptime a) + b;
15}
16
17const the_max = max(u32, 1234, 5678);
18test "compile time generic eval" {
19 assert(the_max == 5678);
20}
21
22fn gimmeTheBigOne(a: u32, b: u32) u32 {
23 return max(u32, a, b);
24}
25
26fn shouldCallSameInstance(a: u32, b: u32) u32 {
27 return max(u32, a, b);
28}
29
30fn sameButWithFloats(a: f64, b: f64) f64 {
31 return max(f64, a, b);
32}
33
34test "fn with comptime args" {
35 assert(gimmeTheBigOne(1234, 5678) == 5678);
36 assert(shouldCallSameInstance(34, 12) == 34);
37 assert(sameButWithFloats(0.43, 0.49) == 0.49);
38}
39
40test "var params" {
41 assert(max_i32(12, 34) == 34);
42 assert(max_f64(1.2, 3.4) == 3.4);
43}
44
45comptime {
46 assert(max_i32(12, 34) == 34);
47 assert(max_f64(1.2, 3.4) == 3.4);
48}
49
50fn max_var(a: var, b: var) @typeOf(a + b) {
51 return if (a > b) a else b;
52}
53
54fn max_i32(a: i32, b: i32) i32 {
55 return max_var(a, b);
56}
57
58fn max_f64(a: f64, b: f64) f64 {
59 return max_var(a, b);
60}
61
62pub fn List(comptime T: type) type {
63 return SmallList(T, 8);
64}
65
66pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
67 return struct {
68 items: []T,
69 length: usize,
70 prealloc_items: [STATIC_SIZE]T,
71 };
72}
73
74test "function with return type type" {
75 var list: List(i32) = undefined;
76 var list2: List(i32) = undefined;
77 list.length = 10;
78 list2.length = 10;
79 assert(list.prealloc_items.len == 8);
80 assert(list2.prealloc_items.len == 8);
81}
82
83test "generic struct" {
84 var a1 = GenNode(i32){
85 .value = 13,
86 .next = null,
87 };
88 var b1 = GenNode(bool){
89 .value = true,
90 .next = null,
91 };
92 assert(a1.value == 13);
93 assert(a1.value == a1.getVal());
94 assert(b1.getVal());
95}
96fn GenNode(comptime T: type) type {
97 return struct {
98 value: T,
99 next: ?*GenNode(T),
100 fn getVal(n: *const GenNode(T)) T {
101 return n.value;
102 }
103 };
104}
105
106test "const decls in struct" {
107 assert(GenericDataThing(3).count_plus_one == 4);
108}
109fn GenericDataThing(comptime count: isize) type {
110 return struct {
111 const count_plus_one = count + 1;
112 };
113}
114
115test "use generic param in generic param" {
116 assert(aGenericFn(i32, 3, 4) == 7);
117}
118fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
119 return a + b;
120}
121
122test "generic fn with implicit cast" {
123 assert(getFirstByte(u8, []u8{13}) == 13);
124 assert(getFirstByte(u16, []u16{
125 0,
126 13,
127 }) == 0);
128}
129fn getByte(ptr: ?*const u8) u8 {
130 return ptr.?.*;
131}
132fn getFirstByte(comptime T: type, mem: []const T) u8 {
133 return getByte(@ptrCast(*const u8, &mem[0]));
134}
135
136const foos = []fn (var) bool{
137 foo1,
138 foo2,
139};
140
141fn foo1(arg: var) bool {
142 return arg;
143}
144fn foo2(arg: var) bool {
145 return !arg;
146}
147
148test "array of generic fns" {
149 assert(foos[0](true));
150 assert(!foos[1](true));
151}
test/cases/if.zig deleted-37
...@@ -1,37 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "if statements" {
4 shouldBeEqual(1, 1);
5 firstEqlThird(2, 1, 2);
6}
7fn shouldBeEqual(a: i32, b: i32) void {
8 if (a != b) {
9 unreachable;
10 } else {
11 return;
12 }
13}
14fn firstEqlThird(a: i32, b: i32, c: i32) void {
15 if (a == b) {
16 unreachable;
17 } else if (b == c) {
18 unreachable;
19 } else if (a == c) {
20 return;
21 } else {
22 unreachable;
23 }
24}
25
26test "else if expression" {
27 assert(elseIfExpressionF(1) == 1);
28}
29fn elseIfExpressionF(c: u8) u8 {
30 if (c == 0) {
31 return 0;
32 } else if (c == 1) {
33 return 1;
34 } else {
35 return u8(2);
36 }
37}
test/cases/import.zig deleted-10
...@@ -1,10 +0,0 @@
1const assert = @import("std").debug.assert;
2const a_namespace = @import("import/a_namespace.zig");
3
4test "call fn via namespace lookup" {
5 assert(a_namespace.foo() == 1234);
6}
7
8test "importing the same thing gives the same import" {
9 assert(@import("std") == @import("std"));
10}
test/cases/import/a_namespace.zig deleted-3
...@@ -1,3 +0,0 @@
1pub fn foo() i32 {
2 return 1234;
3}
test/cases/incomplete_struct_param_tld.zig deleted-30
...@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const A = struct {
4 b: B,
5};
6
7const B = struct {
8 c: C,
9};
10
11const C = struct {
12 x: i32,
13
14 fn d(c: *const C) i32 {
15 return c.x;
16 }
17};
18
19fn foo(a: A) i32 {
20 return a.b.c.d();
21}
22
23test "incomplete struct param top level declaration" {
24 const a = A{
25 .b = B{
26 .c = C{ .x = 13 },
27 },
28 };
29 assert(foo(a) == 13);
30}
test/cases/inttoptr.zig deleted-27
...@@ -1,27 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "casting random address to function pointer" {
6 randomAddressToFunction();
7 comptime randomAddressToFunction();
8}
9
10fn randomAddressToFunction() void {
11 var addr: usize = 0xdeadbeef;
12 var ptr = @intToPtr(fn () void, addr);
13}
14
15test "mutate through ptr initialized with constant intToPtr value" {
16 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
17}
18
19fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
20 const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef);
21 if (x) {
22 hardCodedP.* = hardCodedP.* | 10;
23 } else {
24 return;
25 }
26}
27
test/cases/ir_block_deps.zig deleted-21
...@@ -1,21 +0,0 @@
1const assert = @import("std").debug.assert;
2
3fn foo(id: u64) !i32 {
4 return switch (id) {
5 1 => getErrInt(),
6 2 => {
7 const size = try getErrInt();
8 return try getErrInt();
9 },
10 else => error.ItBroke,
11 };
12}
13
14fn getErrInt() anyerror!i32 {
15 return 0;
16}
17
18test "ir block deps" {
19 assert((foo(1) catch unreachable) == 0);
20 assert((foo(2) catch unreachable) == 0);
21}
test/cases/math.zig deleted-500
...@@ -1,500 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const maxInt = std.math.maxInt;
4const minInt = std.math.minInt;
5
6test "division" {
7 testDivision();
8 comptime testDivision();
9}
10fn testDivision() void {
11 assert(div(u32, 13, 3) == 4);
12 assert(div(f16, 1.0, 2.0) == 0.5);
13 assert(div(f32, 1.0, 2.0) == 0.5);
14
15 assert(divExact(u32, 55, 11) == 5);
16 assert(divExact(i32, -55, 11) == -5);
17 assert(divExact(f16, 55.0, 11.0) == 5.0);
18 assert(divExact(f16, -55.0, 11.0) == -5.0);
19 assert(divExact(f32, 55.0, 11.0) == 5.0);
20 assert(divExact(f32, -55.0, 11.0) == -5.0);
21
22 assert(divFloor(i32, 5, 3) == 1);
23 assert(divFloor(i32, -5, 3) == -2);
24 assert(divFloor(f16, 5.0, 3.0) == 1.0);
25 assert(divFloor(f16, -5.0, 3.0) == -2.0);
26 assert(divFloor(f32, 5.0, 3.0) == 1.0);
27 assert(divFloor(f32, -5.0, 3.0) == -2.0);
28 assert(divFloor(i32, -0x80000000, -2) == 0x40000000);
29 assert(divFloor(i32, 0, -0x80000000) == 0);
30 assert(divFloor(i32, -0x40000001, 0x40000000) == -2);
31 assert(divFloor(i32, -0x80000000, 1) == -0x80000000);
32
33 assert(divTrunc(i32, 5, 3) == 1);
34 assert(divTrunc(i32, -5, 3) == -1);
35 assert(divTrunc(f16, 5.0, 3.0) == 1.0);
36 assert(divTrunc(f16, -5.0, 3.0) == -1.0);
37 assert(divTrunc(f32, 5.0, 3.0) == 1.0);
38 assert(divTrunc(f32, -5.0, 3.0) == -1.0);
39 assert(divTrunc(f64, 5.0, 3.0) == 1.0);
40 assert(divTrunc(f64, -5.0, 3.0) == -1.0);
41
42 comptime {
43 assert(
44 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
45 );
46 assert(
47 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
48 );
49 assert(
50 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
51 );
52 assert(
53 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
54 );
55 assert(
56 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
57 );
58 assert(
59 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
60 );
61 assert(
62 4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
63 );
64 }
65}
66fn div(comptime T: type, a: T, b: T) T {
67 return a / b;
68}
69fn divExact(comptime T: type, a: T, b: T) T {
70 return @divExact(a, b);
71}
72fn divFloor(comptime T: type, a: T, b: T) T {
73 return @divFloor(a, b);
74}
75fn divTrunc(comptime T: type, a: T, b: T) T {
76 return @divTrunc(a, b);
77}
78
79test "@addWithOverflow" {
80 var result: u8 = undefined;
81 assert(@addWithOverflow(u8, 250, 100, &result));
82 assert(!@addWithOverflow(u8, 100, 150, &result));
83 assert(result == 250);
84}
85
86// TODO test mulWithOverflow
87// TODO test subWithOverflow
88
89test "@shlWithOverflow" {
90 var result: u16 = undefined;
91 assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
92 assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
93 assert(result == 0b1011111111111100);
94}
95
96test "@clz" {
97 testClz();
98 comptime testClz();
99}
100
101fn testClz() void {
102 assert(clz(u8(0b00001010)) == 4);
103 assert(clz(u8(0b10001010)) == 0);
104 assert(clz(u8(0b00000000)) == 8);
105 assert(clz(u128(0xffffffffffffffff)) == 64);
106 assert(clz(u128(0x10000000000000000)) == 63);
107}
108
109fn clz(x: var) usize {
110 return @clz(x);
111}
112
113test "@ctz" {
114 testCtz();
115 comptime testCtz();
116}
117
118fn testCtz() void {
119 assert(ctz(u8(0b10100000)) == 5);
120 assert(ctz(u8(0b10001010)) == 1);
121 assert(ctz(u8(0b00000000)) == 8);
122}
123
124fn ctz(x: var) usize {
125 return @ctz(x);
126}
127
128test "assignment operators" {
129 var i: u32 = 0;
130 i += 5;
131 assert(i == 5);
132 i -= 2;
133 assert(i == 3);
134 i *= 20;
135 assert(i == 60);
136 i /= 3;
137 assert(i == 20);
138 i %= 11;
139 assert(i == 9);
140 i <<= 1;
141 assert(i == 18);
142 i >>= 2;
143 assert(i == 4);
144 i = 6;
145 i &= 5;
146 assert(i == 4);
147 i ^= 6;
148 assert(i == 2);
149 i = 6;
150 i |= 3;
151 assert(i == 7);
152}
153
154test "three expr in a row" {
155 testThreeExprInARow(false, true);
156 comptime testThreeExprInARow(false, true);
157}
158fn testThreeExprInARow(f: bool, t: bool) void {
159 assertFalse(f or f or f);
160 assertFalse(t and t and f);
161 assertFalse(1 | 2 | 4 != 7);
162 assertFalse(3 ^ 6 ^ 8 != 13);
163 assertFalse(7 & 14 & 28 != 4);
164 assertFalse(9 << 1 << 2 != 9 << 3);
165 assertFalse(90 >> 1 >> 2 != 90 >> 3);
166 assertFalse(100 - 1 + 1000 != 1099);
167 assertFalse(5 * 4 / 2 % 3 != 1);
168 assertFalse(i32(i32(5)) != 5);
169 assertFalse(!!false);
170 assertFalse(i32(7) != --(i32(7)));
171}
172fn assertFalse(b: bool) void {
173 assert(!b);
174}
175
176test "const number literal" {
177 const one = 1;
178 const eleven = ten + one;
179
180 assert(eleven == 11);
181}
182const ten = 10;
183
184test "unsigned wrapping" {
185 testUnsignedWrappingEval(maxInt(u32));
186 comptime testUnsignedWrappingEval(maxInt(u32));
187}
188fn testUnsignedWrappingEval(x: u32) void {
189 const zero = x +% 1;
190 assert(zero == 0);
191 const orig = zero -% 1;
192 assert(orig == maxInt(u32));
193}
194
195test "signed wrapping" {
196 testSignedWrappingEval(maxInt(i32));
197 comptime testSignedWrappingEval(maxInt(i32));
198}
199fn testSignedWrappingEval(x: i32) void {
200 const min_val = x +% 1;
201 assert(min_val == minInt(i32));
202 const max_val = min_val -% 1;
203 assert(max_val == maxInt(i32));
204}
205
206test "negation wrapping" {
207 testNegationWrappingEval(minInt(i16));
208 comptime testNegationWrappingEval(minInt(i16));
209}
210fn testNegationWrappingEval(x: i16) void {
211 assert(x == -32768);
212 const neg = -%x;
213 assert(neg == -32768);
214}
215
216test "unsigned 64-bit division" {
217 test_u64_div();
218 comptime test_u64_div();
219}
220fn test_u64_div() void {
221 const result = divWithResult(1152921504606846976, 34359738365);
222 assert(result.quotient == 33554432);
223 assert(result.remainder == 100663296);
224}
225fn divWithResult(a: u64, b: u64) DivResult {
226 return DivResult{
227 .quotient = a / b,
228 .remainder = a % b,
229 };
230}
231const DivResult = struct {
232 quotient: u64,
233 remainder: u64,
234};
235
236test "binary not" {
237 assert(comptime x: {
238 break :x ~u16(0b1010101010101010) == 0b0101010101010101;
239 });
240 assert(comptime x: {
241 break :x ~u64(2147483647) == 18446744071562067968;
242 });
243 testBinaryNot(0b1010101010101010);
244}
245
246fn testBinaryNot(x: u16) void {
247 assert(~x == 0b0101010101010101);
248}
249
250test "small int addition" {
251 var x: @IntType(false, 2) = 0;
252 assert(x == 0);
253
254 x += 1;
255 assert(x == 1);
256
257 x += 1;
258 assert(x == 2);
259
260 x += 1;
261 assert(x == 3);
262
263 var result: @typeOf(x) = 3;
264 assert(@addWithOverflow(@typeOf(x), x, 1, &result));
265
266 assert(result == 0);
267}
268
269test "float equality" {
270 const x: f64 = 0.012;
271 const y: f64 = x + 1.0;
272
273 testFloatEqualityImpl(x, y);
274 comptime testFloatEqualityImpl(x, y);
275}
276
277fn testFloatEqualityImpl(x: f64, y: f64) void {
278 const y2 = x + 1.0;
279 assert(y == y2);
280}
281
282test "allow signed integer division/remainder when values are comptime known and positive or exact" {
283 assert(5 / 3 == 1);
284 assert(-5 / -3 == 1);
285 assert(-6 / 3 == -2);
286
287 assert(5 % 3 == 2);
288 assert(-6 % 3 == 0);
289}
290
291test "hex float literal parsing" {
292 comptime assert(0x1.0 == 1.0);
293}
294
295test "quad hex float literal parsing in range" {
296 const a = 0x1.af23456789bbaaab347645365cdep+5;
297 const b = 0x1.dedafcff354b6ae9758763545432p-9;
298 const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
299 const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
300}
301
302test "quad hex float literal parsing accurate" {
303 const a: f128 = 0x1.1111222233334444555566667777p+0;
304
305 // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
306 const expected: u128 = 0x3fff1111222233334444555566667777;
307 assert(@bitCast(u128, a) == expected);
308}
309
310test "hex float literal within range" {
311 const a = 0x1.0p16383;
312 const b = 0x0.1p16387;
313 const c = 0x1.0p-16382;
314}
315
316test "truncating shift left" {
317 testShlTrunc(maxInt(u16));
318 comptime testShlTrunc(maxInt(u16));
319}
320fn testShlTrunc(x: u16) void {
321 const shifted = x << 1;
322 assert(shifted == 65534);
323}
324
325test "truncating shift right" {
326 testShrTrunc(maxInt(u16));
327 comptime testShrTrunc(maxInt(u16));
328}
329fn testShrTrunc(x: u16) void {
330 const shifted = x >> 1;
331 assert(shifted == 32767);
332}
333
334test "exact shift left" {
335 testShlExact(0b00110101);
336 comptime testShlExact(0b00110101);
337}
338fn testShlExact(x: u8) void {
339 const shifted = @shlExact(x, 2);
340 assert(shifted == 0b11010100);
341}
342
343test "exact shift right" {
344 testShrExact(0b10110100);
345 comptime testShrExact(0b10110100);
346}
347fn testShrExact(x: u8) void {
348 const shifted = @shrExact(x, 2);
349 assert(shifted == 0b00101101);
350}
351
352test "comptime_int addition" {
353 comptime {
354 assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
355 assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
356 }
357}
358
359test "comptime_int multiplication" {
360 comptime {
361 assert(
362 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
363 );
364 assert(
365 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
366 );
367 }
368}
369
370test "comptime_int shifting" {
371 comptime {
372 assert((u128(1) << 127) == 0x80000000000000000000000000000000);
373 }
374}
375
376test "comptime_int multi-limb shift and mask" {
377 comptime {
378 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
379
380 assert(u32(a & 0xffffffff) == 0xaaaaaaab);
381 a >>= 32;
382 assert(u32(a & 0xffffffff) == 0xeeeeeeef);
383 a >>= 32;
384 assert(u32(a & 0xffffffff) == 0xa0000001);
385 a >>= 32;
386 assert(u32(a & 0xffffffff) == 0xefffffff);
387 a >>= 32;
388
389 assert(a == 0);
390 }
391}
392
393test "comptime_int multi-limb partial shift right" {
394 comptime {
395 var a = 0x1ffffffffeeeeeeee;
396 a >>= 16;
397 assert(a == 0x1ffffffffeeee);
398 }
399}
400
401test "xor" {
402 test_xor();
403 comptime test_xor();
404}
405
406fn test_xor() void {
407 assert(0xFF ^ 0x00 == 0xFF);
408 assert(0xF0 ^ 0x0F == 0xFF);
409 assert(0xFF ^ 0xF0 == 0x0F);
410 assert(0xFF ^ 0x0F == 0xF0);
411 assert(0xFF ^ 0xFF == 0x00);
412}
413
414test "comptime_int xor" {
415 comptime {
416 assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
417 assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
418 assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
419 assert(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
420 assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
421 assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
422 assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
423 assert(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
424 }
425}
426
427test "f128" {
428 test_f128();
429 comptime test_f128();
430}
431
432fn make_f128(x: f128) f128 {
433 return x;
434}
435
436fn test_f128() void {
437 assert(@sizeOf(f128) == 16);
438 assert(make_f128(1.0) == 1.0);
439 assert(make_f128(1.0) != 1.1);
440 assert(make_f128(1.0) > 0.9);
441 assert(make_f128(1.0) >= 0.9);
442 assert(make_f128(1.0) >= 1.0);
443 should_not_be_zero(1.0);
444}
445
446fn should_not_be_zero(x: f128) void {
447 assert(x != 0.0);
448}
449
450test "comptime float rem int" {
451 comptime {
452 var x = f32(1) % 2;
453 assert(x == 1.0);
454 }
455}
456
457test "remainder division" {
458 comptime remdiv(f16);
459 comptime remdiv(f32);
460 comptime remdiv(f64);
461 comptime remdiv(f128);
462 remdiv(f16);
463 remdiv(f64);
464 remdiv(f128);
465}
466
467fn remdiv(comptime T: type) void {
468 assert(T(1) == T(1) % T(2));
469 assert(T(1) == T(7) % T(3));
470}
471
472test "@sqrt" {
473 testSqrt(f64, 12.0);
474 comptime testSqrt(f64, 12.0);
475 testSqrt(f32, 13.0);
476 comptime testSqrt(f32, 13.0);
477 testSqrt(f16, 13.0);
478 comptime testSqrt(f16, 13.0);
479
480 const x = 14.0;
481 const y = x * x;
482 const z = @sqrt(@typeOf(y), y);
483 comptime assert(z == x);
484}
485
486fn testSqrt(comptime T: type, x: T) void {
487 assert(@sqrt(T, x * x) == x);
488}
489
490test "comptime_int param and return" {
491 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
492 assert(a == 137114567242441932203689521744947848950);
493
494 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
495 assert(b == 985095453608931032642182098849559179469148836107390954364380);
496}
497
498fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
499 return a + b;
500}
test/cases/merge_error_sets.zig deleted-21
...@@ -1,21 +0,0 @@
1const A = error{
2 FileNotFound,
3 NotDir,
4};
5const B = error{OutOfMemory};
6
7const C = A || B;
8
9fn foo() C!void {
10 return error.NotDir;
11}
12
13test "merge error sets" {
14 if (foo()) {
15 @panic("unexpected");
16 } else |err| switch (err) {
17 error.OutOfMemory => @panic("unexpected"),
18 error.FileNotFound => @panic("unexpected"),
19 error.NotDir => {},
20 }
21}
test/cases/misc.zig deleted-681
...@@ -1,681 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4const cstr = std.cstr;
5const builtin = @import("builtin");
6const maxInt = std.math.maxInt;
7
8// normal comment
9
10/// this is a documentation comment
11/// doc comment line 2
12fn emptyFunctionWithComments() void {}
13
14test "empty function with comments" {
15 emptyFunctionWithComments();
16}
17
18comptime {
19 @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal);
20}
21
22extern fn disabledExternFn() void {}
23
24test "call disabled extern fn" {
25 disabledExternFn();
26}
27
28test "@IntType builtin" {
29 assert(@IntType(true, 8) == i8);
30 assert(@IntType(true, 16) == i16);
31 assert(@IntType(true, 32) == i32);
32 assert(@IntType(true, 64) == i64);
33
34 assert(@IntType(false, 8) == u8);
35 assert(@IntType(false, 16) == u16);
36 assert(@IntType(false, 32) == u32);
37 assert(@IntType(false, 64) == u64);
38
39 assert(i8.bit_count == 8);
40 assert(i16.bit_count == 16);
41 assert(i32.bit_count == 32);
42 assert(i64.bit_count == 64);
43
44 assert(i8.is_signed);
45 assert(i16.is_signed);
46 assert(i32.is_signed);
47 assert(i64.is_signed);
48 assert(isize.is_signed);
49
50 assert(!u8.is_signed);
51 assert(!u16.is_signed);
52 assert(!u32.is_signed);
53 assert(!u64.is_signed);
54 assert(!usize.is_signed);
55}
56
57test "floating point primitive bit counts" {
58 assert(f16.bit_count == 16);
59 assert(f32.bit_count == 32);
60 assert(f64.bit_count == 64);
61}
62
63test "short circuit" {
64 testShortCircuit(false, true);
65 comptime testShortCircuit(false, true);
66}
67
68fn testShortCircuit(f: bool, t: bool) void {
69 var hit_1 = f;
70 var hit_2 = f;
71 var hit_3 = f;
72 var hit_4 = f;
73
74 if (t or x: {
75 assert(f);
76 break :x f;
77 }) {
78 hit_1 = t;
79 }
80 if (f or x: {
81 hit_2 = t;
82 break :x f;
83 }) {
84 assert(f);
85 }
86
87 if (t and x: {
88 hit_3 = t;
89 break :x f;
90 }) {
91 assert(f);
92 }
93 if (f and x: {
94 assert(f);
95 break :x f;
96 }) {
97 assert(f);
98 } else {
99 hit_4 = t;
100 }
101 assert(hit_1);
102 assert(hit_2);
103 assert(hit_3);
104 assert(hit_4);
105}
106
107test "truncate" {
108 assert(testTruncate(0x10fd) == 0xfd);
109}
110fn testTruncate(x: u32) u8 {
111 return @truncate(u8, x);
112}
113
114fn first4KeysOfHomeRow() []const u8 {
115 return "aoeu";
116}
117
118test "return string from function" {
119 assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
120}
121
122const g1: i32 = 1233 + 1;
123var g2: i32 = 0;
124
125test "global variables" {
126 assert(g2 == 0);
127 g2 = g1;
128 assert(g2 == 1234);
129}
130
131test "memcpy and memset intrinsics" {
132 var foo: [20]u8 = undefined;
133 var bar: [20]u8 = undefined;
134
135 @memset(foo[0..].ptr, 'A', foo.len);
136 @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
137
138 if (bar[11] != 'A') unreachable;
139}
140
141test "builtin static eval" {
142 const x: i32 = comptime x: {
143 break :x 1 + 2 + 3;
144 };
145 assert(x == comptime 6);
146}
147
148test "slicing" {
149 var array: [20]i32 = undefined;
150
151 array[5] = 1234;
152
153 var slice = array[5..10];
154
155 if (slice.len != 5) unreachable;
156
157 const ptr = &slice[0];
158 if (ptr.* != 1234) unreachable;
159
160 var slice_rest = array[10..];
161 if (slice_rest.len != 10) unreachable;
162}
163
164test "constant equal function pointers" {
165 const alias = emptyFn;
166 assert(comptime x: {
167 break :x emptyFn == alias;
168 });
169}
170
171fn emptyFn() void {}
172
173test "hex escape" {
174 assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
175}
176
177test "string concatenation" {
178 assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
179}
180
181test "array mult operator" {
182 assert(mem.eql(u8, "ab" ** 5, "ababababab"));
183}
184
185test "string escapes" {
186 assert(mem.eql(u8, "\"", "\x22"));
187 assert(mem.eql(u8, "\'", "\x27"));
188 assert(mem.eql(u8, "\n", "\x0a"));
189 assert(mem.eql(u8, "\r", "\x0d"));
190 assert(mem.eql(u8, "\t", "\x09"));
191 assert(mem.eql(u8, "\\", "\x5c"));
192 assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
193}
194
195test "multiline string" {
196 const s1 =
197 \\one
198 \\two)
199 \\three
200 ;
201 const s2 = "one\ntwo)\nthree";
202 assert(mem.eql(u8, s1, s2));
203}
204
205test "multiline C string" {
206 const s1 =
207 c\\one
208 c\\two)
209 c\\three
210 ;
211 const s2 = c"one\ntwo)\nthree";
212 assert(cstr.cmp(s1, s2) == 0);
213}
214
215test "type equality" {
216 assert(*const u8 != *u8);
217}
218
219const global_a: i32 = 1234;
220const global_b: *const i32 = &global_a;
221const global_c: *const f32 = @ptrCast(*const f32, global_b);
222test "compile time global reinterpret" {
223 const d = @ptrCast(*const i32, global_c);
224 assert(d.* == 1234);
225}
226
227test "explicit cast maybe pointers" {
228 const a: ?*i32 = undefined;
229 const b: ?*f32 = @ptrCast(?*f32, a);
230}
231
232test "generic malloc free" {
233 const a = memAlloc(u8, 10) catch unreachable;
234 memFree(u8, a);
235}
236var some_mem: [100]u8 = undefined;
237fn memAlloc(comptime T: type, n: usize) anyerror![]T {
238 return @ptrCast([*]T, &some_mem[0])[0..n];
239}
240fn memFree(comptime T: type, memory: []T) void {}
241
242test "cast undefined" {
243 const array: [100]u8 = undefined;
244 const slice = ([]const u8)(array);
245 testCastUndefined(slice);
246}
247fn testCastUndefined(x: []const u8) void {}
248
249test "cast small unsigned to larger signed" {
250 assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
251 assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
252}
253fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
254 return x;
255}
256fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
257 return x;
258}
259
260test "implicit cast after unreachable" {
261 assert(outer() == 1234);
262}
263fn inner() i32 {
264 return 1234;
265}
266fn outer() i64 {
267 return inner();
268}
269
270test "pointer dereferencing" {
271 var x = i32(3);
272 const y = &x;
273
274 y.* += 1;
275
276 assert(x == 4);
277 assert(y.* == 4);
278}
279
280test "call result of if else expression" {
281 assert(mem.eql(u8, f2(true), "a"));
282 assert(mem.eql(u8, f2(false), "b"));
283}
284fn f2(x: bool) []const u8 {
285 return (if (x) fA else fB)();
286}
287fn fA() []const u8 {
288 return "a";
289}
290fn fB() []const u8 {
291 return "b";
292}
293
294test "const expression eval handling of variables" {
295 var x = true;
296 while (x) {
297 x = false;
298 }
299}
300
301test "constant enum initialization with differing sizes" {
302 test3_1(test3_foo);
303 test3_2(test3_bar);
304}
305const Test3Foo = union(enum) {
306 One: void,
307 Two: f32,
308 Three: Test3Point,
309};
310const Test3Point = struct {
311 x: i32,
312 y: i32,
313};
314const test3_foo = Test3Foo{
315 .Three = Test3Point{
316 .x = 3,
317 .y = 4,
318 },
319};
320const test3_bar = Test3Foo{ .Two = 13 };
321fn test3_1(f: Test3Foo) void {
322 switch (f) {
323 Test3Foo.Three => |pt| {
324 assert(pt.x == 3);
325 assert(pt.y == 4);
326 },
327 else => unreachable,
328 }
329}
330fn test3_2(f: Test3Foo) void {
331 switch (f) {
332 Test3Foo.Two => |x| {
333 assert(x == 13);
334 },
335 else => unreachable,
336 }
337}
338
339test "character literals" {
340 assert('\'' == single_quote);
341}
342const single_quote = '\'';
343
344test "take address of parameter" {
345 testTakeAddressOfParameter(12.34);
346}
347fn testTakeAddressOfParameter(f: f32) void {
348 const f_ptr = &f;
349 assert(f_ptr.* == 12.34);
350}
351
352test "pointer comparison" {
353 const a = ([]const u8)("a");
354 const b = &a;
355 assert(ptrEql(b, b));
356}
357fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
358 return a == b;
359}
360
361test "C string concatenation" {
362 const a = c"OK" ++ c" IT " ++ c"WORKED";
363 const b = c"OK IT WORKED";
364
365 const len = cstr.len(b);
366 const len_with_null = len + 1;
367 {
368 var i: u32 = 0;
369 while (i < len_with_null) : (i += 1) {
370 assert(a[i] == b[i]);
371 }
372 }
373 assert(a[len] == 0);
374 assert(b[len] == 0);
375}
376
377test "cast slice to u8 slice" {
378 assert(@sizeOf(i32) == 4);
379 var big_thing_array = []i32{
380 1,
381 2,
382 3,
383 4,
384 };
385 const big_thing_slice: []i32 = big_thing_array[0..];
386 const bytes = @sliceToBytes(big_thing_slice);
387 assert(bytes.len == 4 * 4);
388 bytes[4] = 0;
389 bytes[5] = 0;
390 bytes[6] = 0;
391 bytes[7] = 0;
392 assert(big_thing_slice[1] == 0);
393 const big_thing_again = @bytesToSlice(i32, bytes);
394 assert(big_thing_again[2] == 3);
395 big_thing_again[2] = -1;
396 assert(bytes[8] == maxInt(u8));
397 assert(bytes[9] == maxInt(u8));
398 assert(bytes[10] == maxInt(u8));
399 assert(bytes[11] == maxInt(u8));
400}
401
402test "pointer to void return type" {
403 testPointerToVoidReturnType() catch unreachable;
404}
405fn testPointerToVoidReturnType() anyerror!void {
406 const a = testPointerToVoidReturnType2();
407 return a.*;
408}
409const test_pointer_to_void_return_type_x = void{};
410fn testPointerToVoidReturnType2() *const void {
411 return &test_pointer_to_void_return_type_x;
412}
413
414test "non const ptr to aliased type" {
415 const int = i32;
416 assert(?*int == ?*i32);
417}
418
419test "array 2D const double ptr" {
420 const rect_2d_vertexes = [][1]f32{
421 []f32{1.0},
422 []f32{2.0},
423 };
424 testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
425}
426
427fn testArray2DConstDoublePtr(ptr: *const f32) void {
428 const ptr2 = @ptrCast([*]const f32, ptr);
429 assert(ptr2[0] == 1.0);
430 assert(ptr2[1] == 2.0);
431}
432
433const Tid = builtin.TypeId;
434const AStruct = struct {
435 x: i32,
436};
437const AnEnum = enum {
438 One,
439 Two,
440};
441const AUnionEnum = union(enum) {
442 One: i32,
443 Two: void,
444};
445const AUnion = union {
446 One: void,
447 Two: void,
448};
449
450test "@typeId" {
451 comptime {
452 assert(@typeId(type) == Tid.Type);
453 assert(@typeId(void) == Tid.Void);
454 assert(@typeId(bool) == Tid.Bool);
455 assert(@typeId(noreturn) == Tid.NoReturn);
456 assert(@typeId(i8) == Tid.Int);
457 assert(@typeId(u8) == Tid.Int);
458 assert(@typeId(i64) == Tid.Int);
459 assert(@typeId(u64) == Tid.Int);
460 assert(@typeId(f32) == Tid.Float);
461 assert(@typeId(f64) == Tid.Float);
462 assert(@typeId(*f32) == Tid.Pointer);
463 assert(@typeId([2]u8) == Tid.Array);
464 assert(@typeId(AStruct) == Tid.Struct);
465 assert(@typeId(@typeOf(1)) == Tid.ComptimeInt);
466 assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
467 assert(@typeId(@typeOf(undefined)) == Tid.Undefined);
468 assert(@typeId(@typeOf(null)) == Tid.Null);
469 assert(@typeId(?i32) == Tid.Optional);
470 assert(@typeId(anyerror!i32) == Tid.ErrorUnion);
471 assert(@typeId(anyerror) == Tid.ErrorSet);
472 assert(@typeId(AnEnum) == Tid.Enum);
473 assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
474 assert(@typeId(AUnionEnum) == Tid.Union);
475 assert(@typeId(AUnion) == Tid.Union);
476 assert(@typeId(fn () void) == Tid.Fn);
477 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
478 // TODO bound fn
479 // TODO arg tuple
480 // TODO opaque
481 }
482}
483
484test "@typeName" {
485 const Struct = struct {};
486 const Union = union {
487 unused: u8,
488 };
489 const Enum = enum {
490 Unused,
491 };
492 comptime {
493 assert(mem.eql(u8, @typeName(i64), "i64"));
494 assert(mem.eql(u8, @typeName(*usize), "*usize"));
495 // https://github.com/ziglang/zig/issues/675
496 assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
497 assert(mem.eql(u8, @typeName(Struct), "Struct"));
498 assert(mem.eql(u8, @typeName(Union), "Union"));
499 assert(mem.eql(u8, @typeName(Enum), "Enum"));
500 }
501}
502
503fn TypeFromFn(comptime T: type) type {
504 return struct {};
505}
506
507test "volatile load and store" {
508 var number: i32 = 1234;
509 const ptr = (*volatile i32)(&number);
510 ptr.* += 1;
511 assert(ptr.* == 1235);
512}
513
514test "slice string literal has type []const u8" {
515 comptime {
516 assert(@typeOf("aoeu"[0..]) == []const u8);
517 const array = []i32{
518 1,
519 2,
520 3,
521 4,
522 };
523 assert(@typeOf(array[0..]) == []const i32);
524 }
525}
526
527test "global variable initialized to global variable array element" {
528 assert(global_ptr == &gdt[0]);
529}
530const GDTEntry = struct {
531 field: i32,
532};
533var gdt = []GDTEntry{
534 GDTEntry{ .field = 1 },
535 GDTEntry{ .field = 2 },
536};
537var global_ptr = &gdt[0];
538
539// can't really run this test but we can make sure it has no compile error
540// and generates code
541const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
542export fn writeToVRam() void {
543 vram[0] = 'X';
544}
545
546test "pointer child field" {
547 assert((*u32).Child == u32);
548}
549
550const OpaqueA = @OpaqueType();
551const OpaqueB = @OpaqueType();
552test "@OpaqueType" {
553 assert(*OpaqueA != *OpaqueB);
554 assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
555 assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
556}
557
558test "variable is allowed to be a pointer to an opaque type" {
559 var x: i32 = 1234;
560 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
561}
562fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
563 var a = ptr;
564 return a;
565}
566
567test "comptime if inside runtime while which unconditionally breaks" {
568 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
569 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
570}
571fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
572 while (cond) {
573 if (false) {}
574 break;
575 }
576}
577
578test "implicit comptime while" {
579 while (false) {
580 @compileError("bad");
581 }
582}
583
584test "struct inside function" {
585 testStructInFn();
586 comptime testStructInFn();
587}
588
589fn testStructInFn() void {
590 const BlockKind = u32;
591
592 const Block = struct {
593 kind: BlockKind,
594 };
595
596 var block = Block{ .kind = 1234 };
597
598 block.kind += 1;
599
600 assert(block.kind == 1235);
601}
602
603fn fnThatClosesOverLocalConst() type {
604 const c = 1;
605 return struct {
606 fn g() i32 {
607 return c;
608 }
609 };
610}
611
612test "function closes over local const" {
613 const x = fnThatClosesOverLocalConst().g();
614 assert(x == 1);
615}
616
617test "cold function" {
618 thisIsAColdFn();
619 comptime thisIsAColdFn();
620}
621
622fn thisIsAColdFn() void {
623 @setCold(true);
624}
625
626const PackedStruct = packed struct {
627 a: u8,
628 b: u8,
629};
630const PackedUnion = packed union {
631 a: u8,
632 b: u32,
633};
634const PackedEnum = packed enum {
635 A,
636 B,
637};
638
639test "packed struct, enum, union parameters in extern function" {
640 testPackedStuff(&(PackedStruct{
641 .a = 1,
642 .b = 2,
643 }), &(PackedUnion{ .a = 1 }), PackedEnum.A);
644}
645
646export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {}
647
648test "slicing zero length array" {
649 const s1 = ""[0..];
650 const s2 = ([]u32{})[0..];
651 assert(s1.len == 0);
652 assert(s2.len == 0);
653 assert(mem.eql(u8, s1, ""));
654 assert(mem.eql(u32, s2, []u32{}));
655}
656
657const addr1 = @ptrCast(*const u8, emptyFn);
658test "comptime cast fn to ptr" {
659 const addr2 = @ptrCast(*const u8, emptyFn);
660 comptime assert(addr1 == addr2);
661}
662
663test "equality compare fn ptrs" {
664 var a = emptyFn;
665 assert(a == a);
666}
667
668test "self reference through fn ptr field" {
669 const S = struct {
670 const A = struct {
671 f: fn (A) u8,
672 };
673
674 fn foo(a: A) u8 {
675 return 12;
676 }
677 };
678 var a: S.A = undefined;
679 a.f = S.foo;
680 assert(a.f(a) == 12);
681}
test/cases/namespace_depends_on_compile_var/a.zig deleted-1
...@@ -1 +0,0 @@
1pub const a_bool = true;
test/cases/namespace_depends_on_compile_var/b.zig deleted-1
...@@ -1 +0,0 @@
1pub const a_bool = false;
test/cases/namespace_depends_on_compile_var/index.zig deleted-14
...@@ -1,14 +0,0 @@
1const builtin = @import("builtin");
2const assert = @import("std").debug.assert;
3
4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {
6 assert(some_namespace.a_bool);
7 } else {
8 assert(!some_namespace.a_bool);
9 }
10}
11const some_namespace = switch (builtin.os) {
12 builtin.Os.linux => @import("a.zig"),
13 else => @import("b.zig"),
14};
test/cases/new_stack_call.zig deleted-26
...@@ -1,26 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4var new_stack_bytes: [1024]u8 = undefined;
5
6test "calling a function with a new stack" {
7 const arg = 1234;
8
9 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
10 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
11 _ = targetFunction(arg);
12
13 assert(arg == 1234);
14 assert(a < b);
15}
16
17fn targetFunction(x: i32) usize {
18 assert(x == 1234);
19
20 var local_variable: i32 = 42;
21 const ptr = &local_variable;
22 ptr.* += 1;
23
24 assert(local_variable == 43);
25 return @ptrToInt(ptr);
26}
test/cases/null.zig deleted-162
...@@ -1,162 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "optional type" {
4 const x: ?bool = true;
5
6 if (x) |y| {
7 if (y) {
8 // OK
9 } else {
10 unreachable;
11 }
12 } else {
13 unreachable;
14 }
15
16 const next_x: ?i32 = null;
17
18 const z = next_x orelse 1234;
19
20 assert(z == 1234);
21
22 const final_x: ?i32 = 13;
23
24 const num = final_x orelse unreachable;
25
26 assert(num == 13);
27}
28
29test "test maybe object and get a pointer to the inner value" {
30 var maybe_bool: ?bool = true;
31
32 if (maybe_bool) |*b| {
33 b.* = false;
34 }
35
36 assert(maybe_bool.? == false);
37}
38
39test "rhs maybe unwrap return" {
40 const x: ?bool = true;
41 const y = x orelse return;
42}
43
44test "maybe return" {
45 maybeReturnImpl();
46 comptime maybeReturnImpl();
47}
48
49fn maybeReturnImpl() void {
50 assert(foo(1235).?);
51 if (foo(null) != null) unreachable;
52 assert(!foo(1234).?);
53}
54
55fn foo(x: ?i32) ?bool {
56 const value = x orelse return null;
57 return value > 1234;
58}
59
60test "if var maybe pointer" {
61 assert(shouldBeAPlus1(Particle{
62 .a = 14,
63 .b = 1,
64 .c = 1,
65 .d = 1,
66 }) == 15);
67}
68fn shouldBeAPlus1(p: Particle) u64 {
69 var maybe_particle: ?Particle = p;
70 if (maybe_particle) |*particle| {
71 particle.a += 1;
72 }
73 if (maybe_particle) |particle| {
74 return particle.a;
75 }
76 return 0;
77}
78const Particle = struct {
79 a: u64,
80 b: u64,
81 c: u64,
82 d: u64,
83};
84
85test "null literal outside function" {
86 const is_null = here_is_a_null_literal.context == null;
87 assert(is_null);
88
89 const is_non_null = here_is_a_null_literal.context != null;
90 assert(!is_non_null);
91}
92const SillyStruct = struct {
93 context: ?i32,
94};
95const here_is_a_null_literal = SillyStruct{ .context = null };
96
97test "test null runtime" {
98 testTestNullRuntime(null);
99}
100fn testTestNullRuntime(x: ?i32) void {
101 assert(x == null);
102 assert(!(x != null));
103}
104
105test "optional void" {
106 optionalVoidImpl();
107 comptime optionalVoidImpl();
108}
109
110fn optionalVoidImpl() void {
111 assert(bar(null) == null);
112 assert(bar({}) != null);
113}
114
115fn bar(x: ?void) ?void {
116 if (x) |_| {
117 return {};
118 } else {
119 return null;
120 }
121}
122
123const StructWithOptional = struct {
124 field: ?i32,
125};
126
127var struct_with_optional: StructWithOptional = undefined;
128
129test "unwrap optional which is field of global var" {
130 struct_with_optional.field = null;
131 if (struct_with_optional.field) |payload| {
132 unreachable;
133 }
134 struct_with_optional.field = 1234;
135 if (struct_with_optional.field) |payload| {
136 assert(payload == 1234);
137 } else {
138 unreachable;
139 }
140}
141
142test "null with default unwrap" {
143 const x: i32 = null orelse 1;
144 assert(x == 1);
145}
146
147test "optional types" {
148 comptime {
149 const opt_type_struct = StructWithOptionalType{ .t = u8 };
150 assert(opt_type_struct.t != null and opt_type_struct.t.? == u8);
151 }
152}
153
154const StructWithOptionalType = struct {
155 t: ?type,
156};
157
158test "optional pointer to 0 bit type null value at runtime" {
159 const EmptyStruct = struct {};
160 var x: ?*EmptyStruct = null;
161 assert(x == null);
162}
test/cases/optional.zig deleted-30
...@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3pub const EmptyStruct = struct {};
4
5test "optional pointer to size zero struct" {
6 var e = EmptyStruct{};
7 var o: ?*EmptyStruct = &e;
8 assert(o != null);
9}
10
11test "equality compare nullable pointers" {
12 testNullPtrsEql();
13 comptime testNullPtrsEql();
14}
15
16fn testNullPtrsEql() void {
17 var number: i32 = 1234;
18
19 var x: ?*i32 = null;
20 var y: ?*i32 = null;
21 assert(x == y);
22 y = &number;
23 assert(x != y);
24 assert(x != &number);
25 assert(&number != x);
26 x = &number;
27 assert(x == y);
28 assert(x == &number);
29 assert(&number == x);
30}
test/cases/pointers.zig deleted-44
...@@ -1,44 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "dereference pointer" {
5 comptime testDerefPtr();
6 testDerefPtr();
7}
8
9fn testDerefPtr() void {
10 var x: i32 = 1234;
11 var y = &x;
12 y.* += 1;
13 assert(x == 1235);
14}
15
16test "pointer arithmetic" {
17 var ptr = c"abcd";
18
19 assert(ptr[0] == 'a');
20 ptr += 1;
21 assert(ptr[0] == 'b');
22 ptr += 1;
23 assert(ptr[0] == 'c');
24 ptr += 1;
25 assert(ptr[0] == 'd');
26 ptr += 1;
27 assert(ptr[0] == 0);
28 ptr -= 1;
29 assert(ptr[0] == 'd');
30 ptr -= 1;
31 assert(ptr[0] == 'c');
32 ptr -= 1;
33 assert(ptr[0] == 'b');
34 ptr -= 1;
35 assert(ptr[0] == 'a');
36}
37
38test "double pointer parsing" {
39 comptime assert(PtrOf(PtrOf(i32)) == **i32);
40}
41
42fn PtrOf(comptime T: type) type {
43 return *T;
44}
test/cases/popcount.zig deleted-24
...@@ -1,24 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "@popCount" {
4 comptime testPopCount();
5 testPopCount();
6}
7
8fn testPopCount() void {
9 {
10 var x: u32 = 0xaa;
11 assert(@popCount(x) == 4);
12 }
13 {
14 var x: u32 = 0xaaaaaaaa;
15 assert(@popCount(x) == 16);
16 }
17 {
18 var x: i16 = -1;
19 assert(@popCount(x) == 16);
20 }
21 comptime {
22 assert(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
23 }
24}
test/cases/ptrcast.zig deleted-52
...@@ -1,52 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "reinterpret bytes as integer with nonzero offset" {
6 testReinterpretBytesAsInteger();
7 comptime testReinterpretBytesAsInteger();
8}
9
10fn testReinterpretBytesAsInteger() void {
11 const bytes = "\x12\x34\x56\x78\xab";
12 const expected = switch (builtin.endian) {
13 builtin.Endian.Little => 0xab785634,
14 builtin.Endian.Big => 0x345678ab,
15 };
16 assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
17}
18
19test "reinterpret bytes of an array into an extern struct" {
20 testReinterpretBytesAsExternStruct();
21 comptime testReinterpretBytesAsExternStruct();
22}
23
24fn testReinterpretBytesAsExternStruct() void {
25 var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 };
26
27 const S = extern struct {
28 a: u8,
29 b: u16,
30 c: u8,
31 };
32
33 var ptr = @ptrCast(*const S, &bytes);
34 var val = ptr.c;
35 assertOrPanic(val == 5);
36}
37
38test "reinterpret struct field at comptime" {
39 const numLittle = comptime Bytes.init(0x12345678);
40 assertOrPanic(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes));
41}
42
43const Bytes = struct {
44 bytes: [4]u8,
45
46 pub fn init(v: u32) Bytes {
47 var res: Bytes = undefined;
48 @ptrCast(*align(1) u32, &res.bytes).* = v;
49
50 return res;
51 }
52};
test/cases/pub_enum/index.zig deleted-13
...@@ -1,13 +0,0 @@
1const other = @import("other.zig");
2const assert = @import("std").debug.assert;
3
4test "pub enum" {
5 pubEnumTest(other.APubEnum.Two);
6}
7fn pubEnumTest(foo: other.APubEnum) void {
8 assert(foo == other.APubEnum.Two);
9}
10
11test "cast with imported symbol" {
12 assert(other.size_t(42) == 42);
13}
test/cases/pub_enum/other.zig deleted-6
...@@ -1,6 +0,0 @@
1pub const APubEnum = enum {
2 One,
3 Two,
4 Three,
5};
6pub const size_t = u64;
test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig deleted-37
...@@ -1,37 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4var ok: bool = false;
5test "reference a variable in an if after an if in the 2nd switch prong" {
6 foo(true, Num.Two, false, "aoeu");
7 assert(!ok);
8 foo(false, Num.One, false, "aoeu");
9 assert(!ok);
10 foo(true, Num.One, false, "aoeu");
11 assert(ok);
12}
13
14const Num = enum {
15 One,
16 Two,
17};
18
19fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
20 switch (k) {
21 Num.Two => {},
22 Num.One => {
23 if (c) {
24 const output_path = b;
25
26 if (c2) {}
27
28 a(output_path);
29 }
30 },
31 }
32}
33
34fn a(x: []const u8) void {
35 assert(mem.eql(u8, x, "aoeu"));
36 ok = true;
37}
test/cases/reflection.zig deleted-95
...@@ -1,95 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const reflection = @This();
4
5test "reflection: array, pointer, optional, error union type child" {
6 comptime {
7 assert(([10]u8).Child == u8);
8 assert((*u8).Child == u8);
9 assert((anyerror!u8).Payload == u8);
10 assert((?u8).Child == u8);
11 }
12}
13
14test "reflection: function return type, var args, and param types" {
15 comptime {
16 assert(@typeOf(dummy).ReturnType == i32);
17 assert(!@typeOf(dummy).is_var_args);
18 assert(@typeOf(dummy_varargs).is_var_args);
19 assert(@typeOf(dummy).arg_count == 3);
20 assert(@ArgType(@typeOf(dummy), 0) == bool);
21 assert(@ArgType(@typeOf(dummy), 1) == i32);
22 assert(@ArgType(@typeOf(dummy), 2) == f32);
23 }
24}
25
26fn dummy(a: bool, b: i32, c: f32) i32 {
27 return 1234;
28}
29fn dummy_varargs(args: ...) void {}
30
31test "reflection: struct member types and names" {
32 comptime {
33 assert(@memberCount(Foo) == 3);
34
35 assert(@memberType(Foo, 0) == i32);
36 assert(@memberType(Foo, 1) == bool);
37 assert(@memberType(Foo, 2) == void);
38
39 assert(mem.eql(u8, @memberName(Foo, 0), "one"));
40 assert(mem.eql(u8, @memberName(Foo, 1), "two"));
41 assert(mem.eql(u8, @memberName(Foo, 2), "three"));
42 }
43}
44
45test "reflection: enum member types and names" {
46 comptime {
47 assert(@memberCount(Bar) == 4);
48
49 assert(@memberType(Bar, 0) == void);
50 assert(@memberType(Bar, 1) == i32);
51 assert(@memberType(Bar, 2) == bool);
52 assert(@memberType(Bar, 3) == f64);
53
54 assert(mem.eql(u8, @memberName(Bar, 0), "One"));
55 assert(mem.eql(u8, @memberName(Bar, 1), "Two"));
56 assert(mem.eql(u8, @memberName(Bar, 2), "Three"));
57 assert(mem.eql(u8, @memberName(Bar, 3), "Four"));
58 }
59}
60
61test "reflection: @field" {
62 var f = Foo{
63 .one = 42,
64 .two = true,
65 .three = void{},
66 };
67
68 assert(f.one == f.one);
69 assert(@field(f, "o" ++ "ne") == f.one);
70 assert(@field(f, "t" ++ "wo") == f.two);
71 assert(@field(f, "th" ++ "ree") == f.three);
72 assert(@field(Foo, "const" ++ "ant") == Foo.constant);
73 assert(@field(Bar, "O" ++ "ne") == Bar.One);
74 assert(@field(Bar, "T" ++ "wo") == Bar.Two);
75 assert(@field(Bar, "Th" ++ "ree") == Bar.Three);
76 assert(@field(Bar, "F" ++ "our") == Bar.Four);
77 assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
78 @field(f, "o" ++ "ne") = 4;
79 assert(f.one == 4);
80}
81
82const Foo = struct {
83 const constant = 52;
84
85 one: i32,
86 two: bool,
87 three: void,
88};
89
90const Bar = union(enum) {
91 One: void,
92 Two: i32,
93 Three: bool,
94 Four: f64,
95};
test/cases/sizeof_and_typeof.zig deleted-69
...@@ -1,69 +0,0 @@
1const builtin = @import("builtin");
2const assert = @import("std").debug.assert;
3
4test "@sizeOf and @typeOf" {
5 const y: @typeOf(x) = 120;
6 assert(@sizeOf(@typeOf(y)) == 2);
7}
8const x: u16 = 13;
9const z: @typeOf(x) = 19;
10
11const A = struct {
12 a: u8,
13 b: u32,
14 c: u8,
15 d: u3,
16 e: u5,
17 f: u16,
18 g: u16,
19};
20
21const P = packed struct {
22 a: u8,
23 b: u32,
24 c: u8,
25 d: u3,
26 e: u5,
27 f: u16,
28 g: u16,
29};
30
31test "@byteOffsetOf" {
32 // Packed structs have fixed memory layout
33 assert(@byteOffsetOf(P, "a") == 0);
34 assert(@byteOffsetOf(P, "b") == 1);
35 assert(@byteOffsetOf(P, "c") == 5);
36 assert(@byteOffsetOf(P, "d") == 6);
37 assert(@byteOffsetOf(P, "e") == 6);
38 assert(@byteOffsetOf(P, "f") == 7);
39 assert(@byteOffsetOf(P, "g") == 9);
40
41 // Normal struct fields can be moved/padded
42 var a: A = undefined;
43 assert(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
44 assert(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
45 assert(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
46 assert(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
47 assert(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
48 assert(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
49 assert(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
50}
51
52test "@bitOffsetOf" {
53 // Packed structs have fixed memory layout
54 assert(@bitOffsetOf(P, "a") == 0);
55 assert(@bitOffsetOf(P, "b") == 8);
56 assert(@bitOffsetOf(P, "c") == 40);
57 assert(@bitOffsetOf(P, "d") == 48);
58 assert(@bitOffsetOf(P, "e") == 51);
59 assert(@bitOffsetOf(P, "f") == 56);
60 assert(@bitOffsetOf(P, "g") == 72);
61
62 assert(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
63 assert(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
64 assert(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
65 assert(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
66 assert(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
67 assert(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
68 assert(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
69}
test/cases/slice.zig deleted-40
...@@ -1,40 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4const x = @intToPtr([*]i32, 0x1000)[0..0x500];
5const y = x[0x100..];
6test "compile time slice of pointer to hard coded address" {
7 assert(@ptrToInt(x.ptr) == 0x1000);
8 assert(x.len == 0x500);
9
10 assert(@ptrToInt(y.ptr) == 0x1100);
11 assert(y.len == 0x400);
12}
13
14test "slice child property" {
15 var array: [5]i32 = undefined;
16 var slice = array[0..];
17 assert(@typeOf(slice).Child == i32);
18}
19
20test "runtime safety lets us slice from len..len" {
21 var an_array = []u8{
22 1,
23 2,
24 3,
25 };
26 assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
27}
28
29fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
30 return a_slice[start..end];
31}
32
33test "implicitly cast array of size 0 to slice" {
34 var msg = []u8{};
35 assertLenIsZero(msg);
36}
37
38fn assertLenIsZero(msg: []const u8) void {
39 assert(msg.len == 0);
40}
test/cases/struct.zig deleted-470
...@@ -1,470 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const StructWithNoFields = struct {
7 fn add(a: i32, b: i32) i32 {
8 return a + b;
9 }
10};
11const empty_global_instance = StructWithNoFields{};
12
13test "call struct static method" {
14 const result = StructWithNoFields.add(3, 4);
15 assert(result == 7);
16}
17
18test "return empty struct instance" {
19 _ = returnEmptyStructInstance();
20}
21fn returnEmptyStructInstance() StructWithNoFields {
22 return empty_global_instance;
23}
24
25const should_be_11 = StructWithNoFields.add(5, 6);
26
27test "invake static method in global scope" {
28 assert(should_be_11 == 11);
29}
30
31test "void struct fields" {
32 const foo = VoidStructFieldsFoo{
33 .a = void{},
34 .b = 1,
35 .c = void{},
36 };
37 assert(foo.b == 1);
38 assert(@sizeOf(VoidStructFieldsFoo) == 4);
39}
40const VoidStructFieldsFoo = struct {
41 a: void,
42 b: i32,
43 c: void,
44};
45
46test "structs" {
47 var foo: StructFoo = undefined;
48 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
49 foo.a += 1;
50 foo.b = foo.a == 1;
51 testFoo(foo);
52 testMutation(&foo);
53 assert(foo.c == 100);
54}
55const StructFoo = struct {
56 a: i32,
57 b: bool,
58 c: f32,
59};
60fn testFoo(foo: StructFoo) void {
61 assert(foo.b);
62}
63fn testMutation(foo: *StructFoo) void {
64 foo.c = 100;
65}
66
67const Node = struct {
68 val: Val,
69 next: *Node,
70};
71
72const Val = struct {
73 x: i32,
74};
75
76test "struct point to self" {
77 var root: Node = undefined;
78 root.val.x = 1;
79
80 var node: Node = undefined;
81 node.next = &root;
82 node.val.x = 2;
83
84 root.next = &node;
85
86 assert(node.next.next.next.val.x == 1);
87}
88
89test "struct byval assign" {
90 var foo1: StructFoo = undefined;
91 var foo2: StructFoo = undefined;
92
93 foo1.a = 1234;
94 foo2.a = 0;
95 assert(foo2.a == 0);
96 foo2 = foo1;
97 assert(foo2.a == 1234);
98}
99
100fn structInitializer() void {
101 const val = Val{ .x = 42 };
102 assert(val.x == 42);
103}
104
105test "fn call of struct field" {
106 assert(callStructField(Foo{ .ptr = aFunc }) == 13);
107}
108
109const Foo = struct {
110 ptr: fn () i32,
111};
112
113fn aFunc() i32 {
114 return 13;
115}
116
117fn callStructField(foo: Foo) i32 {
118 return foo.ptr();
119}
120
121test "store member function in variable" {
122 const instance = MemberFnTestFoo{ .x = 1234 };
123 const memberFn = MemberFnTestFoo.member;
124 const result = memberFn(instance);
125 assert(result == 1234);
126}
127const MemberFnTestFoo = struct {
128 x: i32,
129 fn member(foo: MemberFnTestFoo) i32 {
130 return foo.x;
131 }
132};
133
134test "call member function directly" {
135 const instance = MemberFnTestFoo{ .x = 1234 };
136 const result = MemberFnTestFoo.member(instance);
137 assert(result == 1234);
138}
139
140test "member functions" {
141 const r = MemberFnRand{ .seed = 1234 };
142 assert(r.getSeed() == 1234);
143}
144const MemberFnRand = struct {
145 seed: u32,
146 pub fn getSeed(r: *const MemberFnRand) u32 {
147 return r.seed;
148 }
149};
150
151test "return struct byval from function" {
152 const bar = makeBar(1234, 5678);
153 assert(bar.y == 5678);
154}
155const Bar = struct {
156 x: i32,
157 y: i32,
158};
159fn makeBar(x: i32, y: i32) Bar {
160 return Bar{
161 .x = x,
162 .y = y,
163 };
164}
165
166test "empty struct method call" {
167 const es = EmptyStruct{};
168 assert(es.method() == 1234);
169}
170const EmptyStruct = struct {
171 fn method(es: *const EmptyStruct) i32 {
172 return 1234;
173 }
174};
175
176test "return empty struct from fn" {
177 _ = testReturnEmptyStructFromFn();
178}
179const EmptyStruct2 = struct {};
180fn testReturnEmptyStructFromFn() EmptyStruct2 {
181 return EmptyStruct2{};
182}
183
184test "pass slice of empty struct to fn" {
185 assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
186}
187fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
188 return slice.len;
189}
190
191const APackedStruct = packed struct {
192 x: u8,
193 y: u8,
194};
195
196test "packed struct" {
197 var foo = APackedStruct{
198 .x = 1,
199 .y = 2,
200 };
201 foo.y += 1;
202 const four = foo.x + foo.y;
203 assert(four == 4);
204}
205
206const BitField1 = packed struct {
207 a: u3,
208 b: u3,
209 c: u2,
210};
211
212const bit_field_1 = BitField1{
213 .a = 1,
214 .b = 2,
215 .c = 3,
216};
217
218test "bit field access" {
219 var data = bit_field_1;
220 assert(getA(&data) == 1);
221 assert(getB(&data) == 2);
222 assert(getC(&data) == 3);
223 comptime assert(@sizeOf(BitField1) == 1);
224
225 data.b += 1;
226 assert(data.b == 3);
227
228 data.a += 1;
229 assert(data.a == 2);
230 assert(data.b == 3);
231}
232
233fn getA(data: *const BitField1) u3 {
234 return data.a;
235}
236
237fn getB(data: *const BitField1) u3 {
238 return data.b;
239}
240
241fn getC(data: *const BitField1) u2 {
242 return data.c;
243}
244
245const Foo24Bits = packed struct {
246 field: u24,
247};
248const Foo96Bits = packed struct {
249 a: u24,
250 b: u24,
251 c: u24,
252 d: u24,
253};
254
255test "packed struct 24bits" {
256 comptime {
257 assert(@sizeOf(Foo24Bits) == 3);
258 assert(@sizeOf(Foo96Bits) == 12);
259 }
260
261 var value = Foo96Bits{
262 .a = 0,
263 .b = 0,
264 .c = 0,
265 .d = 0,
266 };
267 value.a += 1;
268 assert(value.a == 1);
269 assert(value.b == 0);
270 assert(value.c == 0);
271 assert(value.d == 0);
272
273 value.b += 1;
274 assert(value.a == 1);
275 assert(value.b == 1);
276 assert(value.c == 0);
277 assert(value.d == 0);
278
279 value.c += 1;
280 assert(value.a == 1);
281 assert(value.b == 1);
282 assert(value.c == 1);
283 assert(value.d == 0);
284
285 value.d += 1;
286 assert(value.a == 1);
287 assert(value.b == 1);
288 assert(value.c == 1);
289 assert(value.d == 1);
290}
291
292const FooArray24Bits = packed struct {
293 a: u16,
294 b: [2]Foo24Bits,
295 c: u16,
296};
297
298test "packed array 24bits" {
299 comptime {
300 assert(@sizeOf([9]Foo24Bits) == 9 * 3);
301 assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
302 }
303
304 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
305 bytes[bytes.len - 1] = 0xaa;
306 const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
307 assert(ptr.a == 0);
308 assert(ptr.b[0].field == 0);
309 assert(ptr.b[1].field == 0);
310 assert(ptr.c == 0);
311
312 ptr.a = maxInt(u16);
313 assert(ptr.a == maxInt(u16));
314 assert(ptr.b[0].field == 0);
315 assert(ptr.b[1].field == 0);
316 assert(ptr.c == 0);
317
318 ptr.b[0].field = maxInt(u24);
319 assert(ptr.a == maxInt(u16));
320 assert(ptr.b[0].field == maxInt(u24));
321 assert(ptr.b[1].field == 0);
322 assert(ptr.c == 0);
323
324 ptr.b[1].field = maxInt(u24);
325 assert(ptr.a == maxInt(u16));
326 assert(ptr.b[0].field == maxInt(u24));
327 assert(ptr.b[1].field == maxInt(u24));
328 assert(ptr.c == 0);
329
330 ptr.c = maxInt(u16);
331 assert(ptr.a == maxInt(u16));
332 assert(ptr.b[0].field == maxInt(u24));
333 assert(ptr.b[1].field == maxInt(u24));
334 assert(ptr.c == maxInt(u16));
335
336 assert(bytes[bytes.len - 1] == 0xaa);
337}
338
339const FooStructAligned = packed struct {
340 a: u8,
341 b: u8,
342};
343
344const FooArrayOfAligned = packed struct {
345 a: [2]FooStructAligned,
346};
347
348test "aligned array of packed struct" {
349 comptime {
350 assert(@sizeOf(FooStructAligned) == 2);
351 assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
352 }
353
354 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
355 const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
356
357 assert(ptr.a[0].a == 0xbb);
358 assert(ptr.a[0].b == 0xbb);
359 assert(ptr.a[1].a == 0xbb);
360 assert(ptr.a[1].b == 0xbb);
361}
362
363test "runtime struct initialization of bitfield" {
364 const s1 = Nibbles{
365 .x = x1,
366 .y = x1,
367 };
368 const s2 = Nibbles{
369 .x = @intCast(u4, x2),
370 .y = @intCast(u4, x2),
371 };
372
373 assert(s1.x == x1);
374 assert(s1.y == x1);
375 assert(s2.x == @intCast(u4, x2));
376 assert(s2.y == @intCast(u4, x2));
377}
378
379var x1 = u4(1);
380var x2 = u8(2);
381
382const Nibbles = packed struct {
383 x: u4,
384 y: u4,
385};
386
387const Bitfields = packed struct {
388 f1: u16,
389 f2: u16,
390 f3: u8,
391 f4: u8,
392 f5: u4,
393 f6: u4,
394 f7: u8,
395};
396
397test "native bit field understands endianness" {
398 var all: u64 = 0x7765443322221111;
399 var bytes: [8]u8 = undefined;
400 @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
401 var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
402
403 assert(bitfields.f1 == 0x1111);
404 assert(bitfields.f2 == 0x2222);
405 assert(bitfields.f3 == 0x33);
406 assert(bitfields.f4 == 0x44);
407 assert(bitfields.f5 == 0x5);
408 assert(bitfields.f6 == 0x6);
409 assert(bitfields.f7 == 0x77);
410}
411
412test "align 1 field before self referential align 8 field as slice return type" {
413 const result = alloc(Expr);
414 assert(result.len == 0);
415}
416
417const Expr = union(enum) {
418 Literal: u8,
419 Question: *Expr,
420};
421
422fn alloc(comptime T: type) []T {
423 return []T{};
424}
425
426test "call method with mutable reference to struct with no fields" {
427 const S = struct {
428 fn doC(s: *const @This()) bool {
429 return true;
430 }
431 fn do(s: *@This()) bool {
432 return true;
433 }
434 };
435
436 var s = S{};
437 assert(S.doC(&s));
438 assert(s.doC());
439 assert(S.do(&s));
440 assert(s.do());
441}
442
443test "implicit cast packed struct field to const ptr" {
444 const LevelUpMove = packed struct {
445 move_id: u9,
446 level: u7,
447
448 fn toInt(value: u7) u7 {
449 return value;
450 }
451 };
452
453 var lup: LevelUpMove = undefined;
454 lup.level = 12;
455 const res = LevelUpMove.toInt(lup.level);
456 assert(res == 12);
457}
458
459test "pointer to packed struct member in a stack variable" {
460 const S = packed struct {
461 a: u2,
462 b: u2,
463 };
464
465 var s = S{ .a = 2, .b = 0 };
466 var b_ptr = &s.b;
467 assert(s.b == 0);
468 b_ptr.* = 2;
469 assert(s.b == 2);
470}
test/cases/struct_contains_null_ptr_itself.zig deleted-21
...@@ -1,21 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?*NodeLineComment = null;
6 assert(x == null);
7}
8
9pub const Node = struct {
10 id: Id,
11 comment: ?*NodeLineComment,
12
13 pub const Id = enum {
14 Root,
15 LineComment,
16 };
17};
18
19pub const NodeLineComment = struct {
20 base: Node,
21};
test/cases/struct_contains_slice_of_itself.zig deleted-85
...@@ -1,85 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const Node = struct {
4 payload: i32,
5 children: []Node,
6};
7
8const NodeAligned = struct {
9 payload: i32,
10 children: []align(@alignOf(NodeAligned)) NodeAligned,
11};
12
13test "struct contains slice of itself" {
14 var other_nodes = []Node{
15 Node{
16 .payload = 31,
17 .children = []Node{},
18 },
19 Node{
20 .payload = 32,
21 .children = []Node{},
22 },
23 };
24 var nodes = []Node{
25 Node{
26 .payload = 1,
27 .children = []Node{},
28 },
29 Node{
30 .payload = 2,
31 .children = []Node{},
32 },
33 Node{
34 .payload = 3,
35 .children = other_nodes[0..],
36 },
37 };
38 const root = Node{
39 .payload = 1234,
40 .children = nodes[0..],
41 };
42 assert(root.payload == 1234);
43 assert(root.children[0].payload == 1);
44 assert(root.children[1].payload == 2);
45 assert(root.children[2].payload == 3);
46 assert(root.children[2].children[0].payload == 31);
47 assert(root.children[2].children[1].payload == 32);
48}
49
50test "struct contains aligned slice of itself" {
51 var other_nodes = []NodeAligned{
52 NodeAligned{
53 .payload = 31,
54 .children = []NodeAligned{},
55 },
56 NodeAligned{
57 .payload = 32,
58 .children = []NodeAligned{},
59 },
60 };
61 var nodes = []NodeAligned{
62 NodeAligned{
63 .payload = 1,
64 .children = []NodeAligned{},
65 },
66 NodeAligned{
67 .payload = 2,
68 .children = []NodeAligned{},
69 },
70 NodeAligned{
71 .payload = 3,
72 .children = other_nodes[0..],
73 },
74 };
75 const root = NodeAligned{
76 .payload = 1234,
77 .children = nodes[0..],
78 };
79 assert(root.payload == 1234);
80 assert(root.children[0].payload == 1);
81 assert(root.children[1].payload == 2);
82 assert(root.children[2].payload == 3);
83 assert(root.children[2].children[0].payload == 31);
84 assert(root.children[2].children[1].payload == 32);
85}
test/cases/switch.zig deleted-271
...@@ -1,271 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "switch with numbers" {
4 testSwitchWithNumbers(13);
5}
6
7fn testSwitchWithNumbers(x: u32) void {
8 const result = switch (x) {
9 1, 2, 3, 4...8 => false,
10 13 => true,
11 else => false,
12 };
13 assert(result);
14}
15
16test "switch with all ranges" {
17 assert(testSwitchWithAllRanges(50, 3) == 1);
18 assert(testSwitchWithAllRanges(101, 0) == 2);
19 assert(testSwitchWithAllRanges(300, 5) == 3);
20 assert(testSwitchWithAllRanges(301, 6) == 6);
21}
22
23fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
24 return switch (x) {
25 0...100 => 1,
26 101...200 => 2,
27 201...300 => 3,
28 else => y,
29 };
30}
31
32test "implicit comptime switch" {
33 const x = 3 + 4;
34 const result = switch (x) {
35 3 => 10,
36 4 => 11,
37 5, 6 => 12,
38 7, 8 => 13,
39 else => 14,
40 };
41
42 comptime {
43 assert(result + 1 == 14);
44 }
45}
46
47test "switch on enum" {
48 const fruit = Fruit.Orange;
49 nonConstSwitchOnEnum(fruit);
50}
51const Fruit = enum {
52 Apple,
53 Orange,
54 Banana,
55};
56fn nonConstSwitchOnEnum(fruit: Fruit) void {
57 switch (fruit) {
58 Fruit.Apple => unreachable,
59 Fruit.Orange => {},
60 Fruit.Banana => unreachable,
61 }
62}
63
64test "switch statement" {
65 nonConstSwitch(SwitchStatmentFoo.C);
66}
67fn nonConstSwitch(foo: SwitchStatmentFoo) void {
68 const val = switch (foo) {
69 SwitchStatmentFoo.A => i32(1),
70 SwitchStatmentFoo.B => 2,
71 SwitchStatmentFoo.C => 3,
72 SwitchStatmentFoo.D => 4,
73 };
74 assert(val == 3);
75}
76const SwitchStatmentFoo = enum {
77 A,
78 B,
79 C,
80 D,
81};
82
83test "switch prong with variable" {
84 switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
85 switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
86 switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
87}
88const SwitchProngWithVarEnum = union(enum) {
89 One: i32,
90 Two: f32,
91 Meh: void,
92};
93fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void {
94 switch (a) {
95 SwitchProngWithVarEnum.One => |x| {
96 assert(x == 13);
97 },
98 SwitchProngWithVarEnum.Two => |x| {
99 assert(x == 13.0);
100 },
101 SwitchProngWithVarEnum.Meh => |x| {
102 const v: void = x;
103 },
104 }
105}
106
107test "switch on enum using pointer capture" {
108 testSwitchEnumPtrCapture();
109 comptime testSwitchEnumPtrCapture();
110}
111
112fn testSwitchEnumPtrCapture() void {
113 var value = SwitchProngWithVarEnum{ .One = 1234 };
114 switch (value) {
115 SwitchProngWithVarEnum.One => |*x| x.* += 1,
116 else => unreachable,
117 }
118 switch (value) {
119 SwitchProngWithVarEnum.One => |x| assert(x == 1235),
120 else => unreachable,
121 }
122}
123
124test "switch with multiple expressions" {
125 const x = switch (returnsFive()) {
126 1, 2, 3 => 1,
127 4, 5, 6 => 2,
128 else => i32(3),
129 };
130 assert(x == 2);
131}
132fn returnsFive() i32 {
133 return 5;
134}
135
136const Number = union(enum) {
137 One: u64,
138 Two: u8,
139 Three: f32,
140};
141
142const number = Number{ .Three = 1.23 };
143
144fn returnsFalse() bool {
145 switch (number) {
146 Number.One => |x| return x > 1234,
147 Number.Two => |x| return x == 'a',
148 Number.Three => |x| return x > 12.34,
149 }
150}
151test "switch on const enum with var" {
152 assert(!returnsFalse());
153}
154
155test "switch on type" {
156 assert(trueIfBoolFalseOtherwise(bool));
157 assert(!trueIfBoolFalseOtherwise(i32));
158}
159
160fn trueIfBoolFalseOtherwise(comptime T: type) bool {
161 return switch (T) {
162 bool => true,
163 else => false,
164 };
165}
166
167test "switch handles all cases of number" {
168 testSwitchHandleAllCases();
169 comptime testSwitchHandleAllCases();
170}
171
172fn testSwitchHandleAllCases() void {
173 assert(testSwitchHandleAllCasesExhaustive(0) == 3);
174 assert(testSwitchHandleAllCasesExhaustive(1) == 2);
175 assert(testSwitchHandleAllCasesExhaustive(2) == 1);
176 assert(testSwitchHandleAllCasesExhaustive(3) == 0);
177
178 assert(testSwitchHandleAllCasesRange(100) == 0);
179 assert(testSwitchHandleAllCasesRange(200) == 1);
180 assert(testSwitchHandleAllCasesRange(201) == 2);
181 assert(testSwitchHandleAllCasesRange(202) == 4);
182 assert(testSwitchHandleAllCasesRange(230) == 3);
183}
184
185fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
186 return switch (x) {
187 0 => u2(3),
188 1 => 2,
189 2 => 1,
190 3 => 0,
191 };
192}
193
194fn testSwitchHandleAllCasesRange(x: u8) u8 {
195 return switch (x) {
196 0...100 => u8(0),
197 101...200 => 1,
198 201, 203 => 2,
199 202 => 4,
200 204...255 => 3,
201 };
202}
203
204test "switch all prongs unreachable" {
205 testAllProngsUnreachable();
206 comptime testAllProngsUnreachable();
207}
208
209fn testAllProngsUnreachable() void {
210 assert(switchWithUnreachable(1) == 2);
211 assert(switchWithUnreachable(2) == 10);
212}
213
214fn switchWithUnreachable(x: i32) i32 {
215 while (true) {
216 switch (x) {
217 1 => return 2,
218 2 => break,
219 else => continue,
220 }
221 }
222 return 10;
223}
224
225fn return_a_number() anyerror!i32 {
226 return 1;
227}
228
229test "capture value of switch with all unreachable prongs" {
230 const x = return_a_number() catch |err| switch (err) {
231 else => unreachable,
232 };
233 assert(x == 1);
234}
235
236test "switching on booleans" {
237 testSwitchOnBools();
238 comptime testSwitchOnBools();
239}
240
241fn testSwitchOnBools() void {
242 assert(testSwitchOnBoolsTrueAndFalse(true) == false);
243 assert(testSwitchOnBoolsTrueAndFalse(false) == true);
244
245 assert(testSwitchOnBoolsTrueWithElse(true) == false);
246 assert(testSwitchOnBoolsTrueWithElse(false) == true);
247
248 assert(testSwitchOnBoolsFalseWithElse(true) == false);
249 assert(testSwitchOnBoolsFalseWithElse(false) == true);
250}
251
252fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
253 return switch (x) {
254 true => false,
255 false => true,
256 };
257}
258
259fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
260 return switch (x) {
261 true => false,
262 else => true,
263 };
264}
265
266fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
267 return switch (x) {
268 false => true,
269 else => false,
270 };
271}
test/cases/switch_prong_err_enum.zig deleted-30
...@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3var read_count: u64 = 0;
4
5fn readOnce() anyerror!u64 {
6 read_count += 1;
7 return read_count;
8}
9
10const FormValue = union(enum) {
11 Address: u64,
12 Other: bool,
13};
14
15fn doThing(form_id: u64) anyerror!FormValue {
16 return switch (form_id) {
17 17 => FormValue{ .Address = try readOnce() },
18 else => error.InvalidDebugInfo,
19 };
20}
21
22test "switch prong returns error enum" {
23 switch (doThing(17) catch unreachable) {
24 FormValue.Address => |payload| {
25 assert(payload == 1);
26 },
27 else => unreachable,
28 }
29 assert(read_count == 1);
30}
test/cases/switch_prong_implicit_cast.zig deleted-22
...@@ -1,22 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const FormValue = union(enum) {
4 One: void,
5 Two: bool,
6};
7
8fn foo(id: u64) !FormValue {
9 return switch (id) {
10 2 => FormValue{ .Two = true },
11 1 => FormValue{ .One = {} },
12 else => return error.Whatever,
13 };
14}
15
16test "switch prong implicit cast" {
17 const result = switch (foo(2) catch unreachable) {
18 FormValue.One => false,
19 FormValue.Two => |x| x,
20 };
21 assert(result);
22}
test/cases/syntax.zig deleted-59
...@@ -1,59 +0,0 @@
1// Test trailing comma syntax
2// zig fmt: off
3
4const struct_trailing_comma = struct { x: i32, y: i32, };
5const struct_no_comma = struct { x: i32, y: i32 };
6const struct_fn_no_comma = struct { fn m() void {} y: i32 };
7
8const enum_no_comma = enum { A, B };
9
10fn container_init() void {
11 const S = struct { x: i32, y: i32 };
12 _ = S { .x = 1, .y = 2 };
13 _ = S { .x = 1, .y = 2, };
14}
15
16fn type_expr_return1() if (true) A {}
17fn type_expr_return2() for (true) |_| A {}
18fn type_expr_return3() while (true) A {}
19fn type_expr_return4() comptime A {}
20
21fn switch_cases(x: i32) void {
22 switch (x) {
23 1,2,3 => {},
24 4,5, => {},
25 6...8, => {},
26 else => {},
27 }
28}
29
30fn switch_prongs(x: i32) void {
31 switch (x) {
32 0 => {},
33 else => {},
34 }
35 switch (x) {
36 0 => {},
37 else => {}
38 }
39}
40
41const fn_no_comma = fn(i32, i32)void;
42const fn_trailing_comma = fn(i32, i32,)void;
43
44fn fn_calls() void {
45 fn add(x: i32, y: i32,) i32 { x + y };
46 _ = add(1, 2);
47 _ = add(1, 2,);
48}
49
50fn asm_lists() void {
51 if (false) { // Build AST but don't analyze
52 asm ("not real assembly"
53 :[a] "x" (x),);
54 asm ("not real assembly"
55 :[a] "x" (->i32),:[a] "x" (1),);
56 asm ("still not real assembly"
57 :::"a","b",);
58 }
59}
test/cases/this.zig deleted-34
...@@ -1,34 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const module = @This();
4
5fn Point(comptime T: type) type {
6 return struct {
7 const Self = @This();
8 x: T,
9 y: T,
10
11 fn addOne(self: *Self) void {
12 self.x += 1;
13 self.y += 1;
14 }
15 };
16}
17
18fn add(x: i32, y: i32) i32 {
19 return x + y;
20}
21
22test "this refer to module call private fn" {
23 assert(module.add(1, 2) == 3);
24}
25
26test "this refer to container" {
27 var pt = Point(i32){
28 .x = 12,
29 .y = 34,
30 };
31 pt.addOne();
32 assert(pt.x == 13);
33 assert(pt.y == 35);
34}
test/cases/truncate.zig deleted-8
...@@ -1,8 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "truncate u0 to larger integer allowed and has comptime known result" {
5 var x: u0 = 0;
6 const y = @truncate(u8, x);
7 comptime assert(y == 0);
8}
test/cases/try.zig deleted-43
...@@ -1,43 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "try on error union" {
4 tryOnErrorUnionImpl();
5 comptime tryOnErrorUnionImpl();
6}
7
8fn tryOnErrorUnionImpl() void {
9 const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
10 error.ItBroke, error.NoMem => 1,
11 error.CrappedOut => i32(2),
12 else => unreachable,
13 };
14 assert(x == 11);
15}
16
17fn returnsTen() anyerror!i32 {
18 return 10;
19}
20
21test "try without vars" {
22 const result1 = if (failIfTrue(true)) 1 else |_| i32(2);
23 assert(result1 == 2);
24
25 const result2 = if (failIfTrue(false)) 1 else |_| i32(2);
26 assert(result2 == 1);
27}
28
29fn failIfTrue(ok: bool) anyerror!void {
30 if (ok) {
31 return error.ItBroke;
32 } else {
33 return;
34 }
35}
36
37test "try then not executed with assignment" {
38 if (failIfTrue(true)) {
39 unreachable;
40 } else |err| {
41 assert(err == error.ItBroke);
42 }
43}
test/cases/type_info.zig deleted-264
...@@ -1,264 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const TypeInfo = @import("builtin").TypeInfo;
4const TypeId = @import("builtin").TypeId;
5
6test "type info: tag type, void info" {
7 testBasic();
8 comptime testBasic();
9}
10
11fn testBasic() void {
12 assert(@TagType(TypeInfo) == TypeId);
13 const void_info = @typeInfo(void);
14 assert(TypeId(void_info) == TypeId.Void);
15 assert(void_info.Void == {});
16}
17
18test "type info: integer, floating point type info" {
19 testIntFloat();
20 comptime testIntFloat();
21}
22
23fn testIntFloat() void {
24 const u8_info = @typeInfo(u8);
25 assert(TypeId(u8_info) == TypeId.Int);
26 assert(!u8_info.Int.is_signed);
27 assert(u8_info.Int.bits == 8);
28
29 const f64_info = @typeInfo(f64);
30 assert(TypeId(f64_info) == TypeId.Float);
31 assert(f64_info.Float.bits == 64);
32}
33
34test "type info: pointer type info" {
35 testPointer();
36 comptime testPointer();
37}
38
39fn testPointer() void {
40 const u32_ptr_info = @typeInfo(*u32);
41 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
42 assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
43 assert(u32_ptr_info.Pointer.is_const == false);
44 assert(u32_ptr_info.Pointer.is_volatile == false);
45 assert(u32_ptr_info.Pointer.alignment == @alignOf(u32));
46 assert(u32_ptr_info.Pointer.child == u32);
47}
48
49test "type info: unknown length pointer type info" {
50 testUnknownLenPtr();
51 comptime testUnknownLenPtr();
52}
53
54fn testUnknownLenPtr() void {
55 const u32_ptr_info = @typeInfo([*]const volatile f64);
56 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
57 assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
58 assert(u32_ptr_info.Pointer.is_const == true);
59 assert(u32_ptr_info.Pointer.is_volatile == true);
60 assert(u32_ptr_info.Pointer.alignment == @alignOf(f64));
61 assert(u32_ptr_info.Pointer.child == f64);
62}
63
64test "type info: slice type info" {
65 testSlice();
66 comptime testSlice();
67}
68
69fn testSlice() void {
70 const u32_slice_info = @typeInfo([]u32);
71 assert(TypeId(u32_slice_info) == TypeId.Pointer);
72 assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
73 assert(u32_slice_info.Pointer.is_const == false);
74 assert(u32_slice_info.Pointer.is_volatile == false);
75 assert(u32_slice_info.Pointer.alignment == 4);
76 assert(u32_slice_info.Pointer.child == u32);
77}
78
79test "type info: array type info" {
80 testArray();
81 comptime testArray();
82}
83
84fn testArray() void {
85 const arr_info = @typeInfo([42]bool);
86 assert(TypeId(arr_info) == TypeId.Array);
87 assert(arr_info.Array.len == 42);
88 assert(arr_info.Array.child == bool);
89}
90
91test "type info: optional type info" {
92 testOptional();
93 comptime testOptional();
94}
95
96fn testOptional() void {
97 const null_info = @typeInfo(?void);
98 assert(TypeId(null_info) == TypeId.Optional);
99 assert(null_info.Optional.child == void);
100}
101
102test "type info: promise info" {
103 testPromise();
104 comptime testPromise();
105}
106
107fn testPromise() void {
108 const null_promise_info = @typeInfo(promise);
109 assert(TypeId(null_promise_info) == TypeId.Promise);
110 assert(null_promise_info.Promise.child == null);
111
112 const promise_info = @typeInfo(promise->usize);
113 assert(TypeId(promise_info) == TypeId.Promise);
114 assert(promise_info.Promise.child.? == usize);
115}
116
117test "type info: error set, error union info" {
118 testErrorSet();
119 comptime testErrorSet();
120}
121
122fn testErrorSet() void {
123 const TestErrorSet = error{
124 First,
125 Second,
126 Third,
127 };
128
129 const error_set_info = @typeInfo(TestErrorSet);
130 assert(TypeId(error_set_info) == TypeId.ErrorSet);
131 assert(error_set_info.ErrorSet.errors.len == 3);
132 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
133 assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
134
135 const error_union_info = @typeInfo(TestErrorSet!usize);
136 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
137 assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
138 assert(error_union_info.ErrorUnion.payload == usize);
139}
140
141test "type info: enum info" {
142 testEnum();
143 comptime testEnum();
144}
145
146fn testEnum() void {
147 const Os = enum {
148 Windows,
149 Macos,
150 Linux,
151 FreeBSD,
152 };
153
154 const os_info = @typeInfo(Os);
155 assert(TypeId(os_info) == TypeId.Enum);
156 assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
157 assert(os_info.Enum.fields.len == 4);
158 assert(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
159 assert(os_info.Enum.fields[3].value == 3);
160 assert(os_info.Enum.tag_type == u2);
161 assert(os_info.Enum.defs.len == 0);
162}
163
164test "type info: union info" {
165 testUnion();
166 comptime testUnion();
167}
168
169fn testUnion() void {
170 const typeinfo_info = @typeInfo(TypeInfo);
171 assert(TypeId(typeinfo_info) == TypeId.Union);
172 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
173 assert(typeinfo_info.Union.tag_type.? == TypeId);
174 assert(typeinfo_info.Union.fields.len == 24);
175 assert(typeinfo_info.Union.fields[4].enum_field != null);
176 assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
177 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
178 assert(typeinfo_info.Union.defs.len == 20);
179
180 const TestNoTagUnion = union {
181 Foo: void,
182 Bar: u32,
183 };
184
185 const notag_union_info = @typeInfo(TestNoTagUnion);
186 assert(TypeId(notag_union_info) == TypeId.Union);
187 assert(notag_union_info.Union.tag_type == null);
188 assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
189 assert(notag_union_info.Union.fields.len == 2);
190 assert(notag_union_info.Union.fields[0].enum_field == null);
191 assert(notag_union_info.Union.fields[1].field_type == u32);
192
193 const TestExternUnion = extern union {
194 foo: *c_void,
195 };
196
197 const extern_union_info = @typeInfo(TestExternUnion);
198 assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
199 assert(extern_union_info.Union.tag_type == null);
200 assert(extern_union_info.Union.fields[0].enum_field == null);
201 assert(extern_union_info.Union.fields[0].field_type == *c_void);
202}
203
204test "type info: struct info" {
205 testStruct();
206 comptime testStruct();
207}
208
209fn testStruct() void {
210 const struct_info = @typeInfo(TestStruct);
211 assert(TypeId(struct_info) == TypeId.Struct);
212 assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
213 assert(struct_info.Struct.fields.len == 3);
214 assert(struct_info.Struct.fields[1].offset == null);
215 assert(struct_info.Struct.fields[2].field_type == *TestStruct);
216 assert(struct_info.Struct.defs.len == 2);
217 assert(struct_info.Struct.defs[0].is_pub);
218 assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
219 assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
220 assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
221 assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
222}
223
224const TestStruct = packed struct {
225 const Self = @This();
226
227 fieldA: usize,
228 fieldB: void,
229 fieldC: *Self,
230
231 pub fn foo(self: *const Self) void {}
232};
233
234test "type info: function type info" {
235 testFunction();
236 comptime testFunction();
237}
238
239fn testFunction() void {
240 const fn_info = @typeInfo(@typeOf(foo));
241 assert(TypeId(fn_info) == TypeId.Fn);
242 assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
243 assert(fn_info.Fn.is_generic);
244 assert(fn_info.Fn.args.len == 2);
245 assert(fn_info.Fn.is_var_args);
246 assert(fn_info.Fn.return_type == null);
247 assert(fn_info.Fn.async_allocator_type == null);
248
249 const test_instance: TestStruct = undefined;
250 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
251 assert(TypeId(bound_fn_info) == TypeId.BoundFn);
252 assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
253}
254
255fn foo(comptime a: usize, b: bool, args: ...) usize {
256 return 0;
257}
258
259test "typeInfo with comptime parameter in struct fn def" {
260 const S = struct {
261 pub fn func(comptime x: f32) void {}
262 };
263 comptime var info = @typeInfo(S);
264}
test/cases/undefined.zig deleted-68
...@@ -1,68 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4fn initStaticArray() [10]i32 {
5 var array: [10]i32 = undefined;
6 array[0] = 1;
7 array[4] = 2;
8 array[7] = 3;
9 array[9] = 4;
10 return array;
11}
12const static_array = initStaticArray();
13test "init static array to undefined" {
14 assert(static_array[0] == 1);
15 assert(static_array[4] == 2);
16 assert(static_array[7] == 3);
17 assert(static_array[9] == 4);
18
19 comptime {
20 assert(static_array[0] == 1);
21 assert(static_array[4] == 2);
22 assert(static_array[7] == 3);
23 assert(static_array[9] == 4);
24 }
25}
26
27const Foo = struct {
28 x: i32,
29
30 fn setFooXMethod(foo: *Foo) void {
31 foo.x = 3;
32 }
33};
34
35fn setFooX(foo: *Foo) void {
36 foo.x = 2;
37}
38
39test "assign undefined to struct" {
40 comptime {
41 var foo: Foo = undefined;
42 setFooX(&foo);
43 assert(foo.x == 2);
44 }
45 {
46 var foo: Foo = undefined;
47 setFooX(&foo);
48 assert(foo.x == 2);
49 }
50}
51
52test "assign undefined to struct with method" {
53 comptime {
54 var foo: Foo = undefined;
55 foo.setFooXMethod();
56 assert(foo.x == 3);
57 }
58 {
59 var foo: Foo = undefined;
60 foo.setFooXMethod();
61 assert(foo.x == 3);
62 }
63}
64
65test "type name of undefined" {
66 const x = undefined;
67 assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
68}
test/cases/underscore.zig deleted-28
...@@ -1,28 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "ignore lval with underscore" {
5 _ = false;
6}
7
8test "ignore lval with underscore (for loop)" {
9 for ([]void{}) |_, i| {
10 for ([]void{}) |_, j| {
11 break;
12 }
13 break;
14 }
15}
16
17test "ignore lval with underscore (while loop)" {
18 while (optionalReturnError()) |_| {
19 while (optionalReturnError()) |_| {
20 break;
21 } else |_| {}
22 break;
23 } else |_| {}
24}
25
26fn optionalReturnError() !?u32 {
27 return error.optionalReturnError;
28}
test/cases/union.zig deleted-352
...@@ -1,352 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const Value = union(enum) {
4 Int: u64,
5 Array: [9]u8,
6};
7
8const Agg = struct {
9 val1: Value,
10 val2: Value,
11};
12
13const v1 = Value{ .Int = 1234 };
14const v2 = Value{ .Array = []u8{3} ** 9 };
15
16const err = (anyerror!Agg)(Agg{
17 .val1 = v1,
18 .val2 = v2,
19});
20
21const array = []Value{
22 v1,
23 v2,
24 v1,
25 v2,
26};
27
28test "unions embedded in aggregate types" {
29 switch (array[1]) {
30 Value.Array => |arr| assert(arr[4] == 3),
31 else => unreachable,
32 }
33 switch ((err catch unreachable).val1) {
34 Value.Int => |x| assert(x == 1234),
35 else => unreachable,
36 }
37}
38
39const Foo = union {
40 float: f64,
41 int: i32,
42};
43
44test "basic unions" {
45 var foo = Foo{ .int = 1 };
46 assert(foo.int == 1);
47 foo = Foo{ .float = 12.34 };
48 assert(foo.float == 12.34);
49}
50
51test "comptime union field access" {
52 comptime {
53 var foo = Foo{ .int = 0 };
54 assert(foo.int == 0);
55
56 foo = Foo{ .float = 42.42 };
57 assert(foo.float == 42.42);
58 }
59}
60
61test "init union with runtime value" {
62 var foo: Foo = undefined;
63
64 setFloat(&foo, 12.34);
65 assert(foo.float == 12.34);
66
67 setInt(&foo, 42);
68 assert(foo.int == 42);
69}
70
71fn setFloat(foo: *Foo, x: f64) void {
72 foo.* = Foo{ .float = x };
73}
74
75fn setInt(foo: *Foo, x: i32) void {
76 foo.* = Foo{ .int = x };
77}
78
79const FooExtern = extern union {
80 float: f64,
81 int: i32,
82};
83
84test "basic extern unions" {
85 var foo = FooExtern{ .int = 1 };
86 assert(foo.int == 1);
87 foo.float = 12.34;
88 assert(foo.float == 12.34);
89}
90
91const Letter = enum {
92 A,
93 B,
94 C,
95};
96const Payload = union(Letter) {
97 A: i32,
98 B: f64,
99 C: bool,
100};
101
102test "union with specified enum tag" {
103 doTest();
104 comptime doTest();
105}
106
107fn doTest() void {
108 assert(bar(Payload{ .A = 1234 }) == -10);
109}
110
111fn bar(value: Payload) i32 {
112 assert(Letter(value) == Letter.A);
113 return switch (value) {
114 Payload.A => |x| return x - 1244,
115 Payload.B => |x| if (x == 12.34) i32(20) else 21,
116 Payload.C => |x| if (x) i32(30) else 31,
117 };
118}
119
120const MultipleChoice = union(enum(u32)) {
121 A = 20,
122 B = 40,
123 C = 60,
124 D = 1000,
125};
126test "simple union(enum(u32))" {
127 var x = MultipleChoice.C;
128 assert(x == MultipleChoice.C);
129 assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
130}
131
132const MultipleChoice2 = union(enum(u32)) {
133 Unspecified1: i32,
134 A: f32 = 20,
135 Unspecified2: void,
136 B: bool = 40,
137 Unspecified3: i32,
138 C: i8 = 60,
139 Unspecified4: void,
140 D: void = 1000,
141 Unspecified5: i32,
142};
143
144test "union(enum(u32)) with specified and unspecified tag values" {
145 comptime assert(@TagType(@TagType(MultipleChoice2)) == u32);
146 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
147 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
148}
149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
151 assert(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);
152 assert(1123 == switch (x) {
153 MultipleChoice2.A => 1,
154 MultipleChoice2.B => 2,
155 MultipleChoice2.C => |v| i32(1000) + v,
156 MultipleChoice2.D => 4,
157 MultipleChoice2.Unspecified1 => 5,
158 MultipleChoice2.Unspecified2 => 6,
159 MultipleChoice2.Unspecified3 => 7,
160 MultipleChoice2.Unspecified4 => 8,
161 MultipleChoice2.Unspecified5 => 9,
162 });
163}
164
165const ExternPtrOrInt = extern union {
166 ptr: *u8,
167 int: u64,
168};
169test "extern union size" {
170 comptime assert(@sizeOf(ExternPtrOrInt) == 8);
171}
172
173const PackedPtrOrInt = packed union {
174 ptr: *u8,
175 int: u64,
176};
177test "extern union size" {
178 comptime assert(@sizeOf(PackedPtrOrInt) == 8);
179}
180
181const ZeroBits = union {
182 OnlyField: void,
183};
184test "union with only 1 field which is void should be zero bits" {
185 comptime assert(@sizeOf(ZeroBits) == 0);
186}
187
188const TheTag = enum {
189 A,
190 B,
191 C,
192};
193const TheUnion = union(TheTag) {
194 A: i32,
195 B: i32,
196 C: i32,
197};
198test "union field access gives the enum values" {
199 assert(TheUnion.A == TheTag.A);
200 assert(TheUnion.B == TheTag.B);
201 assert(TheUnion.C == TheTag.C);
202}
203
204test "cast union to tag type of union" {
205 testCastUnionToTagType(TheUnion{ .B = 1234 });
206 comptime testCastUnionToTagType(TheUnion{ .B = 1234 });
207}
208
209fn testCastUnionToTagType(x: TheUnion) void {
210 assert(TheTag(x) == TheTag.B);
211}
212
213test "cast tag type of union to union" {
214 var x: Value2 = Letter2.B;
215 assert(Letter2(x) == Letter2.B);
216}
217const Letter2 = enum {
218 A,
219 B,
220 C,
221};
222const Value2 = union(Letter2) {
223 A: i32,
224 B,
225 C,
226};
227
228test "implicit cast union to its tag type" {
229 var x: Value2 = Letter2.B;
230 assert(x == Letter2.B);
231 giveMeLetterB(x);
232}
233fn giveMeLetterB(x: Letter2) void {
234 assert(x == Value2.B);
235}
236
237pub const PackThis = union(enum) {
238 Invalid: bool,
239 StringLiteral: u2,
240};
241
242test "constant packed union" {
243 testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }});
244}
245
246fn testConstPackedUnion(expected_tokens: []const PackThis) void {
247 assert(expected_tokens[0].StringLiteral == 1);
248}
249
250test "switch on union with only 1 field" {
251 var r: PartialInst = undefined;
252 r = PartialInst.Compiled;
253 switch (r) {
254 PartialInst.Compiled => {
255 var z: PartialInstWithPayload = undefined;
256 z = PartialInstWithPayload{ .Compiled = 1234 };
257 switch (z) {
258 PartialInstWithPayload.Compiled => |x| {
259 assert(x == 1234);
260 return;
261 },
262 }
263 },
264 }
265 unreachable;
266}
267
268const PartialInst = union(enum) {
269 Compiled,
270};
271
272const PartialInstWithPayload = union(enum) {
273 Compiled: i32,
274};
275
276test "access a member of tagged union with conflicting enum tag name" {
277 const Bar = union(enum) {
278 A: A,
279 B: B,
280
281 const A = u8;
282 const B = void;
283 };
284
285 comptime assert(Bar.A == u8);
286}
287
288test "tagged union initialization with runtime void" {
289 assert(testTaggedUnionInit({}));
290}
291
292const TaggedUnionWithAVoid = union(enum) {
293 A,
294 B: i32,
295};
296
297fn testTaggedUnionInit(x: var) bool {
298 const y = TaggedUnionWithAVoid{ .A = x };
299 return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A;
300}
301
302pub const UnionEnumNoPayloads = union(enum) {
303 A,
304 B,
305};
306
307test "tagged union with no payloads" {
308 const a = UnionEnumNoPayloads{ .B = {} };
309 switch (a) {
310 @TagType(UnionEnumNoPayloads).A => @panic("wrong"),
311 @TagType(UnionEnumNoPayloads).B => {},
312 }
313}
314
315test "union with only 1 field casted to its enum type" {
316 const Literal = union(enum) {
317 Number: f64,
318 Bool: bool,
319 };
320
321 const Expr = union(enum) {
322 Literal: Literal,
323 };
324
325 var e = Expr{ .Literal = Literal{ .Bool = true } };
326 const Tag = @TagType(Expr);
327 comptime assert(@TagType(Tag) == comptime_int);
328 var t = Tag(e);
329 assert(t == Expr.Literal);
330}
331
332test "union with only 1 field casted to its enum type which has enum value specified" {
333 const Literal = union(enum) {
334 Number: f64,
335 Bool: bool,
336 };
337
338 const Tag = enum {
339 Literal = 33,
340 };
341
342 const Expr = union(Tag) {
343 Literal: Literal,
344 };
345
346 var e = Expr{ .Literal = Literal{ .Bool = true } };
347 comptime assert(@TagType(Tag) == comptime_int);
348 var t = Tag(e);
349 assert(t == Expr.Literal);
350 assert(@enumToInt(t) == 33);
351 comptime assert(@enumToInt(t) == 33);
352}
test/cases/var_args.zig deleted-84
...@@ -1,84 +0,0 @@
1const assert = @import("std").debug.assert;
2
3fn add(args: ...) i32 {
4 var sum = i32(0);
5 {
6 comptime var i: usize = 0;
7 inline while (i < args.len) : (i += 1) {
8 sum += args[i];
9 }
10 }
11 return sum;
12}
13
14test "add arbitrary args" {
15 assert(add(i32(1), i32(2), i32(3), i32(4)) == 10);
16 assert(add(i32(1234)) == 1234);
17 assert(add() == 0);
18}
19
20fn readFirstVarArg(args: ...) void {
21 const value = args[0];
22}
23
24test "send void arg to var args" {
25 readFirstVarArg({});
26}
27
28test "pass args directly" {
29 assert(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
30 assert(addSomeStuff(i32(1234)) == 1234);
31 assert(addSomeStuff() == 0);
32}
33
34fn addSomeStuff(args: ...) i32 {
35 return add(args);
36}
37
38test "runtime parameter before var args" {
39 assert(extraFn(10) == 0);
40 assert(extraFn(10, false) == 1);
41 assert(extraFn(10, false, true) == 2);
42
43 // TODO issue #313
44 //comptime {
45 // assert(extraFn(10) == 0);
46 // assert(extraFn(10, false) == 1);
47 // assert(extraFn(10, false, true) == 2);
48 //}
49}
50
51fn extraFn(extra: u32, args: ...) usize {
52 if (args.len >= 1) {
53 assert(args[0] == false);
54 }
55 if (args.len >= 2) {
56 assert(args[1] == true);
57 }
58 return args.len;
59}
60
61const foos = []fn (...) bool{
62 foo1,
63 foo2,
64};
65
66fn foo1(args: ...) bool {
67 return true;
68}
69fn foo2(args: ...) bool {
70 return false;
71}
72
73test "array of var args functions" {
74 assert(foos[0]());
75 assert(!foos[1]());
76}
77
78test "pass zero length array to var args param" {
79 doNothingWithFirstArg("");
80}
81
82fn doNothingWithFirstArg(args: ...) void {
83 const a = args[0];
84}
test/cases/void.zig deleted-30
...@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const Foo = struct {
4 a: void,
5 b: i32,
6 c: void,
7};
8
9test "compare void with void compile time known" {
10 comptime {
11 const foo = Foo{
12 .a = {},
13 .b = 1,
14 .c = {},
15 };
16 assert(foo.a == {});
17 }
18}
19
20test "iterate over a void slice" {
21 var j: usize = 0;
22 for (times(10)) |_, i| {
23 assert(i == j);
24 j += 1;
25 }
26}
27
28fn times(n: usize) []const void {
29 return ([*]void)(undefined)[0..n];
30}
test/cases/while.zig deleted-227
...@@ -1,227 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "while loop" {
4 var i: i32 = 0;
5 while (i < 4) {
6 i += 1;
7 }
8 assert(i == 4);
9 assert(whileLoop1() == 1);
10}
11fn whileLoop1() i32 {
12 return whileLoop2();
13}
14fn whileLoop2() i32 {
15 while (true) {
16 return 1;
17 }
18}
19test "static eval while" {
20 assert(static_eval_while_number == 1);
21}
22const static_eval_while_number = staticWhileLoop1();
23fn staticWhileLoop1() i32 {
24 return whileLoop2();
25}
26fn staticWhileLoop2() i32 {
27 while (true) {
28 return 1;
29 }
30}
31
32test "continue and break" {
33 runContinueAndBreakTest();
34 assert(continue_and_break_counter == 8);
35}
36var continue_and_break_counter: i32 = 0;
37fn runContinueAndBreakTest() void {
38 var i: i32 = 0;
39 while (true) {
40 continue_and_break_counter += 2;
41 i += 1;
42 if (i < 4) {
43 continue;
44 }
45 break;
46 }
47 assert(i == 4);
48}
49
50test "return with implicit cast from while loop" {
51 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
52}
53fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
54 while (true) {
55 return;
56 }
57}
58
59test "while with continue expression" {
60 var sum: i32 = 0;
61 {
62 var i: i32 = 0;
63 while (i < 10) : (i += 1) {
64 if (i == 5) continue;
65 sum += i;
66 }
67 }
68 assert(sum == 40);
69}
70
71test "while with else" {
72 var sum: i32 = 0;
73 var i: i32 = 0;
74 var got_else: i32 = 0;
75 while (i < 10) : (i += 1) {
76 sum += 1;
77 } else {
78 got_else += 1;
79 }
80 assert(sum == 10);
81 assert(got_else == 1);
82}
83
84test "while with optional as condition" {
85 numbers_left = 10;
86 var sum: i32 = 0;
87 while (getNumberOrNull()) |value| {
88 sum += value;
89 }
90 assert(sum == 45);
91}
92
93test "while with optional as condition with else" {
94 numbers_left = 10;
95 var sum: i32 = 0;
96 var got_else: i32 = 0;
97 while (getNumberOrNull()) |value| {
98 sum += value;
99 assert(got_else == 0);
100 } else {
101 got_else += 1;
102 }
103 assert(sum == 45);
104 assert(got_else == 1);
105}
106
107test "while with error union condition" {
108 numbers_left = 10;
109 var sum: i32 = 0;
110 var got_else: i32 = 0;
111 while (getNumberOrErr()) |value| {
112 sum += value;
113 } else |err| {
114 assert(err == error.OutOfNumbers);
115 got_else += 1;
116 }
117 assert(sum == 45);
118 assert(got_else == 1);
119}
120
121var numbers_left: i32 = undefined;
122fn getNumberOrErr() anyerror!i32 {
123 return if (numbers_left == 0) error.OutOfNumbers else x: {
124 numbers_left -= 1;
125 break :x numbers_left;
126 };
127}
128fn getNumberOrNull() ?i32 {
129 return if (numbers_left == 0) null else x: {
130 numbers_left -= 1;
131 break :x numbers_left;
132 };
133}
134
135test "while on optional with else result follow else prong" {
136 const result = while (returnNull()) |value| {
137 break value;
138 } else
139 i32(2);
140 assert(result == 2);
141}
142
143test "while on optional with else result follow break prong" {
144 const result = while (returnOptional(10)) |value| {
145 break value;
146 } else
147 i32(2);
148 assert(result == 10);
149}
150
151test "while on error union with else result follow else prong" {
152 const result = while (returnError()) |value| {
153 break value;
154 } else |err|
155 i32(2);
156 assert(result == 2);
157}
158
159test "while on error union with else result follow break prong" {
160 const result = while (returnSuccess(10)) |value| {
161 break value;
162 } else |err|
163 i32(2);
164 assert(result == 10);
165}
166
167test "while on bool with else result follow else prong" {
168 const result = while (returnFalse()) {
169 break i32(10);
170 } else
171 i32(2);
172 assert(result == 2);
173}
174
175test "while on bool with else result follow break prong" {
176 const result = while (returnTrue()) {
177 break i32(10);
178 } else
179 i32(2);
180 assert(result == 10);
181}
182
183test "break from outer while loop" {
184 testBreakOuter();
185 comptime testBreakOuter();
186}
187
188fn testBreakOuter() void {
189 outer: while (true) {
190 while (true) {
191 break :outer;
192 }
193 }
194}
195
196test "continue outer while loop" {
197 testContinueOuter();
198 comptime testContinueOuter();
199}
200
201fn testContinueOuter() void {
202 var i: usize = 0;
203 outer: while (i < 10) : (i += 1) {
204 while (true) {
205 continue :outer;
206 }
207 }
208}
209
210fn returnNull() ?i32 {
211 return null;
212}
213fn returnOptional(x: i32) ?i32 {
214 return x;
215}
216fn returnError() anyerror!i32 {
217 return error.YouWantedAnError;
218}
219fn returnSuccess(x: i32) anyerror!i32 {
220 return x;
221}
222fn returnFalse() bool {
223 return false;
224}
225fn returnTrue() bool {
226 return true;
227}
test/cases/widening.zig deleted-27
...@@ -1,27 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4
5test "integer widening" {
6 var a: u8 = 250;
7 var b: u16 = a;
8 var c: u32 = b;
9 var d: u64 = c;
10 var e: u64 = d;
11 var f: u128 = e;
12 assert(f == a);
13}
14
15test "implicit unsigned integer to signed integer" {
16 var a: u8 = 250;
17 var b: i16 = a;
18 assert(b == 250);
19}
20
21test "float widening" {
22 var a: f16 = 12.34;
23 var b: f32 = a;
24 var c: f64 = b;
25 var d: f128 = c;
26 assert(d == a);
27}
test/compile_errors.zig+2-2
...@@ -3220,7 +3220,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3220,7 +3220,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3220 \\ return 2;3220 \\ return 2;
3221 \\}3221 \\}
3222 ,3222 ,
3223 ".tmp_source.zig:2:15: error: unable to infer expression type",3223 ".tmp_source.zig:2:15: error: values of type 'comptime_int' must be comptime known",
3224 );3224 );
32253225
3226 cases.add(3226 cases.add(
...@@ -3566,7 +3566,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3566,7 +3566,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3566 \\3566 \\
3567 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }3567 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
3568 ,3568 ,
3569 ".tmp_source.zig:2:11: error: expected type, found 'i32'",3569 ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'",
3570 );3570 );
35713571
3572 cases.add(3572 cases.add(
test/stage1/behavior.zig created+80
...@@ -0,0 +1,80 @@
1comptime {
2 _ = @import("behavior/align.zig");
3 _ = @import("behavior/alignof.zig");
4 _ = @import("behavior/array.zig");
5 _ = @import("behavior/asm.zig");
6 _ = @import("behavior/atomics.zig");
7 _ = @import("behavior/bit_shifting.zig");
8 _ = @import("behavior/bitcast.zig");
9 _ = @import("behavior/bitreverse.zig");
10 _ = @import("behavior/bool.zig");
11 _ = @import("behavior/bswap.zig");
12 _ = @import("behavior/bugs/1076.zig");
13 _ = @import("behavior/bugs/1111.zig");
14 _ = @import("behavior/bugs/1277.zig");
15 _ = @import("behavior/bugs/1322.zig");
16 _ = @import("behavior/bugs/1381.zig");
17 _ = @import("behavior/bugs/1421.zig");
18 _ = @import("behavior/bugs/1442.zig");
19 _ = @import("behavior/bugs/1486.zig");
20 _ = @import("behavior/bugs/394.zig");
21 _ = @import("behavior/bugs/655.zig");
22 _ = @import("behavior/bugs/656.zig");
23 _ = @import("behavior/bugs/726.zig");
24 _ = @import("behavior/bugs/828.zig");
25 _ = @import("behavior/bugs/920.zig");
26 _ = @import("behavior/byval_arg_var.zig");
27 _ = @import("behavior/cancel.zig");
28 _ = @import("behavior/cast.zig");
29 _ = @import("behavior/const_slice_child.zig");
30 _ = @import("behavior/coroutine_await_struct.zig");
31 _ = @import("behavior/coroutines.zig");
32 _ = @import("behavior/defer.zig");
33 _ = @import("behavior/enum.zig");
34 _ = @import("behavior/enum_with_members.zig");
35 _ = @import("behavior/error.zig");
36 _ = @import("behavior/eval.zig");
37 _ = @import("behavior/field_parent_ptr.zig");
38 _ = @import("behavior/fn.zig");
39 _ = @import("behavior/fn_in_struct_in_comptime.zig");
40 _ = @import("behavior/for.zig");
41 _ = @import("behavior/generics.zig");
42 _ = @import("behavior/if.zig");
43 _ = @import("behavior/import.zig");
44 _ = @import("behavior/incomplete_struct_param_tld.zig");
45 _ = @import("behavior/inttoptr.zig");
46 _ = @import("behavior/ir_block_deps.zig");
47 _ = @import("behavior/math.zig");
48 _ = @import("behavior/merge_error_sets.zig");
49 _ = @import("behavior/misc.zig");
50 _ = @import("behavior/namespace_depends_on_compile_var/index.zig");
51 _ = @import("behavior/new_stack_call.zig");
52 _ = @import("behavior/null.zig");
53 _ = @import("behavior/optional.zig");
54 _ = @import("behavior/pointers.zig");
55 _ = @import("behavior/popcount.zig");
56 _ = @import("behavior/ptrcast.zig");
57 _ = @import("behavior/pub_enum/index.zig");
58 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
59 _ = @import("behavior/reflection.zig");
60 _ = @import("behavior/sizeof_and_typeof.zig");
61 _ = @import("behavior/slice.zig");
62 _ = @import("behavior/struct.zig");
63 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
64 _ = @import("behavior/struct_contains_slice_of_itself.zig");
65 _ = @import("behavior/switch.zig");
66 _ = @import("behavior/switch_prong_err_enum.zig");
67 _ = @import("behavior/switch_prong_implicit_cast.zig");
68 _ = @import("behavior/syntax.zig");
69 _ = @import("behavior/this.zig");
70 _ = @import("behavior/truncate.zig");
71 _ = @import("behavior/try.zig");
72 _ = @import("behavior/type_info.zig");
73 _ = @import("behavior/undefined.zig");
74 _ = @import("behavior/underscore.zig");
75 _ = @import("behavior/union.zig");
76 _ = @import("behavior/var_args.zig");
77 _ = @import("behavior/void.zig");
78 _ = @import("behavior/while.zig");
79 _ = @import("behavior/widening.zig");
80}
test/stage1/behavior/align.zig created+230
...@@ -0,0 +1,230 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const builtin = @import("builtin");
3
4var foo: u8 align(4) = 100;
5
6test "global variable alignment" {
7 assertOrPanic(@typeOf(&foo).alignment == 4);
8 assertOrPanic(@typeOf(&foo) == *align(4) u8);
9 const slice = (*[1]u8)(&foo)[0..];
10 assertOrPanic(@typeOf(slice) == []align(4) u8);
11}
12
13fn derp() align(@sizeOf(usize) * 2) i32 {
14 return 1234;
15}
16fn noop1() align(1) void {}
17fn noop4() align(4) void {}
18
19test "function alignment" {
20 assertOrPanic(derp() == 1234);
21 assertOrPanic(@typeOf(noop1) == fn () align(1) void);
22 assertOrPanic(@typeOf(noop4) == fn () align(4) void);
23 noop1();
24 noop4();
25}
26
27var baz: packed struct {
28 a: u32,
29 b: u32,
30} = undefined;
31
32test "packed struct alignment" {
33 assertOrPanic(@typeOf(&baz.b) == *align(1) u32);
34}
35
36const blah: packed struct {
37 a: u3,
38 b: u3,
39 c: u2,
40} = undefined;
41
42test "bit field alignment" {
43 assertOrPanic(@typeOf(&blah.b) == *align(1:3:1) const u3);
44}
45
46test "default alignment allows unspecified in type syntax" {
47 assertOrPanic(*u32 == *align(@alignOf(u32)) u32);
48}
49
50test "implicitly decreasing pointer alignment" {
51 const a: u32 align(4) = 3;
52 const b: u32 align(8) = 4;
53 assertOrPanic(addUnaligned(&a, &b) == 7);
54}
55
56fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
57 return a.* + b.*;
58}
59
60test "implicitly decreasing slice alignment" {
61 const a: u32 align(4) = 3;
62 const b: u32 align(8) = 4;
63 assertOrPanic(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
64}
65fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
66 return a[0] + b[0];
67}
68
69test "specifying alignment allows pointer cast" {
70 testBytesAlign(0x33);
71}
72fn testBytesAlign(b: u8) void {
73 var bytes align(4) = []u8{
74 b,
75 b,
76 b,
77 b,
78 };
79 const ptr = @ptrCast(*u32, &bytes[0]);
80 assertOrPanic(ptr.* == 0x33333333);
81}
82
83test "specifying alignment allows slice cast" {
84 testBytesAlignSlice(0x33);
85}
86fn testBytesAlignSlice(b: u8) void {
87 var bytes align(4) = []u8{
88 b,
89 b,
90 b,
91 b,
92 };
93 const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
94 assertOrPanic(slice[0] == 0x33333333);
95}
96
97test "@alignCast pointers" {
98 var x: u32 align(4) = 1;
99 expectsOnly1(&x);
100 assertOrPanic(x == 2);
101}
102fn expectsOnly1(x: *align(1) u32) void {
103 expects4(@alignCast(4, x));
104}
105fn expects4(x: *align(4) u32) void {
106 x.* += 1;
107}
108
109test "@alignCast slices" {
110 var array align(4) = []u32{
111 1,
112 1,
113 };
114 const slice = array[0..];
115 sliceExpectsOnly1(slice);
116 assertOrPanic(slice[0] == 2);
117}
118fn sliceExpectsOnly1(slice: []align(1) u32) void {
119 sliceExpects4(@alignCast(4, slice));
120}
121fn sliceExpects4(slice: []align(4) u32) void {
122 slice[0] += 1;
123}
124
125test "implicitly decreasing fn alignment" {
126 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
127 testImplicitlyDecreaseFnAlign(alignedBig, 5678);
128}
129
130fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
131 assertOrPanic(ptr() == answer);
132}
133
134fn alignedSmall() align(8) i32 {
135 return 1234;
136}
137fn alignedBig() align(16) i32 {
138 return 5678;
139}
140
141test "@alignCast functions" {
142 assertOrPanic(fnExpectsOnly1(simple4) == 0x19);
143}
144fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
145 return fnExpects4(@alignCast(4, ptr));
146}
147fn fnExpects4(ptr: fn () align(4) i32) i32 {
148 return ptr();
149}
150fn simple4() align(4) i32 {
151 return 0x19;
152}
153
154test "generic function with align param" {
155 assertOrPanic(whyWouldYouEverDoThis(1) == 0x1);
156 assertOrPanic(whyWouldYouEverDoThis(4) == 0x1);
157 assertOrPanic(whyWouldYouEverDoThis(8) == 0x1);
158}
159
160fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
161 return 0x1;
162}
163
164test "@ptrCast preserves alignment of bigger source" {
165 var x: u32 align(16) = 1234;
166 const ptr = @ptrCast(*u8, &x);
167 assertOrPanic(@typeOf(ptr) == *align(16) u8);
168}
169
170test "runtime known array index has best alignment possible" {
171 // take full advantage of over-alignment
172 var array align(4) = []u8{ 1, 2, 3, 4 };
173 assertOrPanic(@typeOf(&array[0]) == *align(4) u8);
174 assertOrPanic(@typeOf(&array[1]) == *u8);
175 assertOrPanic(@typeOf(&array[2]) == *align(2) u8);
176 assertOrPanic(@typeOf(&array[3]) == *u8);
177
178 // because align is too small but we still figure out to use 2
179 var bigger align(2) = []u64{ 1, 2, 3, 4 };
180 assertOrPanic(@typeOf(&bigger[0]) == *align(2) u64);
181 assertOrPanic(@typeOf(&bigger[1]) == *align(2) u64);
182 assertOrPanic(@typeOf(&bigger[2]) == *align(2) u64);
183 assertOrPanic(@typeOf(&bigger[3]) == *align(2) u64);
184
185 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
186 var smaller align(2) = []u32{ 1, 2, 3, 4 };
187 comptime assertOrPanic(@typeOf(smaller[0..]) == []align(2) u32);
188 comptime assertOrPanic(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
189 testIndex(smaller[0..].ptr, 0, *align(2) u32);
190 testIndex(smaller[0..].ptr, 1, *align(2) u32);
191 testIndex(smaller[0..].ptr, 2, *align(2) u32);
192 testIndex(smaller[0..].ptr, 3, *align(2) u32);
193
194 // has to use ABI alignment because index known at runtime only
195 testIndex2(array[0..].ptr, 0, *u8);
196 testIndex2(array[0..].ptr, 1, *u8);
197 testIndex2(array[0..].ptr, 2, *u8);
198 testIndex2(array[0..].ptr, 3, *u8);
199}
200fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
201 comptime assertOrPanic(@typeOf(&smaller[index]) == T);
202}
203fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
204 comptime assertOrPanic(@typeOf(&ptr[index]) == T);
205}
206
207test "alignstack" {
208 assertOrPanic(fnWithAlignedStack() == 1234);
209}
210
211fn fnWithAlignedStack() i32 {
212 @setAlignStack(256);
213 return 1234;
214}
215
216test "alignment of structs" {
217 assertOrPanic(@alignOf(struct {
218 a: i32,
219 b: *i32,
220 }) == @alignOf(usize));
221}
222
223test "alignment of extern() void" {
224 var runtime_nothing = nothing;
225 const casted1 = @ptrCast(*const u8, runtime_nothing);
226 const casted2 = @ptrCast(extern fn () void, casted1);
227 casted2();
228}
229
230extern fn nothing() void {}
test/stage1/behavior/alignof.zig created+18
...@@ -0,0 +1,18 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const Foo = struct {
7 x: u32,
8 y: u32,
9 z: u32,
10};
11
12test "@alignOf(T) before referencing T" {
13 comptime assertOrPanic(@alignOf(Foo) != maxInt(usize));
14 if (builtin.arch == builtin.Arch.x86_64) {
15 comptime assertOrPanic(@alignOf(Foo) == 4);
16 }
17}
18
test/stage1/behavior/array.zig created+270
...@@ -0,0 +1,270 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4test "arrays" {
5 var array: [5]u32 = undefined;
6
7 var i: u32 = 0;
8 while (i < 5) {
9 array[i] = i + 1;
10 i = array[i];
11 }
12
13 i = 0;
14 var accumulator = u32(0);
15 while (i < 5) {
16 accumulator += array[i];
17
18 i += 1;
19 }
20
21 assertOrPanic(accumulator == 15);
22 assertOrPanic(getArrayLen(array) == 5);
23}
24fn getArrayLen(a: []const u32) usize {
25 return a.len;
26}
27
28test "void arrays" {
29 var array: [4]void = undefined;
30 array[0] = void{};
31 array[1] = array[2];
32 assertOrPanic(@sizeOf(@typeOf(array)) == 0);
33 assertOrPanic(array.len == 4);
34}
35
36test "array literal" {
37 const hex_mult = []u16{
38 4096,
39 256,
40 16,
41 1,
42 };
43
44 assertOrPanic(hex_mult.len == 4);
45 assertOrPanic(hex_mult[1] == 256);
46}
47
48test "array dot len const expr" {
49 assertOrPanic(comptime x: {
50 break :x some_array.len == 4;
51 });
52}
53
54const ArrayDotLenConstExpr = struct {
55 y: [some_array.len]u8,
56};
57const some_array = []u8{
58 0,
59 1,
60 2,
61 3,
62};
63
64test "nested arrays" {
65 const array_of_strings = [][]const u8{
66 "hello",
67 "this",
68 "is",
69 "my",
70 "thing",
71 };
72 for (array_of_strings) |s, i| {
73 if (i == 0) assertOrPanic(mem.eql(u8, s, "hello"));
74 if (i == 1) assertOrPanic(mem.eql(u8, s, "this"));
75 if (i == 2) assertOrPanic(mem.eql(u8, s, "is"));
76 if (i == 3) assertOrPanic(mem.eql(u8, s, "my"));
77 if (i == 4) assertOrPanic(mem.eql(u8, s, "thing"));
78 }
79}
80
81var s_array: [8]Sub = undefined;
82const Sub = struct {
83 b: u8,
84};
85const Str = struct {
86 a: []Sub,
87};
88test "set global var array via slice embedded in struct" {
89 var s = Str{ .a = s_array[0..] };
90
91 s.a[0].b = 1;
92 s.a[1].b = 2;
93 s.a[2].b = 3;
94
95 assertOrPanic(s_array[0].b == 1);
96 assertOrPanic(s_array[1].b == 2);
97 assertOrPanic(s_array[2].b == 3);
98}
99
100test "array literal with specified size" {
101 var array = [2]u8{
102 1,
103 2,
104 };
105 assertOrPanic(array[0] == 1);
106 assertOrPanic(array[1] == 2);
107}
108
109test "array child property" {
110 var x: [5]i32 = undefined;
111 assertOrPanic(@typeOf(x).Child == i32);
112}
113
114test "array len property" {
115 var x: [5]i32 = undefined;
116 assertOrPanic(@typeOf(x).len == 5);
117}
118
119test "array len field" {
120 var arr = [4]u8{ 0, 0, 0, 0 };
121 var ptr = &arr;
122 assertOrPanic(arr.len == 4);
123 comptime assertOrPanic(arr.len == 4);
124 assertOrPanic(ptr.len == 4);
125 comptime assertOrPanic(ptr.len == 4);
126}
127
128test "single-item pointer to array indexing and slicing" {
129 testSingleItemPtrArrayIndexSlice();
130 comptime testSingleItemPtrArrayIndexSlice();
131}
132
133fn testSingleItemPtrArrayIndexSlice() void {
134 var array = "aaaa";
135 doSomeMangling(&array);
136 assertOrPanic(mem.eql(u8, "azya", array));
137}
138
139fn doSomeMangling(array: *[4]u8) void {
140 array[1] = 'z';
141 array[2..3][0] = 'y';
142}
143
144test "implicit cast single-item pointer" {
145 testImplicitCastSingleItemPtr();
146 comptime testImplicitCastSingleItemPtr();
147}
148
149fn testImplicitCastSingleItemPtr() void {
150 var byte: u8 = 100;
151 const slice = (*[1]u8)(&byte)[0..];
152 slice[0] += 1;
153 assertOrPanic(byte == 101);
154}
155
156fn testArrayByValAtComptime(b: [2]u8) u8 {
157 return b[0];
158}
159
160test "comptime evalutating function that takes array by value" {
161 const arr = []u8{ 0, 1 };
162 _ = comptime testArrayByValAtComptime(arr);
163 _ = comptime testArrayByValAtComptime(arr);
164}
165
166test "implicit comptime in array type size" {
167 var arr: [plusOne(10)]bool = undefined;
168 assertOrPanic(arr.len == 11);
169}
170
171fn plusOne(x: u32) u32 {
172 return x + 1;
173}
174
175test "array literal as argument to function" {
176 const S = struct {
177 fn entry(two: i32) void {
178 foo([]i32{
179 1,
180 2,
181 3,
182 });
183 foo([]i32{
184 1,
185 two,
186 3,
187 });
188 foo2(true, []i32{
189 1,
190 2,
191 3,
192 });
193 foo2(true, []i32{
194 1,
195 two,
196 3,
197 });
198 }
199 fn foo(x: []const i32) void {
200 assertOrPanic(x[0] == 1);
201 assertOrPanic(x[1] == 2);
202 assertOrPanic(x[2] == 3);
203 }
204 fn foo2(trash: bool, x: []const i32) void {
205 assertOrPanic(trash);
206 assertOrPanic(x[0] == 1);
207 assertOrPanic(x[1] == 2);
208 assertOrPanic(x[2] == 3);
209 }
210 };
211 S.entry(2);
212 comptime S.entry(2);
213}
214
215test "double nested array to const slice cast in array literal" {
216 const S = struct {
217 fn entry(two: i32) void {
218 const cases = [][]const []const i32{
219 [][]const i32{[]i32{1}},
220 [][]const i32{[]i32{ 2, 3 }},
221 [][]const i32{
222 []i32{4},
223 []i32{ 5, 6, 7 },
224 },
225 };
226 check(cases);
227
228 const cases2 = [][]const i32{
229 []i32{1},
230 []i32{ two, 3 },
231 };
232 assertOrPanic(cases2.len == 2);
233 assertOrPanic(cases2[0].len == 1);
234 assertOrPanic(cases2[0][0] == 1);
235 assertOrPanic(cases2[1].len == 2);
236 assertOrPanic(cases2[1][0] == 2);
237 assertOrPanic(cases2[1][1] == 3);
238
239 const cases3 = [][]const []const i32{
240 [][]const i32{[]i32{1}},
241 [][]const i32{[]i32{ two, 3 }},
242 [][]const i32{
243 []i32{4},
244 []i32{ 5, 6, 7 },
245 },
246 };
247 check(cases3);
248 }
249
250 fn check(cases: []const []const []const i32) void {
251 assertOrPanic(cases.len == 3);
252 assertOrPanic(cases[0].len == 1);
253 assertOrPanic(cases[0][0].len == 1);
254 assertOrPanic(cases[0][0][0] == 1);
255 assertOrPanic(cases[1].len == 1);
256 assertOrPanic(cases[1][0].len == 2);
257 assertOrPanic(cases[1][0][0] == 2);
258 assertOrPanic(cases[1][0][1] == 3);
259 assertOrPanic(cases[2].len == 2);
260 assertOrPanic(cases[2][0].len == 1);
261 assertOrPanic(cases[2][0][0] == 4);
262 assertOrPanic(cases[2][1].len == 3);
263 assertOrPanic(cases[2][1][0] == 5);
264 assertOrPanic(cases[2][1][1] == 6);
265 assertOrPanic(cases[2][1][2] == 7);
266 }
267 };
268 S.entry(2);
269 comptime S.entry(2);
270}
test/stage1/behavior/asm.zig created+92
...@@ -0,0 +1,92 @@
1const config = @import("builtin");
2const assertOrPanic = @import("std").debug.assertOrPanic;
3
4comptime {
5 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
6 asm volatile (
7 \\.globl aoeu;
8 \\.type aoeu, @function;
9 \\.set aoeu, derp;
10 );
11 }
12}
13
14test "module level assembly" {
15 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
16 assertOrPanic(aoeu() == 1234);
17 }
18}
19
20test "output constraint modifiers" {
21 // This is only testing compilation.
22 var a: u32 = 3;
23 asm volatile (""
24 : [_] "=m,r" (a)
25 :
26 : ""
27 );
28 asm volatile (""
29 : [_] "=r,m" (a)
30 :
31 : ""
32 );
33}
34
35test "alternative constraints" {
36 // Make sure we allow commas as a separator for alternative constraints.
37 var a: u32 = 3;
38 asm volatile (""
39 : [_] "=r,m" (a)
40 : [_] "r,m" (a)
41 : ""
42 );
43}
44
45test "sized integer/float in asm input" {
46 asm volatile (""
47 :
48 : [_] "m" (usize(3))
49 : ""
50 );
51 asm volatile (""
52 :
53 : [_] "m" (i15(-3))
54 : ""
55 );
56 asm volatile (""
57 :
58 : [_] "m" (u3(3))
59 : ""
60 );
61 asm volatile (""
62 :
63 : [_] "m" (i3(3))
64 : ""
65 );
66 asm volatile (""
67 :
68 : [_] "m" (u121(3))
69 : ""
70 );
71 asm volatile (""
72 :
73 : [_] "m" (i121(3))
74 : ""
75 );
76 asm volatile (""
77 :
78 : [_] "m" (f32(3.17))
79 : ""
80 );
81 asm volatile (""
82 :
83 : [_] "m" (f64(3.17))
84 : ""
85 );
86}
87
88extern fn aoeu() i32;
89
90export fn derp() i32 {
91 return 1234;
92}
test/stage1/behavior/atomics.zig created+71
...@@ -0,0 +1,71 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const builtin = @import("builtin");
4const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;
6
7test "cmpxchg" {
8 var x: i32 = 1234;
9 if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
10 assertOrPanic(x1 == 1234);
11 } else {
12 @panic("cmpxchg should have failed");
13 }
14
15 while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
16 assertOrPanic(x1 == 1234);
17 }
18 assertOrPanic(x == 5678);
19
20 assertOrPanic(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
21 assertOrPanic(x == 42);
22}
23
24test "fence" {
25 var x: i32 = 1234;
26 @fence(AtomicOrder.SeqCst);
27 x = 5678;
28}
29
30test "atomicrmw and atomicload" {
31 var data: u8 = 200;
32 testAtomicRmw(&data);
33 assertOrPanic(data == 42);
34 testAtomicLoad(&data);
35}
36
37fn testAtomicRmw(ptr: *u8) void {
38 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
39 assertOrPanic(prev_value == 200);
40 comptime {
41 var x: i32 = 1234;
42 const y: i32 = 12345;
43 assertOrPanic(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
44 assertOrPanic(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
45 }
46}
47
48fn testAtomicLoad(ptr: *u8) void {
49 const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
50 assertOrPanic(x == 42);
51}
52
53test "cmpxchg with ptr" {
54 var data1: i32 = 1234;
55 var data2: i32 = 5678;
56 var data3: i32 = 9101;
57 var x: *i32 = &data1;
58 if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
59 assertOrPanic(x1 == &data1);
60 } else {
61 @panic("cmpxchg should have failed");
62 }
63
64 while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
65 assertOrPanic(x1 == &data1);
66 }
67 assertOrPanic(x == &data3);
68
69 assertOrPanic(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
70 assertOrPanic(x == &data2);
71}
test/stage1/behavior/bit_shifting.zig created+88
...@@ -0,0 +1,88 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 assertOrPanic(Key == @IntType(false, Key.bit_count));
6 assertOrPanic(Key.bit_count >= mask_bit_count);
7 const ShardKey = @IntType(false, mask_bit_count);
8 const shift_amount = Key.bit_count - ShardKey.bit_count;
9 return struct {
10 const Self = @This();
11 shards: [1 << ShardKey.bit_count]?*Node,
12
13 pub fn create() Self {
14 return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) };
15 }
16
17 fn getShardKey(key: Key) ShardKey {
18 // https://github.com/ziglang/zig/issues/1544
19 // this special case is needed because you can't u32 >> 32.
20 if (ShardKey == u0) return 0;
21
22 // this can be u1 >> u0
23 const shard_key = key >> shift_amount;
24
25 // TODO: https://github.com/ziglang/zig/issues/1544
26 // This cast could be implicit if we teach the compiler that
27 // u32 >> 30 -> u2
28 return @intCast(ShardKey, shard_key);
29 }
30
31 pub fn put(self: *Self, node: *Node) void {
32 const shard_key = Self.getShardKey(node.key);
33 node.next = self.shards[shard_key];
34 self.shards[shard_key] = node;
35 }
36
37 pub fn get(self: *Self, key: Key) ?*Node {
38 const shard_key = Self.getShardKey(key);
39 var maybe_node = self.shards[shard_key];
40 while (maybe_node) |node| : (maybe_node = node.next) {
41 if (node.key == key) return node;
42 }
43 return null;
44 }
45
46 pub const Node = struct {
47 key: Key,
48 value: V,
49 next: ?*Node,
50
51 pub fn init(self: *Node, key: Key, value: V) void {
52 self.key = key;
53 self.value = value;
54 self.next = null;
55 }
56 };
57 };
58}
59
60test "sharded table" {
61 // realistic 16-way sharding
62 testShardedTable(u32, 4, 8);
63
64 testShardedTable(u5, 0, 32); // ShardKey == u0
65 testShardedTable(u5, 2, 32);
66 testShardedTable(u5, 5, 32);
67
68 testShardedTable(u1, 0, 2);
69 testShardedTable(u1, 1, 2); // this does u1 >> u0
70
71 testShardedTable(u0, 0, 1);
72}
73fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void {
74 const Table = ShardedTable(Key, mask_bit_count, void);
75
76 var table = Table.create();
77 var node_buffer: [node_count]Table.Node = undefined;
78 for (node_buffer) |*node, i| {
79 const key = @intCast(Key, i);
80 assertOrPanic(table.get(key) == null);
81 node.init(key, {});
82 table.put(node);
83 }
84
85 for (node_buffer) |*node, i| {
86 assertOrPanic(table.get(@intCast(Key, i)) == node);
87 }
88}
test/stage1/behavior/bitcast.zig created+36
...@@ -0,0 +1,36 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const maxInt = std.math.maxInt;
4
5test "@bitCast i32 -> u32" {
6 testBitCast_i32_u32();
7 comptime testBitCast_i32_u32();
8}
9
10fn testBitCast_i32_u32() void {
11 assertOrPanic(conv(-1) == maxInt(u32));
12 assertOrPanic(conv2(maxInt(u32)) == -1);
13}
14
15fn conv(x: i32) u32 {
16 return @bitCast(u32, x);
17}
18fn conv2(x: u32) i32 {
19 return @bitCast(i32, x);
20}
21
22test "@bitCast extern enum to its integer type" {
23 const SOCK = extern enum {
24 A,
25 B,
26
27 fn testBitCastExternEnum() void {
28 var SOCK_DGRAM = @This().B;
29 var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
30 assertOrPanic(sock_dgram == 1);
31 }
32 };
33
34 SOCK.testBitCastExternEnum();
35 comptime SOCK.testBitCastExternEnum();
36}
test/stage1/behavior/bitreverse.zig created+81
...@@ -0,0 +1,81 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const minInt = std.math.minInt;
4
5test "@bitreverse" {
6 comptime testBitReverse();
7 testBitReverse();
8}
9
10fn testBitReverse() void {
11 // using comptime_ints, unsigned
12 assertOrPanic(@bitreverse(u0, 0) == 0);
13 assertOrPanic(@bitreverse(u5, 0x12) == 0x9);
14 assertOrPanic(@bitreverse(u8, 0x12) == 0x48);
15 assertOrPanic(@bitreverse(u16, 0x1234) == 0x2c48);
16 assertOrPanic(@bitreverse(u24, 0x123456) == 0x6a2c48);
17 assertOrPanic(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
18 assertOrPanic(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
19 assertOrPanic(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
20 assertOrPanic(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
21 assertOrPanic(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
22 assertOrPanic(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
23
24 // using runtime uints, unsigned
25 var num0: u0 = 0;
26 assertOrPanic(@bitreverse(u0, num0) == 0);
27 var num5: u5 = 0x12;
28 assertOrPanic(@bitreverse(u5, num5) == 0x9);
29 var num8: u8 = 0x12;
30 assertOrPanic(@bitreverse(u8, num8) == 0x48);
31 var num16: u16 = 0x1234;
32 assertOrPanic(@bitreverse(u16, num16) == 0x2c48);
33 var num24: u24 = 0x123456;
34 assertOrPanic(@bitreverse(u24, num24) == 0x6a2c48);
35 var num32: u32 = 0x12345678;
36 assertOrPanic(@bitreverse(u32, num32) == 0x1e6a2c48);
37 var num40: u40 = 0x123456789a;
38 assertOrPanic(@bitreverse(u40, num40) == 0x591e6a2c48);
39 var num48: u48 = 0x123456789abc;
40 assertOrPanic(@bitreverse(u48, num48) == 0x3d591e6a2c48);
41 var num56: u56 = 0x123456789abcde;
42 assertOrPanic(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
43 var num64: u64 = 0x123456789abcdef1;
44 assertOrPanic(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
45 var num128: u128 = 0x123456789abcdef11121314151617181;
46 assertOrPanic(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
47
48 // using comptime_ints, signed, positive
49 assertOrPanic(@bitreverse(i0, 0) == 0);
50 assertOrPanic(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49)));
51 assertOrPanic(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48)));
52 assertOrPanic(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48)));
53 assertOrPanic(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48)));
54 assertOrPanic(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48)));
55 assertOrPanic(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48)));
56 assertOrPanic(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48)));
57 assertOrPanic(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48)));
58 assertOrPanic(@bitreverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48)));
59
60 // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
61 var neg5: i5 = minInt(i5) + 1;
62 assertOrPanic(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
63 var neg8: i8 = -18;
64 assertOrPanic(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
65 var neg16: i16 = -32694;
66 assertOrPanic(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
67 var neg24: i24 = -6773785;
68 assertOrPanic(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
69 var neg32: i32 = -16773785;
70 assertOrPanic(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
71 var neg40: i40 = minInt(i40) + 12345;
72 assertOrPanic(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
73 var neg48: i48 = minInt(i48) + 12345;
74 assertOrPanic(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
75 var neg56: i56 = minInt(i56) + 12345;
76 assertOrPanic(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
77 var neg64: i64 = minInt(i64) + 12345;
78 assertOrPanic(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
79 var neg128: i128 = minInt(i128) + 12345;
80 assertOrPanic(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
81}
test/stage1/behavior/bool.zig created+35
...@@ -0,0 +1,35 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "bool literals" {
4 assertOrPanic(true);
5 assertOrPanic(!false);
6}
7
8test "cast bool to int" {
9 const t = true;
10 const f = false;
11 assertOrPanic(@boolToInt(t) == u32(1));
12 assertOrPanic(@boolToInt(f) == u32(0));
13 nonConstCastBoolToInt(t, f);
14}
15
16fn nonConstCastBoolToInt(t: bool, f: bool) void {
17 assertOrPanic(@boolToInt(t) == u32(1));
18 assertOrPanic(@boolToInt(f) == u32(0));
19}
20
21test "bool cmp" {
22 assertOrPanic(testBoolCmp(true, false) == false);
23}
24fn testBoolCmp(a: bool, b: bool) bool {
25 return a == b;
26}
27
28const global_f = false;
29const global_t = true;
30const not_global_f = !global_f;
31const not_global_t = !global_t;
32test "compile time bool not" {
33 assertOrPanic(not_global_f);
34 assertOrPanic(!not_global_t);
35}
test/stage1/behavior/bswap.zig created+32
...@@ -0,0 +1,32 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "@bswap" {
5 comptime testByteSwap();
6 testByteSwap();
7}
8
9fn testByteSwap() void {
10 assertOrPanic(@bswap(u0, 0) == 0);
11 assertOrPanic(@bswap(u8, 0x12) == 0x12);
12 assertOrPanic(@bswap(u16, 0x1234) == 0x3412);
13 assertOrPanic(@bswap(u24, 0x123456) == 0x563412);
14 assertOrPanic(@bswap(u32, 0x12345678) == 0x78563412);
15 assertOrPanic(@bswap(u40, 0x123456789a) == 0x9a78563412);
16 assertOrPanic(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
17 assertOrPanic(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
18 assertOrPanic(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
19 assertOrPanic(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
20
21 assertOrPanic(@bswap(i0, 0) == 0);
22 assertOrPanic(@bswap(i8, -50) == -50);
23 assertOrPanic(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
24 assertOrPanic(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
25 assertOrPanic(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
26 assertOrPanic(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
27 assertOrPanic(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
28 assertOrPanic(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
29 assertOrPanic(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
30 assertOrPanic(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
31 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
32}
test/stage1/behavior/bugs/1076.zig created+16
...@@ -0,0 +1,16 @@
1const std = @import("std");
2const mem = std.mem;
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "comptime code should not modify constant data" {
6 testCastPtrOfArrayToSliceAndPtr();
7 comptime testCastPtrOfArrayToSliceAndPtr();
8}
9
10fn testCastPtrOfArrayToSliceAndPtr() void {
11 var array = "aoeu";
12 const x: [*]u8 = &array;
13 x[0] += 1;
14 assertOrPanic(mem.eql(u8, array[0..], "boeu"));
15}
16
test/stage1/behavior/bugs/1111.zig created+12
...@@ -0,0 +1,12 @@
1const Foo = extern enum {
2 Bar = -1,
3};
4
5test "issue 1111 fixed" {
6 const v = Foo.Bar;
7
8 switch (v) {
9 Foo.Bar => return,
10 else => return,
11 }
12}
test/stage1/behavior/bugs/1277.zig created+15
...@@ -0,0 +1,15 @@
1const std = @import("std");
2
3const S = struct {
4 f: ?fn () i32,
5};
6
7const s = S{ .f = f };
8
9fn f() i32 {
10 return 1234;
11}
12
13test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
14 std.debug.assertOrPanic(s.f.?() == 1234);
15}
test/stage1/behavior/bugs/1322.zig created+19
...@@ -0,0 +1,19 @@
1const std = @import("std");
2
3const B = union(enum) {
4 c: C,
5 None,
6};
7
8const A = struct {
9 b: B,
10};
11
12const C = struct {};
13
14test "tagged union with all void fields but a meaningful tag" {
15 var a: A = A{ .b = B{ .c = C{} } };
16 std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).c);
17 a = A{ .b = B.None };
18 std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).None);
19}
test/stage1/behavior/bugs/1381.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2
3const B = union(enum) {
4 D: u8,
5 E: u16,
6};
7
8const A = union(enum) {
9 B: B,
10 C: u8,
11};
12
13test "union that needs padding bytes inside an array" {
14 var as = []A{
15 A{ .B = B{ .D = 1 } },
16 A{ .B = B{ .D = 1 } },
17 };
18
19 const a = as[0].B;
20 std.debug.assertOrPanic(a.D == 1);
21}
test/stage1/behavior/bugs/1421.zig created+14
...@@ -0,0 +1,14 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assertOrPanic = std.debug.assertOrPanic;
4
5const S = struct {
6 fn method() builtin.TypeInfo {
7 return @typeInfo(S);
8 }
9};
10
11test "functions with return type required to be comptime are generic" {
12 const ti = S.method();
13 assertOrPanic(builtin.TypeId(ti) == builtin.TypeId.Struct);
14}
test/stage1/behavior/bugs/1442.zig created+11
...@@ -0,0 +1,11 @@
1const std = @import("std");
2
3const Union = union(enum) {
4 Text: []const u8,
5 Color: u32,
6};
7
8test "const error union field alignment" {
9 var union_or_err: anyerror!Union = Union{ .Color = 1234 };
10 std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
11}
test/stage1/behavior/bugs/1486.zig created+11
...@@ -0,0 +1,11 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 assertOrPanic(&global == ptr);
9 assertOrPanic(ptr.* == 1234);
10}
11
test/stage1/behavior/bugs/394.zig created+18
...@@ -0,0 +1,18 @@
1const E = union(enum) {
2 A: [9]u8,
3 B: u64,
4};
5const S = struct {
6 x: u8,
7 y: E,
8};
9
10const assertOrPanic = @import("std").debug.assertOrPanic;
11
12test "bug 394 fixed" {
13 const x = S{
14 .x = 3,
15 .y = E{ .B = 1 },
16 };
17 assertOrPanic(x.x == 3);
18}
test/stage1/behavior/bugs/655.zig created+12
...@@ -0,0 +1,12 @@
1const std = @import("std");
2const other_file = @import("655_other_file.zig");
3
4test "function with *const parameter with type dereferenced by namespace" {
5 const x: other_file.Integer = 1234;
6 comptime std.debug.assertOrPanic(@typeOf(&x) == *const other_file.Integer);
7 foo(&x);
8}
9
10fn foo(x: *const other_file.Integer) void {
11 std.debug.assertOrPanic(x.* == 1234);
12}
test/stage1/behavior/bugs/655_other_file.zig created+1
...@@ -0,0 +1 @@
1pub const Integer = u32;
test/stage1/behavior/bugs/656.zig created+31
...@@ -0,0 +1,31 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const PrefixOp = union(enum) {
4 Return,
5 AddrOf: Value,
6};
7
8const Value = struct {
9 align_expr: ?u32,
10};
11
12test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
13 foo(false, true);
14}
15
16fn foo(a: bool, b: bool) void {
17 var prefix_op = PrefixOp{
18 .AddrOf = Value{ .align_expr = 1234 },
19 };
20 if (a) {} else {
21 switch (prefix_op) {
22 PrefixOp.AddrOf => |addr_of_info| {
23 if (b) {}
24 if (addr_of_info.align_expr) |align_expr| {
25 assertOrPanic(align_expr == 1234);
26 }
27 },
28 PrefixOp.Return => {},
29 }
30 }
31}
test/stage1/behavior/bugs/726.zig created+16
...@@ -0,0 +1,16 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "@ptrCast from const to nullable" {
4 const c: u8 = 4;
5 var x: ?*const u8 = @ptrCast(?*const u8, &c);
6 assertOrPanic(x.?.* == 4);
7}
8
9test "@ptrCast from var in empty struct to nullable" {
10 const container = struct {
11 var c: u8 = 4;
12 };
13 var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
14 assertOrPanic(x.?.* == 4);
15}
16
test/stage1/behavior/bugs/828.zig created+33
...@@ -0,0 +1,33 @@
1const CountBy = struct {
2 a: usize,
3
4 const One = CountBy{ .a = 1 };
5
6 pub fn counter(self: *const CountBy) Counter {
7 return Counter{ .i = 0 };
8 }
9};
10
11const Counter = struct {
12 i: usize,
13
14 pub fn count(self: *Counter) bool {
15 self.i += 1;
16 return self.i <= 10;
17 }
18};
19
20fn constCount(comptime cb: *const CountBy, comptime unused: u32) void {
21 comptime {
22 var cnt = cb.counter();
23 if (cnt.i != 0) @compileError("Counter instance reused!");
24 while (cnt.count()) {}
25 }
26}
27
28test "comptime struct return should not return the same instance" {
29 //the first parameter must be passed by reference to trigger the bug
30 //a second parameter is required to trigger the bug
31 const ValA = constCount(&CountBy.One, 12);
32 const ValB = constCount(&CountBy.One, 15);
33}
test/stage1/behavior/bugs/920.zig created+65
...@@ -0,0 +1,65 @@
1const std = @import("std");
2const math = std.math;
3const Random = std.rand.Random;
4
5const ZigTable = struct {
6 r: f64,
7 x: [257]f64,
8 f: [257]f64,
9
10 pdf: fn (f64) f64,
11 is_symmetric: bool,
12 zero_case: fn (*Random, f64) f64,
13};
14
15fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable {
16 var tables: ZigTable = undefined;
17
18 tables.is_symmetric = is_symmetric;
19 tables.r = r;
20 tables.pdf = f;
21 tables.zero_case = zero_case;
22
23 tables.x[0] = v / f(r);
24 tables.x[1] = r;
25
26 for (tables.x[2..256]) |*entry, i| {
27 const last = tables.x[2 + i - 1];
28 entry.* = f_inv(v / last + f(last));
29 }
30 tables.x[256] = 0;
31
32 for (tables.f[0..]) |*entry, i| {
33 entry.* = f(tables.x[i]);
34 }
35
36 return tables;
37}
38
39const norm_r = 3.6541528853610088;
40const norm_v = 0.00492867323399;
41
42fn norm_f(x: f64) f64 {
43 return math.exp(-x * x / 2.0);
44}
45fn norm_f_inv(y: f64) f64 {
46 return math.sqrt(-2.0 * math.ln(y));
47}
48fn norm_zero_case(random: *Random, u: f64) f64 {
49 return 0.0;
50}
51
52const NormalDist = blk: {
53 @setEvalBranchQuota(30000);
54 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
55};
56
57test "bug 920 fixed" {
58 const NormalDist1 = blk: {
59 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
60 };
61
62 for (NormalDist1.f) |_, i| {
63 std.debug.assertOrPanic(NormalDist1.f[i] == NormalDist.f[i]);
64 }
65}
test/stage1/behavior/byval_arg_var.zig created+27
...@@ -0,0 +1,27 @@
1const std = @import("std");
2
3var result: []const u8 = "wrong";
4
5test "pass string literal byvalue to a generic var param" {
6 start();
7 blowUpStack(10);
8
9 std.debug.assertOrPanic(std.mem.eql(u8, result, "string literal"));
10}
11
12fn start() void {
13 foo("string literal");
14}
15
16fn foo(x: var) void {
17 bar(x);
18}
19
20fn bar(x: var) void {
21 result = x;
22}
23
24fn blowUpStack(x: u32) void {
25 if (x == 0) return;
26 blowUpStack(x - 1);
27}
test/stage1/behavior/cancel.zig created+92
...@@ -0,0 +1,92 @@
1const std = @import("std");
2
3var defer_f1: bool = false;
4var defer_f2: bool = false;
5var defer_f3: bool = false;
6
7test "cancel forwards" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = async<&da.allocator> f1() catch unreachable;
12 cancel p;
13 std.debug.assertOrPanic(defer_f1);
14 std.debug.assertOrPanic(defer_f2);
15 std.debug.assertOrPanic(defer_f3);
16}
17
18async fn f1() void {
19 defer {
20 defer_f1 = true;
21 }
22 await (async f2() catch unreachable);
23}
24
25async fn f2() void {
26 defer {
27 defer_f2 = true;
28 }
29 await (async f3() catch unreachable);
30}
31
32async fn f3() void {
33 defer {
34 defer_f3 = true;
35 }
36 suspend;
37}
38
39var defer_b1: bool = false;
40var defer_b2: bool = false;
41var defer_b3: bool = false;
42var defer_b4: bool = false;
43
44test "cancel backwards" {
45 var da = std.heap.DirectAllocator.init();
46 defer da.deinit();
47
48 const p = async<&da.allocator> b1() catch unreachable;
49 cancel p;
50 std.debug.assertOrPanic(defer_b1);
51 std.debug.assertOrPanic(defer_b2);
52 std.debug.assertOrPanic(defer_b3);
53 std.debug.assertOrPanic(defer_b4);
54}
55
56async fn b1() void {
57 defer {
58 defer_b1 = true;
59 }
60 await (async b2() catch unreachable);
61}
62
63var b4_handle: promise = undefined;
64
65async fn b2() void {
66 const b3_handle = async b3() catch unreachable;
67 resume b4_handle;
68 cancel b4_handle;
69 defer {
70 defer_b2 = true;
71 }
72 const value = await b3_handle;
73 @panic("unreachable");
74}
75
76async fn b3() i32 {
77 defer {
78 defer_b3 = true;
79 }
80 await (async b4() catch unreachable);
81 return 1234;
82}
83
84async fn b4() void {
85 defer {
86 defer_b4 = true;
87 }
88 suspend {
89 b4_handle = @handle();
90 }
91 suspend;
92}
test/stage1/behavior/cast.zig created+473
...@@ -0,0 +1,473 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5
6test "int to ptr cast" {
7 const x = usize(13);
8 const y = @intToPtr(*u8, x);
9 const z = @ptrToInt(y);
10 assertOrPanic(z == 13);
11}
12
13test "integer literal to pointer cast" {
14 const vga_mem = @intToPtr(*u16, 0xB8000);
15 assertOrPanic(@ptrToInt(vga_mem) == 0xB8000);
16}
17
18test "pointer reinterpret const float to int" {
19 const float: f64 = 5.99999999999994648725e-01;
20 const float_ptr = &float;
21 const int_ptr = @ptrCast(*const i32, float_ptr);
22 const int_val = int_ptr.*;
23 assertOrPanic(int_val == 858993411);
24}
25
26test "implicitly cast indirect pointer to maybe-indirect pointer" {
27 const S = struct {
28 const Self = @This();
29 x: u8,
30 fn constConst(p: *const *const Self) u8 {
31 return p.*.x;
32 }
33 fn maybeConstConst(p: ?*const *const Self) u8 {
34 return p.?.*.x;
35 }
36 fn constConstConst(p: *const *const *const Self) u8 {
37 return p.*.*.x;
38 }
39 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
40 return p.?.*.*.x;
41 }
42 };
43 const s = S{ .x = 42 };
44 const p = &s;
45 const q = &p;
46 const r = &q;
47 assertOrPanic(42 == S.constConst(q));
48 assertOrPanic(42 == S.maybeConstConst(q));
49 assertOrPanic(42 == S.constConstConst(r));
50 assertOrPanic(42 == S.maybeConstConstConst(r));
51}
52
53test "explicit cast from integer to error type" {
54 testCastIntToErr(error.ItBroke);
55 comptime testCastIntToErr(error.ItBroke);
56}
57fn testCastIntToErr(err: anyerror) void {
58 const x = @errorToInt(err);
59 const y = @intToError(x);
60 assertOrPanic(error.ItBroke == y);
61}
62
63test "peer resolve arrays of different size to const slice" {
64 assertOrPanic(mem.eql(u8, boolToStr(true), "true"));
65 assertOrPanic(mem.eql(u8, boolToStr(false), "false"));
66 comptime assertOrPanic(mem.eql(u8, boolToStr(true), "true"));
67 comptime assertOrPanic(mem.eql(u8, boolToStr(false), "false"));
68}
69fn boolToStr(b: bool) []const u8 {
70 return if (b) "true" else "false";
71}
72
73test "peer resolve array and const slice" {
74 testPeerResolveArrayConstSlice(true);
75 comptime testPeerResolveArrayConstSlice(true);
76}
77fn testPeerResolveArrayConstSlice(b: bool) void {
78 const value1 = if (b) "aoeu" else ([]const u8)("zz");
79 const value2 = if (b) ([]const u8)("zz") else "aoeu";
80 assertOrPanic(mem.eql(u8, value1, "aoeu"));
81 assertOrPanic(mem.eql(u8, value2, "zz"));
82}
83
84test "implicitly cast from T to anyerror!?T" {
85 castToOptionalTypeError(1);
86 comptime castToOptionalTypeError(1);
87}
88
89const A = struct {
90 a: i32,
91};
92fn castToOptionalTypeError(z: i32) void {
93 const x = i32(1);
94 const y: anyerror!?i32 = x;
95 assertOrPanic((try y).? == 1);
96
97 const f = z;
98 const g: anyerror!?i32 = f;
99
100 const a = A{ .a = z };
101 const b: anyerror!?A = a;
102 assertOrPanic((b catch unreachable).?.a == 1);
103}
104
105test "implicitly cast from int to anyerror!?T" {
106 implicitIntLitToOptional();
107 comptime implicitIntLitToOptional();
108}
109fn implicitIntLitToOptional() void {
110 const f: ?i32 = 1;
111 const g: anyerror!?i32 = 1;
112}
113
114test "return null from fn() anyerror!?&T" {
115 const a = returnNullFromOptionalTypeErrorRef();
116 const b = returnNullLitFromOptionalTypeErrorRef();
117 assertOrPanic((try a) == null and (try b) == null);
118}
119fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
120 const a: ?*A = null;
121 return a;
122}
123fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
124 return null;
125}
126
127test "peer type resolution: ?T and T" {
128 assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0);
129 assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3);
130 comptime {
131 assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0);
132 assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3);
133 }
134}
135fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
136 if (c) {
137 return if (b) null else usize(0);
138 }
139
140 return usize(3);
141}
142
143test "peer type resolution: [0]u8 and []const u8" {
144 assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
145 assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
146 comptime {
147 assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
148 assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
149 }
150}
151fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
152 if (a) {
153 return []const u8{};
154 }
155
156 return slice[0..1];
157}
158
159test "implicitly cast from [N]T to ?[]const T" {
160 assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi"));
161 comptime assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi"));
162}
163
164fn castToOptionalSlice() ?[]const u8 {
165 return "hi";
166}
167
168test "implicitly cast from [0]T to anyerror![]T" {
169 testCastZeroArrayToErrSliceMut();
170 comptime testCastZeroArrayToErrSliceMut();
171}
172
173fn testCastZeroArrayToErrSliceMut() void {
174 assertOrPanic((gimmeErrOrSlice() catch unreachable).len == 0);
175}
176
177fn gimmeErrOrSlice() anyerror![]u8 {
178 return []u8{};
179}
180
181test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
182 {
183 var data = "hi";
184 const slice = data[0..];
185 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
186 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
187 }
188 comptime {
189 var data = "hi";
190 const slice = data[0..];
191 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
192 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
193 }
194}
195fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
196 if (a) {
197 return []u8{};
198 }
199
200 return slice[0..1];
201}
202
203test "resolve undefined with integer" {
204 testResolveUndefWithInt(true, 1234);
205 comptime testResolveUndefWithInt(true, 1234);
206}
207fn testResolveUndefWithInt(b: bool, x: i32) void {
208 const value = if (b) x else undefined;
209 if (b) {
210 assertOrPanic(value == x);
211 }
212}
213
214test "implicit cast from &const [N]T to []const T" {
215 testCastConstArrayRefToConstSlice();
216 comptime testCastConstArrayRefToConstSlice();
217}
218
219fn testCastConstArrayRefToConstSlice() void {
220 const blah = "aoeu";
221 const const_array_ref = &blah;
222 assertOrPanic(@typeOf(const_array_ref) == *const [4]u8);
223 const slice: []const u8 = const_array_ref;
224 assertOrPanic(mem.eql(u8, slice, "aoeu"));
225}
226
227test "peer type resolution: error and [N]T" {
228 // TODO: implicit error!T to error!U where T can implicitly cast to U
229 //assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
230 //comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
231 assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
232 comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
233}
234
235//fn testPeerErrorAndArray(x: u8) error![]const u8 {
236// return switch (x) {
237// 0x00 => "OK",
238// else => error.BadValue,
239// };
240//}
241fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
242 return switch (x) {
243 0x00 => "OK",
244 0x01 => "OKK",
245 else => error.BadValue,
246 };
247}
248
249test "@floatToInt" {
250 testFloatToInts();
251 comptime testFloatToInts();
252}
253
254fn testFloatToInts() void {
255 const x = i32(1e4);
256 assertOrPanic(x == 10000);
257 const y = @floatToInt(i32, f32(1e4));
258 assertOrPanic(y == 10000);
259 expectFloatToInt(f16, 255.1, u8, 255);
260 expectFloatToInt(f16, 127.2, i8, 127);
261 expectFloatToInt(f16, -128.2, i8, -128);
262 expectFloatToInt(f32, 255.1, u8, 255);
263 expectFloatToInt(f32, 127.2, i8, 127);
264 expectFloatToInt(f32, -128.2, i8, -128);
265 expectFloatToInt(comptime_int, 1234, i16, 1234);
266}
267
268fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {
269 assertOrPanic(@floatToInt(I, f) == i);
270}
271
272test "cast u128 to f128 and back" {
273 comptime testCast128();
274 testCast128();
275}
276
277fn testCast128() void {
278 assertOrPanic(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
279}
280
281fn cast128Int(x: f128) u128 {
282 return @bitCast(u128, x);
283}
284
285fn cast128Float(x: u128) f128 {
286 return @bitCast(f128, x);
287}
288
289test "const slice widen cast" {
290 const bytes align(4) = []u8{
291 0x12,
292 0x12,
293 0x12,
294 0x12,
295 };
296
297 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
298 assertOrPanic(u32_value == 0x12121212);
299
300 assertOrPanic(@bitCast(u32, bytes) == 0x12121212);
301}
302
303test "single-item pointer of array to slice and to unknown length pointer" {
304 testCastPtrOfArrayToSliceAndPtr();
305 comptime testCastPtrOfArrayToSliceAndPtr();
306}
307
308fn testCastPtrOfArrayToSliceAndPtr() void {
309 var array = "aoeu";
310 const x: [*]u8 = &array;
311 x[0] += 1;
312 assertOrPanic(mem.eql(u8, array[0..], "boeu"));
313 const y: []u8 = &array;
314 y[0] += 1;
315 assertOrPanic(mem.eql(u8, array[0..], "coeu"));
316}
317
318test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
319 const window_name = [1][*]const u8{c"window name"};
320 const x: [*]const ?[*]const u8 = &window_name;
321 assertOrPanic(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
322}
323
324test "@intCast comptime_int" {
325 const result = @intCast(i32, 1234);
326 assertOrPanic(@typeOf(result) == i32);
327 assertOrPanic(result == 1234);
328}
329
330test "@floatCast comptime_int and comptime_float" {
331 {
332 const result = @floatCast(f16, 1234);
333 assertOrPanic(@typeOf(result) == f16);
334 assertOrPanic(result == 1234.0);
335 }
336 {
337 const result = @floatCast(f16, 1234.0);
338 assertOrPanic(@typeOf(result) == f16);
339 assertOrPanic(result == 1234.0);
340 }
341 {
342 const result = @floatCast(f32, 1234);
343 assertOrPanic(@typeOf(result) == f32);
344 assertOrPanic(result == 1234.0);
345 }
346 {
347 const result = @floatCast(f32, 1234.0);
348 assertOrPanic(@typeOf(result) == f32);
349 assertOrPanic(result == 1234.0);
350 }
351}
352
353test "comptime_int @intToFloat" {
354 {
355 const result = @intToFloat(f16, 1234);
356 assertOrPanic(@typeOf(result) == f16);
357 assertOrPanic(result == 1234.0);
358 }
359 {
360 const result = @intToFloat(f32, 1234);
361 assertOrPanic(@typeOf(result) == f32);
362 assertOrPanic(result == 1234.0);
363 }
364}
365
366test "@bytesToSlice keeps pointer alignment" {
367 var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
368 const numbers = @bytesToSlice(u32, bytes[0..]);
369 comptime assertOrPanic(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
370}
371
372test "@intCast i32 to u7" {
373 var x: u128 = maxInt(u128);
374 var y: i32 = 120;
375 var z = x >> @intCast(u7, y);
376 assertOrPanic(z == 0xff);
377}
378
379test "implicit cast undefined to optional" {
380 assertOrPanic(MakeType(void).getNull() == null);
381 assertOrPanic(MakeType(void).getNonNull() != null);
382}
383
384fn MakeType(comptime T: type) type {
385 return struct {
386 fn getNull() ?T {
387 return null;
388 }
389
390 fn getNonNull() ?T {
391 return T(undefined);
392 }
393 };
394}
395
396test "implicit cast from *[N]T to ?[*]T" {
397 var x: ?[*]u16 = null;
398 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
399
400 x = &y;
401 assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4]));
402 x.?[0] = 8;
403 y[3] = 6;
404 assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4]));
405}
406
407test "implicit cast from *T to ?*c_void" {
408 var a: u8 = 1;
409 incrementVoidPtrValue(&a);
410 std.debug.assertOrPanic(a == 2);
411}
412
413fn incrementVoidPtrValue(value: ?*c_void) void {
414 @ptrCast(*u8, value.?).* += 1;
415}
416
417test "implicit cast from [*]T to ?*c_void" {
418 var a = []u8{ 3, 2, 1 };
419 incrementVoidPtrArray(a[0..].ptr, 3);
420 assertOrPanic(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
421}
422
423fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
424 var n: usize = 0;
425 while (n < len) : (n += 1) {
426 @ptrCast([*]u8, array.?)[n] += 1;
427 }
428}
429
430test "*usize to *void" {
431 var i = usize(0);
432 var v = @ptrCast(*void, &i);
433 v.* = {};
434}
435
436test "compile time int to ptr of function" {
437 foobar(FUNCTION_CONSTANT);
438}
439
440pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
441pub const PFN_void = extern fn (*c_void) void;
442
443fn foobar(func: PFN_void) void {
444 std.debug.assertOrPanic(@ptrToInt(func) == maxInt(usize));
445}
446
447test "implicit ptr to *c_void" {
448 var a: u32 = 1;
449 var ptr: *c_void = &a;
450 var b: *u32 = @ptrCast(*u32, ptr);
451 assertOrPanic(b.* == 1);
452 var ptr2: ?*c_void = &a;
453 var c: *u32 = @ptrCast(*u32, ptr2.?);
454 assertOrPanic(c.* == 1);
455}
456
457test "@intCast to comptime_int" {
458 assertOrPanic(@intCast(comptime_int, 0) == 0);
459}
460
461test "implicit cast comptime numbers to any type when the value fits" {
462 const a: u64 = 255;
463 var b: u8 = a;
464 assertOrPanic(b == 255);
465}
466
467test "@intToEnum passed a comptime_int to an enum with one item" {
468 const E = enum {
469 A,
470 };
471 const x = @intToEnum(E, 0);
472 assertOrPanic(x == E.A);
473}
test/stage1/behavior/const_slice_child.zig created+45
...@@ -0,0 +1,45 @@
1const debug = @import("std").debug;
2const assertOrPanic = debug.assertOrPanic;
3
4var argv: [*]const [*]const u8 = undefined;
5
6test "const slice child" {
7 const strs = ([][*]const u8){
8 c"one",
9 c"two",
10 c"three",
11 };
12 // TODO this should implicitly cast
13 argv = @ptrCast([*]const [*]const u8, &strs);
14 bar(strs.len);
15}
16
17fn foo(args: [][]const u8) void {
18 assertOrPanic(args.len == 3);
19 assertOrPanic(streql(args[0], "one"));
20 assertOrPanic(streql(args[1], "two"));
21 assertOrPanic(streql(args[2], "three"));
22}
23
24fn bar(argc: usize) void {
25 const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable;
26 for (args) |_, i| {
27 const ptr = argv[i];
28 args[i] = ptr[0..strlen(ptr)];
29 }
30 foo(args);
31}
32
33fn strlen(ptr: [*]const u8) usize {
34 var count: usize = 0;
35 while (ptr[count] != 0) : (count += 1) {}
36 return count;
37}
38
39fn streql(a: []const u8, b: []const u8) bool {
40 if (a.len != b.len) return false;
41 for (a) |item, index| {
42 if (b[index] != item) return false;
43 }
44 return true;
45}
test/stage1/behavior/coroutine_await_struct.zig created+47
...@@ -0,0 +1,47 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assertOrPanic = std.debug.assertOrPanic;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: promise = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 var da = std.heap.DirectAllocator.init();
14 defer da.deinit();
15
16 await_seq('a');
17 const p = async<&da.allocator> await_amain() catch unreachable;
18 await_seq('f');
19 resume await_a_promise;
20 await_seq('i');
21 assertOrPanic(await_final_result.x == 1234);
22 assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi"));
23}
24async fn await_amain() void {
25 await_seq('b');
26 const p = async await_another() catch unreachable;
27 await_seq('e');
28 await_final_result = await p;
29 await_seq('h');
30}
31async fn await_another() Foo {
32 await_seq('c');
33 suspend {
34 await_seq('d');
35 await_a_promise = @handle();
36 }
37 await_seq('g');
38 return Foo{ .x = 1234 };
39}
40
41var await_points = []u8{0} ** "abcdefghi".len;
42var await_seq_index: usize = 0;
43
44fn await_seq(c: u8) void {
45 await_points[await_seq_index] = c;
46 await_seq_index += 1;
47}
test/stage1/behavior/coroutines.zig created+258
...@@ -0,0 +1,258 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assertOrPanic = std.debug.assertOrPanic;
4
5var x: i32 = 1;
6
7test "create a coroutine and cancel it" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = try async<&da.allocator> simpleAsyncFn();
12 comptime assertOrPanic(@typeOf(p) == promise->void);
13 cancel p;
14 assertOrPanic(x == 2);
15}
16async fn simpleAsyncFn() void {
17 x += 1;
18 suspend;
19 x += 1;
20}
21
22test "coroutine suspend, resume, cancel" {
23 var da = std.heap.DirectAllocator.init();
24 defer da.deinit();
25
26 seq('a');
27 const p = try async<&da.allocator> testAsyncSeq();
28 seq('c');
29 resume p;
30 seq('f');
31 cancel p;
32 seq('g');
33
34 assertOrPanic(std.mem.eql(u8, points, "abcdefg"));
35}
36async fn testAsyncSeq() void {
37 defer seq('e');
38
39 seq('b');
40 suspend;
41 seq('d');
42}
43var points = []u8{0} ** "abcdefg".len;
44var index: usize = 0;
45
46fn seq(c: u8) void {
47 points[index] = c;
48 index += 1;
49}
50
51test "coroutine suspend with block" {
52 var da = std.heap.DirectAllocator.init();
53 defer da.deinit();
54
55 const p = try async<&da.allocator> testSuspendBlock();
56 std.debug.assertOrPanic(!result);
57 resume a_promise;
58 std.debug.assertOrPanic(result);
59 cancel p;
60}
61
62var a_promise: promise = undefined;
63var result = false;
64async fn testSuspendBlock() void {
65 suspend {
66 comptime assertOrPanic(@typeOf(@handle()) == promise->void);
67 a_promise = @handle();
68 }
69
70 //Test to make sure that @handle() works as advertised (issue #1296)
71 //var our_handle: promise = @handle();
72 assertOrPanic(a_promise == @handle());
73
74 result = true;
75}
76
77var await_a_promise: promise = undefined;
78var await_final_result: i32 = 0;
79
80test "coroutine await" {
81 var da = std.heap.DirectAllocator.init();
82 defer da.deinit();
83
84 await_seq('a');
85 const p = async<&da.allocator> await_amain() catch unreachable;
86 await_seq('f');
87 resume await_a_promise;
88 await_seq('i');
89 assertOrPanic(await_final_result == 1234);
90 assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi"));
91}
92async fn await_amain() void {
93 await_seq('b');
94 const p = async await_another() catch unreachable;
95 await_seq('e');
96 await_final_result = await p;
97 await_seq('h');
98}
99async fn await_another() i32 {
100 await_seq('c');
101 suspend {
102 await_seq('d');
103 await_a_promise = @handle();
104 }
105 await_seq('g');
106 return 1234;
107}
108
109var await_points = []u8{0} ** "abcdefghi".len;
110var await_seq_index: usize = 0;
111
112fn await_seq(c: u8) void {
113 await_points[await_seq_index] = c;
114 await_seq_index += 1;
115}
116
117var early_final_result: i32 = 0;
118
119test "coroutine await early return" {
120 var da = std.heap.DirectAllocator.init();
121 defer da.deinit();
122
123 early_seq('a');
124 const p = async<&da.allocator> early_amain() catch @panic("out of memory");
125 early_seq('f');
126 assertOrPanic(early_final_result == 1234);
127 assertOrPanic(std.mem.eql(u8, early_points, "abcdef"));
128}
129async fn early_amain() void {
130 early_seq('b');
131 const p = async early_another() catch @panic("out of memory");
132 early_seq('d');
133 early_final_result = await p;
134 early_seq('e');
135}
136async fn early_another() i32 {
137 early_seq('c');
138 return 1234;
139}
140
141var early_points = []u8{0} ** "abcdef".len;
142var early_seq_index: usize = 0;
143
144fn early_seq(c: u8) void {
145 early_points[early_seq_index] = c;
146 early_seq_index += 1;
147}
148
149test "coro allocation failure" {
150 var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0);
151 if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) {
152 @panic("expected allocation failure");
153 } else |err| switch (err) {
154 error.OutOfMemory => {},
155 }
156}
157async fn asyncFuncThatNeverGetsRun() void {
158 @panic("coro frame allocation should fail");
159}
160
161test "async function with dot syntax" {
162 const S = struct {
163 var y: i32 = 1;
164 async fn foo() void {
165 y += 1;
166 suspend;
167 }
168 };
169 var da = std.heap.DirectAllocator.init();
170 defer da.deinit();
171 const p = try async<&da.allocator> S.foo();
172 cancel p;
173 assertOrPanic(S.y == 2);
174}
175
176test "async fn pointer in a struct field" {
177 var data: i32 = 1;
178 const Foo = struct {
179 bar: async<*std.mem.Allocator> fn (*i32) void,
180 };
181 var foo = Foo{ .bar = simpleAsyncFn2 };
182 var da = std.heap.DirectAllocator.init();
183 defer da.deinit();
184 const p = (async<&da.allocator> foo.bar(&data)) catch unreachable;
185 assertOrPanic(data == 2);
186 cancel p;
187 assertOrPanic(data == 4);
188}
189async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
190 defer y.* += 2;
191 y.* += 1;
192 suspend;
193}
194
195test "async fn with inferred error set" {
196 var da = std.heap.DirectAllocator.init();
197 defer da.deinit();
198 const p = (async<&da.allocator> failing()) catch unreachable;
199 resume p;
200 cancel p;
201}
202
203async fn failing() !void {
204 suspend;
205 return error.Fail;
206}
207
208test "error return trace across suspend points - early return" {
209 const p = nonFailing();
210 resume p;
211 var da = std.heap.DirectAllocator.init();
212 defer da.deinit();
213 const p2 = try async<&da.allocator> printTrace(p);
214 cancel p2;
215}
216
217test "error return trace across suspend points - async return" {
218 const p = nonFailing();
219 const p2 = try async<std.debug.global_allocator> printTrace(p);
220 resume p;
221 cancel p2;
222}
223
224fn nonFailing() (promise->anyerror!void) {
225 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
226}
227async fn suspendThenFail() anyerror!void {
228 suspend;
229 return error.Fail;
230}
231async fn printTrace(p: promise->(anyerror!void)) void {
232 (await p) catch |e| {
233 std.debug.assertOrPanic(e == error.Fail);
234 if (@errorReturnTrace()) |trace| {
235 assertOrPanic(trace.index == 1);
236 } else switch (builtin.mode) {
237 builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
238 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
239 }
240 };
241}
242
243test "break from suspend" {
244 var buf: [500]u8 = undefined;
245 var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
246 var my_result: i32 = 1;
247 const p = try async<a> testBreakFromSuspend(&my_result);
248 cancel p;
249 std.debug.assertOrPanic(my_result == 2);
250}
251async fn testBreakFromSuspend(my_result: *i32) void {
252 suspend {
253 resume @handle();
254 }
255 my_result.* += 1;
256 suspend;
257 my_result.* += 1;
258}
test/stage1/behavior/defer.zig created+78
...@@ -0,0 +1,78 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3var result: [3]u8 = undefined;
4var index: usize = undefined;
5
6fn runSomeErrorDefers(x: bool) !bool {
7 index = 0;
8 defer {
9 result[index] = 'a';
10 index += 1;
11 }
12 errdefer {
13 result[index] = 'b';
14 index += 1;
15 }
16 defer {
17 result[index] = 'c';
18 index += 1;
19 }
20 return if (x) x else error.FalseNotAllowed;
21}
22
23test "mixing normal and error defers" {
24 assertOrPanic(runSomeErrorDefers(true) catch unreachable);
25 assertOrPanic(result[0] == 'c');
26 assertOrPanic(result[1] == 'a');
27
28 const ok = runSomeErrorDefers(false) catch |err| x: {
29 assertOrPanic(err == error.FalseNotAllowed);
30 break :x true;
31 };
32 assertOrPanic(ok);
33 assertOrPanic(result[0] == 'c');
34 assertOrPanic(result[1] == 'b');
35 assertOrPanic(result[2] == 'a');
36}
37
38test "break and continue inside loop inside defer expression" {
39 testBreakContInDefer(10);
40 comptime testBreakContInDefer(10);
41}
42
43fn testBreakContInDefer(x: usize) void {
44 defer {
45 var i: usize = 0;
46 while (i < x) : (i += 1) {
47 if (i < 5) continue;
48 if (i == 5) break;
49 }
50 assertOrPanic(i == 5);
51 }
52}
53
54test "defer and labeled break" {
55 var i = usize(0);
56
57 blk: {
58 defer i += 1;
59 break :blk;
60 }
61
62 assertOrPanic(i == 1);
63}
64
65test "errdefer does not apply to fn inside fn" {
66 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assertOrPanic(e == error.Bad);
67}
68
69fn testNestedFnErrDefer() anyerror!void {
70 var a: i32 = 0;
71 errdefer a += 1;
72 const S = struct {
73 fn baz() anyerror {
74 return error.Bad;
75 }
76 };
77 return S.baz();
78}
test/stage1/behavior/enum.zig created+894
...@@ -0,0 +1,894 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4test "enum type" {
5 const foo1 = Foo{ .One = 13 };
6 const foo2 = Foo{
7 .Two = Point{
8 .x = 1234,
9 .y = 5678,
10 },
11 };
12 const bar = Bar.B;
13
14 assertOrPanic(bar == Bar.B);
15 assertOrPanic(@memberCount(Foo) == 3);
16 assertOrPanic(@memberCount(Bar) == 4);
17 assertOrPanic(@sizeOf(Foo) == @sizeOf(FooNoVoid));
18 assertOrPanic(@sizeOf(Bar) == 1);
19}
20
21test "enum as return value" {
22 switch (returnAnInt(13)) {
23 Foo.One => |value| assertOrPanic(value == 13),
24 else => unreachable,
25 }
26}
27
28const Point = struct {
29 x: u64,
30 y: u64,
31};
32const Foo = union(enum) {
33 One: i32,
34 Two: Point,
35 Three: void,
36};
37const FooNoVoid = union(enum) {
38 One: i32,
39 Two: Point,
40};
41const Bar = enum {
42 A,
43 B,
44 C,
45 D,
46};
47
48fn returnAnInt(x: i32) Foo {
49 return Foo{ .One = x };
50}
51
52test "constant enum with payload" {
53 var empty = AnEnumWithPayload{ .Empty = {} };
54 var full = AnEnumWithPayload{ .Full = 13 };
55 shouldBeEmpty(empty);
56 shouldBeNotEmpty(full);
57}
58
59fn shouldBeEmpty(x: AnEnumWithPayload) void {
60 switch (x) {
61 AnEnumWithPayload.Empty => {},
62 else => unreachable,
63 }
64}
65
66fn shouldBeNotEmpty(x: AnEnumWithPayload) void {
67 switch (x) {
68 AnEnumWithPayload.Empty => unreachable,
69 else => {},
70 }
71}
72
73const AnEnumWithPayload = union(enum) {
74 Empty: void,
75 Full: i32,
76};
77
78const Number = enum {
79 Zero,
80 One,
81 Two,
82 Three,
83 Four,
84};
85
86test "enum to int" {
87 shouldEqual(Number.Zero, 0);
88 shouldEqual(Number.One, 1);
89 shouldEqual(Number.Two, 2);
90 shouldEqual(Number.Three, 3);
91 shouldEqual(Number.Four, 4);
92}
93
94fn shouldEqual(n: Number, expected: u3) void {
95 assertOrPanic(@enumToInt(n) == expected);
96}
97
98test "int to enum" {
99 testIntToEnumEval(3);
100}
101fn testIntToEnumEval(x: i32) void {
102 assertOrPanic(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
103}
104const IntToEnumNumber = enum {
105 Zero,
106 One,
107 Two,
108 Three,
109 Four,
110};
111
112test "@tagName" {
113 assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114 comptime assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
115}
116
117fn testEnumTagNameBare(n: BareNumber) []const u8 {
118 return @tagName(n);
119}
120
121const BareNumber = enum {
122 One,
123 Two,
124 Three,
125};
126
127test "enum alignment" {
128 comptime {
129 assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
130 assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf(u64));
131 }
132}
133
134const AlignTestEnum = union(enum) {
135 A: [9]u8,
136 B: u64,
137};
138
139const ValueCount1 = enum {
140 I0,
141};
142const ValueCount2 = enum {
143 I0,
144 I1,
145};
146const ValueCount256 = enum {
147 I0,
148 I1,
149 I2,
150 I3,
151 I4,
152 I5,
153 I6,
154 I7,
155 I8,
156 I9,
157 I10,
158 I11,
159 I12,
160 I13,
161 I14,
162 I15,
163 I16,
164 I17,
165 I18,
166 I19,
167 I20,
168 I21,
169 I22,
170 I23,
171 I24,
172 I25,
173 I26,
174 I27,
175 I28,
176 I29,
177 I30,
178 I31,
179 I32,
180 I33,
181 I34,
182 I35,
183 I36,
184 I37,
185 I38,
186 I39,
187 I40,
188 I41,
189 I42,
190 I43,
191 I44,
192 I45,
193 I46,
194 I47,
195 I48,
196 I49,
197 I50,
198 I51,
199 I52,
200 I53,
201 I54,
202 I55,
203 I56,
204 I57,
205 I58,
206 I59,
207 I60,
208 I61,
209 I62,
210 I63,
211 I64,
212 I65,
213 I66,
214 I67,
215 I68,
216 I69,
217 I70,
218 I71,
219 I72,
220 I73,
221 I74,
222 I75,
223 I76,
224 I77,
225 I78,
226 I79,
227 I80,
228 I81,
229 I82,
230 I83,
231 I84,
232 I85,
233 I86,
234 I87,
235 I88,
236 I89,
237 I90,
238 I91,
239 I92,
240 I93,
241 I94,
242 I95,
243 I96,
244 I97,
245 I98,
246 I99,
247 I100,
248 I101,
249 I102,
250 I103,
251 I104,
252 I105,
253 I106,
254 I107,
255 I108,
256 I109,
257 I110,
258 I111,
259 I112,
260 I113,
261 I114,
262 I115,
263 I116,
264 I117,
265 I118,
266 I119,
267 I120,
268 I121,
269 I122,
270 I123,
271 I124,
272 I125,
273 I126,
274 I127,
275 I128,
276 I129,
277 I130,
278 I131,
279 I132,
280 I133,
281 I134,
282 I135,
283 I136,
284 I137,
285 I138,
286 I139,
287 I140,
288 I141,
289 I142,
290 I143,
291 I144,
292 I145,
293 I146,
294 I147,
295 I148,
296 I149,
297 I150,
298 I151,
299 I152,
300 I153,
301 I154,
302 I155,
303 I156,
304 I157,
305 I158,
306 I159,
307 I160,
308 I161,
309 I162,
310 I163,
311 I164,
312 I165,
313 I166,
314 I167,
315 I168,
316 I169,
317 I170,
318 I171,
319 I172,
320 I173,
321 I174,
322 I175,
323 I176,
324 I177,
325 I178,
326 I179,
327 I180,
328 I181,
329 I182,
330 I183,
331 I184,
332 I185,
333 I186,
334 I187,
335 I188,
336 I189,
337 I190,
338 I191,
339 I192,
340 I193,
341 I194,
342 I195,
343 I196,
344 I197,
345 I198,
346 I199,
347 I200,
348 I201,
349 I202,
350 I203,
351 I204,
352 I205,
353 I206,
354 I207,
355 I208,
356 I209,
357 I210,
358 I211,
359 I212,
360 I213,
361 I214,
362 I215,
363 I216,
364 I217,
365 I218,
366 I219,
367 I220,
368 I221,
369 I222,
370 I223,
371 I224,
372 I225,
373 I226,
374 I227,
375 I228,
376 I229,
377 I230,
378 I231,
379 I232,
380 I233,
381 I234,
382 I235,
383 I236,
384 I237,
385 I238,
386 I239,
387 I240,
388 I241,
389 I242,
390 I243,
391 I244,
392 I245,
393 I246,
394 I247,
395 I248,
396 I249,
397 I250,
398 I251,
399 I252,
400 I253,
401 I254,
402 I255,
403};
404const ValueCount257 = enum {
405 I0,
406 I1,
407 I2,
408 I3,
409 I4,
410 I5,
411 I6,
412 I7,
413 I8,
414 I9,
415 I10,
416 I11,
417 I12,
418 I13,
419 I14,
420 I15,
421 I16,
422 I17,
423 I18,
424 I19,
425 I20,
426 I21,
427 I22,
428 I23,
429 I24,
430 I25,
431 I26,
432 I27,
433 I28,
434 I29,
435 I30,
436 I31,
437 I32,
438 I33,
439 I34,
440 I35,
441 I36,
442 I37,
443 I38,
444 I39,
445 I40,
446 I41,
447 I42,
448 I43,
449 I44,
450 I45,
451 I46,
452 I47,
453 I48,
454 I49,
455 I50,
456 I51,
457 I52,
458 I53,
459 I54,
460 I55,
461 I56,
462 I57,
463 I58,
464 I59,
465 I60,
466 I61,
467 I62,
468 I63,
469 I64,
470 I65,
471 I66,
472 I67,
473 I68,
474 I69,
475 I70,
476 I71,
477 I72,
478 I73,
479 I74,
480 I75,
481 I76,
482 I77,
483 I78,
484 I79,
485 I80,
486 I81,
487 I82,
488 I83,
489 I84,
490 I85,
491 I86,
492 I87,
493 I88,
494 I89,
495 I90,
496 I91,
497 I92,
498 I93,
499 I94,
500 I95,
501 I96,
502 I97,
503 I98,
504 I99,
505 I100,
506 I101,
507 I102,
508 I103,
509 I104,
510 I105,
511 I106,
512 I107,
513 I108,
514 I109,
515 I110,
516 I111,
517 I112,
518 I113,
519 I114,
520 I115,
521 I116,
522 I117,
523 I118,
524 I119,
525 I120,
526 I121,
527 I122,
528 I123,
529 I124,
530 I125,
531 I126,
532 I127,
533 I128,
534 I129,
535 I130,
536 I131,
537 I132,
538 I133,
539 I134,
540 I135,
541 I136,
542 I137,
543 I138,
544 I139,
545 I140,
546 I141,
547 I142,
548 I143,
549 I144,
550 I145,
551 I146,
552 I147,
553 I148,
554 I149,
555 I150,
556 I151,
557 I152,
558 I153,
559 I154,
560 I155,
561 I156,
562 I157,
563 I158,
564 I159,
565 I160,
566 I161,
567 I162,
568 I163,
569 I164,
570 I165,
571 I166,
572 I167,
573 I168,
574 I169,
575 I170,
576 I171,
577 I172,
578 I173,
579 I174,
580 I175,
581 I176,
582 I177,
583 I178,
584 I179,
585 I180,
586 I181,
587 I182,
588 I183,
589 I184,
590 I185,
591 I186,
592 I187,
593 I188,
594 I189,
595 I190,
596 I191,
597 I192,
598 I193,
599 I194,
600 I195,
601 I196,
602 I197,
603 I198,
604 I199,
605 I200,
606 I201,
607 I202,
608 I203,
609 I204,
610 I205,
611 I206,
612 I207,
613 I208,
614 I209,
615 I210,
616 I211,
617 I212,
618 I213,
619 I214,
620 I215,
621 I216,
622 I217,
623 I218,
624 I219,
625 I220,
626 I221,
627 I222,
628 I223,
629 I224,
630 I225,
631 I226,
632 I227,
633 I228,
634 I229,
635 I230,
636 I231,
637 I232,
638 I233,
639 I234,
640 I235,
641 I236,
642 I237,
643 I238,
644 I239,
645 I240,
646 I241,
647 I242,
648 I243,
649 I244,
650 I245,
651 I246,
652 I247,
653 I248,
654 I249,
655 I250,
656 I251,
657 I252,
658 I253,
659 I254,
660 I255,
661 I256,
662};
663
664test "enum sizes" {
665 comptime {
666 assertOrPanic(@sizeOf(ValueCount1) == 0);
667 assertOrPanic(@sizeOf(ValueCount2) == 1);
668 assertOrPanic(@sizeOf(ValueCount256) == 1);
669 assertOrPanic(@sizeOf(ValueCount257) == 2);
670 }
671}
672
673const Small2 = enum(u2) {
674 One,
675 Two,
676};
677const Small = enum(u2) {
678 One,
679 Two,
680 Three,
681 Four,
682};
683
684test "set enum tag type" {
685 {
686 var x = Small.One;
687 x = Small.Two;
688 comptime assertOrPanic(@TagType(Small) == u2);
689 }
690 {
691 var x = Small2.One;
692 x = Small2.Two;
693 comptime assertOrPanic(@TagType(Small2) == u2);
694 }
695}
696
697const A = enum(u3) {
698 One,
699 Two,
700 Three,
701 Four,
702 One2,
703 Two2,
704 Three2,
705 Four2,
706};
707
708const B = enum(u3) {
709 One3,
710 Two3,
711 Three3,
712 Four3,
713 One23,
714 Two23,
715 Three23,
716 Four23,
717};
718
719const C = enum(u2) {
720 One4,
721 Two4,
722 Three4,
723 Four4,
724};
725
726const BitFieldOfEnums = packed struct {
727 a: A,
728 b: B,
729 c: C,
730};
731
732const bit_field_1 = BitFieldOfEnums{
733 .a = A.Two,
734 .b = B.Three3,
735 .c = C.Four4,
736};
737
738test "bit field access with enum fields" {
739 var data = bit_field_1;
740 assertOrPanic(getA(&data) == A.Two);
741 assertOrPanic(getB(&data) == B.Three3);
742 assertOrPanic(getC(&data) == C.Four4);
743 comptime assertOrPanic(@sizeOf(BitFieldOfEnums) == 1);
744
745 data.b = B.Four3;
746 assertOrPanic(data.b == B.Four3);
747
748 data.a = A.Three;
749 assertOrPanic(data.a == A.Three);
750 assertOrPanic(data.b == B.Four3);
751}
752
753fn getA(data: *const BitFieldOfEnums) A {
754 return data.a;
755}
756
757fn getB(data: *const BitFieldOfEnums) B {
758 return data.b;
759}
760
761fn getC(data: *const BitFieldOfEnums) C {
762 return data.c;
763}
764
765test "casting enum to its tag type" {
766 testCastEnumToTagType(Small2.Two);
767 comptime testCastEnumToTagType(Small2.Two);
768}
769
770fn testCastEnumToTagType(value: Small2) void {
771 assertOrPanic(@enumToInt(value) == 1);
772}
773
774const MultipleChoice = enum(u32) {
775 A = 20,
776 B = 40,
777 C = 60,
778 D = 1000,
779};
780
781test "enum with specified tag values" {
782 testEnumWithSpecifiedTagValues(MultipleChoice.C);
783 comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
784}
785
786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
787 assertOrPanic(@enumToInt(x) == 60);
788 assertOrPanic(1234 == switch (x) {
789 MultipleChoice.A => 1,
790 MultipleChoice.B => 2,
791 MultipleChoice.C => u32(1234),
792 MultipleChoice.D => 4,
793 });
794}
795
796const MultipleChoice2 = enum(u32) {
797 Unspecified1,
798 A = 20,
799 Unspecified2,
800 B = 40,
801 Unspecified3,
802 C = 60,
803 Unspecified4,
804 D = 1000,
805 Unspecified5,
806};
807
808test "enum with specified and unspecified tag values" {
809 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
810 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
811}
812
813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
814 assertOrPanic(@enumToInt(x) == 1000);
815 assertOrPanic(1234 == switch (x) {
816 MultipleChoice2.A => 1,
817 MultipleChoice2.B => 2,
818 MultipleChoice2.C => 3,
819 MultipleChoice2.D => u32(1234),
820 MultipleChoice2.Unspecified1 => 5,
821 MultipleChoice2.Unspecified2 => 6,
822 MultipleChoice2.Unspecified3 => 7,
823 MultipleChoice2.Unspecified4 => 8,
824 MultipleChoice2.Unspecified5 => 9,
825 });
826}
827
828test "cast integer literal to enum" {
829 assertOrPanic(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 assertOrPanic(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
831}
832
833const EnumWithOneMember = enum {
834 Eof,
835};
836
837fn doALoopThing(id: EnumWithOneMember) void {
838 while (true) {
839 if (id == EnumWithOneMember.Eof) {
840 break;
841 }
842 @compileError("above if condition should be comptime");
843 }
844}
845
846test "comparison operator on enum with one member is comptime known" {
847 doALoopThing(EnumWithOneMember.Eof);
848}
849
850const State = enum {
851 Start,
852};
853test "switch on enum with one member is comptime known" {
854 var state = State.Start;
855 switch (state) {
856 State.Start => return,
857 }
858 @compileError("analysis should not reach here");
859}
860
861const EnumWithTagValues = enum(u4) {
862 A = 1 << 0,
863 B = 1 << 1,
864 C = 1 << 2,
865 D = 1 << 3,
866};
867test "enum with tag values don't require parens" {
868 assertOrPanic(@enumToInt(EnumWithTagValues.C) == 0b0100);
869}
870
871test "enum with 1 field but explicit tag type should still have the tag type" {
872 const Enum = enum(u8) {
873 B = 2,
874 };
875 comptime @import("std").debug.assertOrPanic(@sizeOf(Enum) == @sizeOf(u8));
876}
877
878test "empty extern enum with members" {
879 const E = extern enum {
880 A,
881 B,
882 C,
883 };
884 assertOrPanic(@sizeOf(E) == @sizeOf(c_int));
885}
886
887test "tag name with assigned enum values" {
888 const LocalFoo = enum {
889 A = 1,
890 B = 0,
891 };
892 var b = LocalFoo.B;
893 assertOrPanic(mem.eql(u8, @tagName(b), "B"));
894}
test/stage1/behavior/enum_with_members.zig created+27
...@@ -0,0 +1,27 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3const fmt = @import("std").fmt;
4
5const ET = union(enum) {
6 SINT: i32,
7 UINT: u32,
8
9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
10 return switch (a.*) {
11 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
13 };
14 }
15};
16
17test "enum with members" {
18 const a = ET{ .SINT = -42 };
19 const b = ET{ .UINT = 42 };
20 var buf: [20]u8 = undefined;
21
22 assertOrPanic((a.print(buf[0..]) catch unreachable) == 3);
23 assertOrPanic(mem.eql(u8, buf[0..3], "-42"));
24
25 assertOrPanic((b.print(buf[0..]) catch unreachable) == 2);
26 assertOrPanic(mem.eql(u8, buf[0..2], "42"));
27}
test/stage1/behavior/error.zig created+332
...@@ -0,0 +1,332 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const assertError = std.debug.assertError;
4const mem = std.mem;
5const builtin = @import("builtin");
6
7pub fn foo() anyerror!i32 {
8 const x = try bar();
9 return x + 1;
10}
11
12pub fn bar() anyerror!i32 {
13 return 13;
14}
15
16pub fn baz() anyerror!i32 {
17 const y = foo() catch 1234;
18 return y + 1;
19}
20
21test "error wrapping" {
22 assertOrPanic((baz() catch unreachable) == 15);
23}
24
25fn gimmeItBroke() []const u8 {
26 return @errorName(error.ItBroke);
27}
28
29test "@errorName" {
30 assertOrPanic(mem.eql(u8, @errorName(error.AnError), "AnError"));
31 assertOrPanic(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
32}
33
34test "error values" {
35 const a = @errorToInt(error.err1);
36 const b = @errorToInt(error.err2);
37 assertOrPanic(a != b);
38}
39
40test "redefinition of error values allowed" {
41 shouldBeNotEqual(error.AnError, error.SecondError);
42}
43fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
44 if (a == b) unreachable;
45}
46
47test "error binary operator" {
48 const a = errBinaryOperatorG(true) catch 3;
49 const b = errBinaryOperatorG(false) catch 3;
50 assertOrPanic(a == 3);
51 assertOrPanic(b == 10);
52}
53fn errBinaryOperatorG(x: bool) anyerror!isize {
54 return if (x) error.ItBroke else isize(10);
55}
56
57test "unwrap simple value from error" {
58 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
59 assertOrPanic(i == 13);
60}
61fn unwrapSimpleValueFromErrorDo() anyerror!isize {
62 return 13;
63}
64
65test "error return in assignment" {
66 doErrReturnInAssignment() catch unreachable;
67}
68
69fn doErrReturnInAssignment() anyerror!void {
70 var x: i32 = undefined;
71 x = try makeANonErr();
72}
73
74fn makeANonErr() anyerror!i32 {
75 return 1;
76}
77
78test "error union type " {
79 testErrorUnionType();
80 comptime testErrorUnionType();
81}
82
83fn testErrorUnionType() void {
84 const x: anyerror!i32 = 1234;
85 if (x) |value| assertOrPanic(value == 1234) else |_| unreachable;
86 assertOrPanic(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
87 assertOrPanic(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
88 assertOrPanic(@typeOf(x).ErrorSet == anyerror);
89}
90
91test "error set type" {
92 testErrorSetType();
93 comptime testErrorSetType();
94}
95
96const MyErrSet = error{
97 OutOfMemory,
98 FileNotFound,
99};
100
101fn testErrorSetType() void {
102 assertOrPanic(@memberCount(MyErrSet) == 2);
103
104 const a: MyErrSet!i32 = 5678;
105 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
106
107 if (a) |value| assertOrPanic(value == 5678) else |err| switch (err) {
108 error.OutOfMemory => unreachable,
109 error.FileNotFound => unreachable,
110 }
111}
112
113test "explicit error set cast" {
114 testExplicitErrorSetCast(Set1.A);
115 comptime testExplicitErrorSetCast(Set1.A);
116}
117
118const Set1 = error{
119 A,
120 B,
121};
122const Set2 = error{
123 A,
124 C,
125};
126
127fn testExplicitErrorSetCast(set1: Set1) void {
128 var x = @errSetCast(Set2, set1);
129 var y = @errSetCast(Set1, x);
130 assertOrPanic(y == error.A);
131}
132
133test "comptime test error for empty error set" {
134 testComptimeTestErrorEmptySet(1234);
135 comptime testComptimeTestErrorEmptySet(1234);
136}
137
138const EmptyErrorSet = error{};
139
140fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
141 if (x) |v| assertOrPanic(v == 1234) else |err| @compileError("bad");
142}
143
144test "syntax: optional operator in front of error union operator" {
145 comptime {
146 assertOrPanic(?(anyerror!i32) == ?(anyerror!i32));
147 }
148}
149
150test "comptime err to int of error set with only 1 possible value" {
151 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
153}
154fn testErrToIntWithOnePossibleValue(
155 x: error{A},
156 comptime value: u32,
157) void {
158 if (@errorToInt(x) != value) {
159 @compileError("bad");
160 }
161}
162
163test "error union peer type resolution" {
164 testErrorUnionPeerTypeResolution(1);
165}
166
167fn testErrorUnionPeerTypeResolution(x: i32) void {
168 const y = switch (x) {
169 1 => bar_1(),
170 2 => baz_1(),
171 else => quux_1(),
172 };
173 if (y) |_| {
174 @panic("expected error");
175 } else |e| {
176 assertOrPanic(e == error.A);
177 }
178}
179
180fn bar_1() anyerror {
181 return error.A;
182}
183
184fn baz_1() !i32 {
185 return error.B;
186}
187
188fn quux_1() !i32 {
189 return error.C;
190}
191
192test "error: fn returning empty error set can be passed as fn returning any error" {
193 entry();
194 comptime entry();
195}
196
197fn entry() void {
198 foo2(bar2);
199}
200
201fn foo2(f: fn () anyerror!void) void {
202 const x = f();
203}
204
205fn bar2() (error{}!void) {}
206
207test "error: Zero sized error set returned with value payload crash" {
208 _ = foo3(0);
209 _ = comptime foo3(0);
210}
211
212const Error = error{};
213fn foo3(b: usize) Error!usize {
214 return b;
215}
216
217test "error: Infer error set from literals" {
218 _ = nullLiteral("n") catch |err| handleErrors(err);
219 _ = floatLiteral("n") catch |err| handleErrors(err);
220 _ = intLiteral("n") catch |err| handleErrors(err);
221 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
222 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
223 _ = comptime intLiteral("n") catch |err| handleErrors(err);
224}
225
226fn handleErrors(err: var) noreturn {
227 switch (err) {
228 error.T => {},
229 }
230
231 unreachable;
232}
233
234fn nullLiteral(str: []const u8) !?i64 {
235 if (str[0] == 'n') return null;
236
237 return error.T;
238}
239
240fn floatLiteral(str: []const u8) !?f64 {
241 if (str[0] == 'n') return 1.0;
242
243 return error.T;
244}
245
246fn intLiteral(str: []const u8) !?i64 {
247 if (str[0] == 'n') return 1;
248
249 return error.T;
250}
251
252test "nested error union function call in optional unwrap" {
253 const S = struct {
254 const Foo = struct {
255 a: i32,
256 };
257
258 fn errorable() !i32 {
259 var x: Foo = (try getFoo()) orelse return error.Other;
260 return x.a;
261 }
262
263 fn errorable2() !i32 {
264 var x: Foo = (try getFoo2()) orelse return error.Other;
265 return x.a;
266 }
267
268 fn errorable3() !i32 {
269 var x: Foo = (try getFoo3()) orelse return error.Other;
270 return x.a;
271 }
272
273 fn getFoo() anyerror!?Foo {
274 return Foo{ .a = 1234 };
275 }
276
277 fn getFoo2() anyerror!?Foo {
278 return error.Failure;
279 }
280
281 fn getFoo3() anyerror!?Foo {
282 return null;
283 }
284 };
285 assertOrPanic((try S.errorable()) == 1234);
286 assertError(S.errorable2(), error.Failure);
287 assertError(S.errorable3(), error.Other);
288 comptime {
289 assertOrPanic((try S.errorable()) == 1234);
290 assertError(S.errorable2(), error.Failure);
291 assertError(S.errorable3(), error.Other);
292 }
293}
294
295test "widen cast integer payload of error union function call" {
296 const S = struct {
297 fn errorable() !u64 {
298 var x = u64(try number());
299 return x;
300 }
301
302 fn number() anyerror!u32 {
303 return 1234;
304 }
305 };
306 assertOrPanic((try S.errorable()) == 1234);
307}
308
309test "return function call to error set from error union function" {
310 const S = struct {
311 fn errorable() anyerror!i32 {
312 return fail();
313 }
314
315 fn fail() anyerror {
316 return error.Failure;
317 }
318 };
319 assertError(S.errorable(), error.Failure);
320 comptime assertError(S.errorable(), error.Failure);
321}
322
323test "optional error set is the same size as error set" {
324 comptime assertOrPanic(@sizeOf(?anyerror) == @sizeOf(anyerror));
325 const S = struct {
326 fn returnsOptErrSet() ?anyerror {
327 return null;
328 }
329 };
330 assertOrPanic(S.returnsOptErrSet() == null);
331 comptime assertOrPanic(S.returnsOptErrSet() == null);
332}
test/stage1/behavior/eval.zig created+784
...@@ -0,0 +1,784 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const builtin = @import("builtin");
4
5test "compile time recursion" {
6 assertOrPanic(some_data.len == 21);
7}
8var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
9fn fibonacci(x: i32) i32 {
10 if (x <= 1) return 1;
11 return fibonacci(x - 1) + fibonacci(x - 2);
12}
13
14fn unwrapAndAddOne(blah: ?i32) i32 {
15 return blah.? + 1;
16}
17const should_be_1235 = unwrapAndAddOne(1234);
18test "static add one" {
19 assertOrPanic(should_be_1235 == 1235);
20}
21
22test "inlined loop" {
23 comptime var i = 0;
24 comptime var sum = 0;
25 inline while (i <= 5) : (i += 1)
26 sum += i;
27 assertOrPanic(sum == 15);
28}
29
30fn gimme1or2(comptime a: bool) i32 {
31 const x: i32 = 1;
32 const y: i32 = 2;
33 comptime var z: i32 = if (a) x else y;
34 return z;
35}
36test "inline variable gets result of const if" {
37 assertOrPanic(gimme1or2(true) == 1);
38 assertOrPanic(gimme1or2(false) == 2);
39}
40
41test "static function evaluation" {
42 assertOrPanic(statically_added_number == 3);
43}
44const statically_added_number = staticAdd(1, 2);
45fn staticAdd(a: i32, b: i32) i32 {
46 return a + b;
47}
48
49test "const expr eval on single expr blocks" {
50 assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
51 comptime assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
52}
53
54fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
55 const literal = 3;
56
57 const result = if (b) b: {
58 break :b literal;
59 } else b: {
60 break :b x;
61 };
62
63 return result;
64}
65
66test "statically initialized list" {
67 assertOrPanic(static_point_list[0].x == 1);
68 assertOrPanic(static_point_list[0].y == 2);
69 assertOrPanic(static_point_list[1].x == 3);
70 assertOrPanic(static_point_list[1].y == 4);
71}
72const Point = struct {
73 x: i32,
74 y: i32,
75};
76const static_point_list = []Point{
77 makePoint(1, 2),
78 makePoint(3, 4),
79};
80fn makePoint(x: i32, y: i32) Point {
81 return Point{
82 .x = x,
83 .y = y,
84 };
85}
86
87test "static eval list init" {
88 assertOrPanic(static_vec3.data[2] == 1.0);
89 assertOrPanic(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
90}
91const static_vec3 = vec3(0.0, 0.0, 1.0);
92pub const Vec3 = struct {
93 data: [3]f32,
94};
95pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
96 return Vec3{ .data = []f32{
97 x,
98 y,
99 z,
100 } };
101}
102
103test "constant expressions" {
104 var array: [array_size]u8 = undefined;
105 assertOrPanic(@sizeOf(@typeOf(array)) == 20);
106}
107const array_size: u8 = 20;
108
109test "constant struct with negation" {
110 assertOrPanic(vertices[0].x == -0.6);
111}
112const Vertex = struct {
113 x: f32,
114 y: f32,
115 r: f32,
116 g: f32,
117 b: f32,
118};
119const vertices = []Vertex{
120 Vertex{
121 .x = -0.6,
122 .y = -0.4,
123 .r = 1.0,
124 .g = 0.0,
125 .b = 0.0,
126 },
127 Vertex{
128 .x = 0.6,
129 .y = -0.4,
130 .r = 0.0,
131 .g = 1.0,
132 .b = 0.0,
133 },
134 Vertex{
135 .x = 0.0,
136 .y = 0.6,
137 .r = 0.0,
138 .g = 0.0,
139 .b = 1.0,
140 },
141};
142
143test "statically initialized struct" {
144 st_init_str_foo.x += 1;
145 assertOrPanic(st_init_str_foo.x == 14);
146}
147const StInitStrFoo = struct {
148 x: i32,
149 y: bool,
150};
151var st_init_str_foo = StInitStrFoo{
152 .x = 13,
153 .y = true,
154};
155
156test "statically initalized array literal" {
157 const y: [4]u8 = st_init_arr_lit_x;
158 assertOrPanic(y[3] == 4);
159}
160const st_init_arr_lit_x = []u8{
161 1,
162 2,
163 3,
164 4,
165};
166
167test "const slice" {
168 comptime {
169 const a = "1234567890";
170 assertOrPanic(a.len == 10);
171 const b = a[1..2];
172 assertOrPanic(b.len == 1);
173 assertOrPanic(b[0] == '2');
174 }
175}
176
177test "try to trick eval with runtime if" {
178 assertOrPanic(testTryToTrickEvalWithRuntimeIf(true) == 10);
179}
180
181fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
182 comptime var i: usize = 0;
183 inline while (i < 10) : (i += 1) {
184 const result = if (b) false else true;
185 }
186 comptime {
187 return i;
188 }
189}
190
191fn max(comptime T: type, a: T, b: T) T {
192 if (T == bool) {
193 return a or b;
194 } else if (a > b) {
195 return a;
196 } else {
197 return b;
198 }
199}
200fn letsTryToCompareBools(a: bool, b: bool) bool {
201 return max(bool, a, b);
202}
203test "inlined block and runtime block phi" {
204 assertOrPanic(letsTryToCompareBools(true, true));
205 assertOrPanic(letsTryToCompareBools(true, false));
206 assertOrPanic(letsTryToCompareBools(false, true));
207 assertOrPanic(!letsTryToCompareBools(false, false));
208
209 comptime {
210 assertOrPanic(letsTryToCompareBools(true, true));
211 assertOrPanic(letsTryToCompareBools(true, false));
212 assertOrPanic(letsTryToCompareBools(false, true));
213 assertOrPanic(!letsTryToCompareBools(false, false));
214 }
215}
216
217const CmdFn = struct {
218 name: []const u8,
219 func: fn (i32) i32,
220};
221
222const cmd_fns = []CmdFn{
223 CmdFn{
224 .name = "one",
225 .func = one,
226 },
227 CmdFn{
228 .name = "two",
229 .func = two,
230 },
231 CmdFn{
232 .name = "three",
233 .func = three,
234 },
235};
236fn one(value: i32) i32 {
237 return value + 1;
238}
239fn two(value: i32) i32 {
240 return value + 2;
241}
242fn three(value: i32) i32 {
243 return value + 3;
244}
245
246fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
247 var result: i32 = start_value;
248 comptime var i = 0;
249 inline while (i < cmd_fns.len) : (i += 1) {
250 if (cmd_fns[i].name[0] == prefix_char) {
251 result = cmd_fns[i].func(result);
252 }
253 }
254 return result;
255}
256
257test "comptime iterate over fn ptr list" {
258 assertOrPanic(performFn('t', 1) == 6);
259 assertOrPanic(performFn('o', 0) == 1);
260 assertOrPanic(performFn('w', 99) == 99);
261}
262
263test "eval @setRuntimeSafety at compile-time" {
264 const result = comptime fnWithSetRuntimeSafety();
265 assertOrPanic(result == 1234);
266}
267
268fn fnWithSetRuntimeSafety() i32 {
269 @setRuntimeSafety(true);
270 return 1234;
271}
272
273test "eval @setFloatMode at compile-time" {
274 const result = comptime fnWithFloatMode();
275 assertOrPanic(result == 1234.0);
276}
277
278fn fnWithFloatMode() f32 {
279 @setFloatMode(builtin.FloatMode.Strict);
280 return 1234.0;
281}
282
283const SimpleStruct = struct {
284 field: i32,
285
286 fn method(self: *const SimpleStruct) i32 {
287 return self.field + 3;
288 }
289};
290
291var simple_struct = SimpleStruct{ .field = 1234 };
292
293const bound_fn = simple_struct.method;
294
295test "call method on bound fn referring to var instance" {
296 assertOrPanic(bound_fn() == 1237);
297}
298
299test "ptr to local array argument at comptime" {
300 comptime {
301 var bytes: [10]u8 = undefined;
302 modifySomeBytes(bytes[0..]);
303 assertOrPanic(bytes[0] == 'a');
304 assertOrPanic(bytes[9] == 'b');
305 }
306}
307
308fn modifySomeBytes(bytes: []u8) void {
309 bytes[0] = 'a';
310 bytes[9] = 'b';
311}
312
313test "comparisons 0 <= uint and 0 > uint should be comptime" {
314 testCompTimeUIntComparisons(1234);
315}
316fn testCompTimeUIntComparisons(x: u32) void {
317 if (!(0 <= x)) {
318 @compileError("this condition should be comptime known");
319 }
320 if (0 > x) {
321 @compileError("this condition should be comptime known");
322 }
323 if (!(x >= 0)) {
324 @compileError("this condition should be comptime known");
325 }
326 if (x < 0) {
327 @compileError("this condition should be comptime known");
328 }
329}
330
331test "const ptr to variable data changes at runtime" {
332 assertOrPanic(foo_ref.name[0] == 'a');
333 foo_ref.name = "b";
334 assertOrPanic(foo_ref.name[0] == 'b');
335}
336
337const Foo = struct {
338 name: []const u8,
339};
340
341var foo_contents = Foo{ .name = "a" };
342const foo_ref = &foo_contents;
343
344test "create global array with for loop" {
345 assertOrPanic(global_array[5] == 5 * 5);
346 assertOrPanic(global_array[9] == 9 * 9);
347}
348
349const global_array = x: {
350 var result: [10]usize = undefined;
351 for (result) |*item, index| {
352 item.* = index * index;
353 }
354 break :x result;
355};
356
357test "compile-time downcast when the bits fit" {
358 comptime {
359 const spartan_count: u16 = 255;
360 const byte = @intCast(u8, spartan_count);
361 assertOrPanic(byte == 255);
362 }
363}
364
365const hi1 = "hi";
366const hi2 = hi1;
367test "const global shares pointer with other same one" {
368 assertEqualPtrs(&hi1[0], &hi2[0]);
369 comptime assertOrPanic(&hi1[0] == &hi2[0]);
370}
371fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void {
372 assertOrPanic(ptr1 == ptr2);
373}
374
375test "@setEvalBranchQuota" {
376 comptime {
377 // 1001 for the loop and then 1 more for the assertOrPanic fn call
378 @setEvalBranchQuota(1002);
379 var i = 0;
380 var sum = 0;
381 while (i < 1001) : (i += 1) {
382 sum += i;
383 }
384 assertOrPanic(sum == 500500);
385 }
386}
387
388// TODO test "float literal at compile time not lossy" {
389// TODO assertOrPanic(16777216.0 + 1.0 == 16777217.0);
390// TODO assertOrPanic(9007199254740992.0 + 1.0 == 9007199254740993.0);
391// TODO }
392
393test "f32 at compile time is lossy" {
394 assertOrPanic(f32(1 << 24) + 1 == 1 << 24);
395}
396
397test "f64 at compile time is lossy" {
398 assertOrPanic(f64(1 << 53) + 1 == 1 << 53);
399}
400
401test "f128 at compile time is lossy" {
402 assertOrPanic(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
403}
404
405comptime {
406 assertOrPanic(f128(1 << 113) == 10384593717069655257060992658440192);
407}
408
409pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
410 return struct {
411 pub const Node = struct {};
412 };
413}
414
415test "string literal used as comptime slice is memoized" {
416 const a = "link";
417 const b = "link";
418 comptime assertOrPanic(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
419 comptime assertOrPanic(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
420}
421
422test "comptime slice of undefined pointer of length 0" {
423 const slice1 = ([*]i32)(undefined)[0..0];
424 assertOrPanic(slice1.len == 0);
425 const slice2 = ([*]i32)(undefined)[100..100];
426 assertOrPanic(slice2.len == 0);
427}
428
429fn copyWithPartialInline(s: []u32, b: []u8) void {
430 comptime var i: usize = 0;
431 inline while (i < 4) : (i += 1) {
432 s[i] = 0;
433 s[i] |= u32(b[i * 4 + 0]) << 24;
434 s[i] |= u32(b[i * 4 + 1]) << 16;
435 s[i] |= u32(b[i * 4 + 2]) << 8;
436 s[i] |= u32(b[i * 4 + 3]) << 0;
437 }
438}
439
440test "binary math operator in partially inlined function" {
441 var s: [4]u32 = undefined;
442 var b: [16]u8 = undefined;
443
444 for (b) |*r, i|
445 r.* = @intCast(u8, i + 1);
446
447 copyWithPartialInline(s[0..], b[0..]);
448 assertOrPanic(s[0] == 0x1020304);
449 assertOrPanic(s[1] == 0x5060708);
450 assertOrPanic(s[2] == 0x90a0b0c);
451 assertOrPanic(s[3] == 0xd0e0f10);
452}
453
454test "comptime function with the same args is memoized" {
455 comptime {
456 assertOrPanic(MakeType(i32) == MakeType(i32));
457 assertOrPanic(MakeType(i32) != MakeType(f64));
458 }
459}
460
461fn MakeType(comptime T: type) type {
462 return struct {
463 field: T,
464 };
465}
466
467test "comptime function with mutable pointer is not memoized" {
468 comptime {
469 var x: i32 = 1;
470 const ptr = &x;
471 increment(ptr);
472 increment(ptr);
473 assertOrPanic(x == 3);
474 }
475}
476
477fn increment(value: *i32) void {
478 value.* += 1;
479}
480
481fn generateTable(comptime T: type) [1010]T {
482 var res: [1010]T = undefined;
483 var i: usize = 0;
484 while (i < 1010) : (i += 1) {
485 res[i] = @intCast(T, i);
486 }
487 return res;
488}
489
490fn doesAlotT(comptime T: type, value: usize) T {
491 @setEvalBranchQuota(5000);
492 const table = comptime blk: {
493 break :blk generateTable(T);
494 };
495 return table[value];
496}
497
498test "@setEvalBranchQuota at same scope as generic function call" {
499 assertOrPanic(doesAlotT(u32, 2) == 2);
500}
501
502test "comptime slice of slice preserves comptime var" {
503 comptime {
504 var buff: [10]u8 = undefined;
505 buff[0..][0..][0] = 1;
506 assertOrPanic(buff[0..][0..][0] == 1);
507 }
508}
509
510test "comptime slice of pointer preserves comptime var" {
511 comptime {
512 var buff: [10]u8 = undefined;
513 var a = buff[0..].ptr;
514 a[0..1][0] = 1;
515 assertOrPanic(buff[0..][0..][0] == 1);
516 }
517}
518
519const SingleFieldStruct = struct {
520 x: i32,
521
522 fn read_x(self: *const SingleFieldStruct) i32 {
523 return self.x;
524 }
525};
526test "const ptr to comptime mutable data is not memoized" {
527 comptime {
528 var foo = SingleFieldStruct{ .x = 1 };
529 assertOrPanic(foo.read_x() == 1);
530 foo.x = 2;
531 assertOrPanic(foo.read_x() == 2);
532 }
533}
534
535test "array concat of slices gives slice" {
536 comptime {
537 var a: []const u8 = "aoeu";
538 var b: []const u8 = "asdf";
539 const c = a ++ b;
540 assertOrPanic(std.mem.eql(u8, c, "aoeuasdf"));
541 }
542}
543
544test "comptime shlWithOverflow" {
545 const ct_shifted: u64 = comptime amt: {
546 var amt = u64(0);
547 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
548 break :amt amt;
549 };
550
551 const rt_shifted: u64 = amt: {
552 var amt = u64(0);
553 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
554 break :amt amt;
555 };
556
557 assertOrPanic(ct_shifted == rt_shifted);
558}
559
560test "runtime 128 bit integer division" {
561 var a: u128 = 152313999999999991610955792383;
562 var b: u128 = 10000000000000000000;
563 var c = a / b;
564 assertOrPanic(c == 15231399999);
565}
566
567pub const Info = struct {
568 version: u8,
569};
570
571pub const diamond_info = Info{ .version = 0 };
572
573test "comptime modification of const struct field" {
574 comptime {
575 var res = diamond_info;
576 res.version = 1;
577 assertOrPanic(diamond_info.version == 0);
578 assertOrPanic(res.version == 1);
579 }
580}
581
582test "pointer to type" {
583 comptime {
584 var T: type = i32;
585 assertOrPanic(T == i32);
586 var ptr = &T;
587 assertOrPanic(@typeOf(ptr) == *type);
588 ptr.* = f32;
589 assertOrPanic(T == f32);
590 assertOrPanic(*T == *f32);
591 }
592}
593
594test "slice of type" {
595 comptime {
596 var types_array = []type{ i32, f64, type };
597 for (types_array) |T, i| {
598 switch (i) {
599 0 => assertOrPanic(T == i32),
600 1 => assertOrPanic(T == f64),
601 2 => assertOrPanic(T == type),
602 else => unreachable,
603 }
604 }
605 for (types_array[0..]) |T, i| {
606 switch (i) {
607 0 => assertOrPanic(T == i32),
608 1 => assertOrPanic(T == f64),
609 2 => assertOrPanic(T == type),
610 else => unreachable,
611 }
612 }
613 }
614}
615
616const Wrapper = struct {
617 T: type,
618};
619
620fn wrap(comptime T: type) Wrapper {
621 return Wrapper{ .T = T };
622}
623
624test "function which returns struct with type field causes implicit comptime" {
625 const ty = wrap(i32).T;
626 assertOrPanic(ty == i32);
627}
628
629test "call method with comptime pass-by-non-copying-value self parameter" {
630 const S = struct {
631 a: u8,
632
633 fn b(comptime s: @This()) u8 {
634 return s.a;
635 }
636 };
637
638 const s = S{ .a = 2 };
639 var b = s.b();
640 assertOrPanic(b == 2);
641}
642
643test "@tagName of @typeId" {
644 const str = @tagName(@typeId(u8));
645 assertOrPanic(std.mem.eql(u8, str, "Int"));
646}
647
648test "setting backward branch quota just before a generic fn call" {
649 @setEvalBranchQuota(1001);
650 loopNTimes(1001);
651}
652
653fn loopNTimes(comptime n: usize) void {
654 comptime var i = 0;
655 inline while (i < n) : (i += 1) {}
656}
657
658test "variable inside inline loop that has different types on different iterations" {
659 testVarInsideInlineLoop(true, u32(42));
660}
661
662fn testVarInsideInlineLoop(args: ...) void {
663 comptime var i = 0;
664 inline while (i < args.len) : (i += 1) {
665 const x = args[i];
666 if (i == 0) assertOrPanic(x);
667 if (i == 1) assertOrPanic(x == 42);
668 }
669}
670
671test "inline for with same type but different values" {
672 var res: usize = 0;
673 inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| {
674 var a: T = undefined;
675 res += a.len;
676 }
677 assertOrPanic(res == 5);
678}
679
680test "refer to the type of a generic function" {
681 const Func = fn (type) void;
682 const f: Func = doNothingWithType;
683 f(i32);
684}
685
686fn doNothingWithType(comptime T: type) void {}
687
688test "zero extend from u0 to u1" {
689 var zero_u0: u0 = 0;
690 var zero_u1: u1 = zero_u0;
691 assertOrPanic(zero_u1 == 0);
692}
693
694test "bit shift a u1" {
695 var x: u1 = 1;
696 var y = x << 0;
697 assertOrPanic(y == 1);
698}
699
700test "@intCast to a u0" {
701 var x: u8 = 0;
702 var y: u0 = @intCast(u0, x);
703 assertOrPanic(y == 0);
704}
705
706test "@bytesToslice on a packed struct" {
707 const F = packed struct {
708 a: u8,
709 };
710
711 var b = [1]u8{9};
712 var f = @bytesToSlice(F, b);
713 assertOrPanic(f[0].a == 9);
714}
715
716test "comptime pointer cast array and then slice" {
717 const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
718
719 const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
720 const sliceA: []const u8 = ptrA[0..2];
721
722 const ptrB: [*]const u8 = &array;
723 const sliceB: []const u8 = ptrB[0..2];
724
725 assertOrPanic(sliceA[1] == 2);
726 assertOrPanic(sliceB[1] == 2);
727}
728
729test "slice bounds in comptime concatenation" {
730 const bs = comptime blk: {
731 const b = c"11";
732 break :blk b[0..1];
733 };
734 const str = "" ++ bs;
735 assertOrPanic(str.len == 1);
736 assertOrPanic(std.mem.eql(u8, str, "1"));
737
738 const str2 = bs ++ "";
739 assertOrPanic(str2.len == 1);
740 assertOrPanic(std.mem.eql(u8, str2, "1"));
741}
742
743test "comptime bitwise operators" {
744 comptime {
745 assertOrPanic(3 & 1 == 1);
746 assertOrPanic(3 & -1 == 3);
747 assertOrPanic(-3 & -1 == -3);
748 assertOrPanic(3 | -1 == -1);
749 assertOrPanic(-3 | -1 == -1);
750 assertOrPanic(3 ^ -1 == -4);
751 assertOrPanic(-3 ^ -1 == 2);
752 assertOrPanic(~i8(-1) == 0);
753 assertOrPanic(~i128(-1) == 0);
754 assertOrPanic(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
755 assertOrPanic(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
756 assertOrPanic(~u128(0) == 0xffffffffffffffffffffffffffffffff);
757 }
758}
759
760test "*align(1) u16 is the same as *align(1:0:2) u16" {
761 comptime {
762 assertOrPanic(*align(1:0:2) u16 == *align(1) u16);
763 // TODO add parsing support for this syntax
764 //assertOrPanic(*align(:0:2) u16 == *u16);
765 }
766}
767
768test "array concatenation forces comptime" {
769 var a = oneItem(3) ++ oneItem(4);
770 assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 4 }));
771}
772
773test "array multiplication forces comptime" {
774 var a = oneItem(3) ** scalar(2);
775 assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 3 }));
776}
777
778fn oneItem(x: i32) [1]i32 {
779 return []i32{x};
780}
781
782fn scalar(x: u32) u32 {
783 return x;
784}
test/stage1/behavior/field_parent_ptr.zig created+41
...@@ -0,0 +1,41 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "@fieldParentPtr non-first field" {
4 testParentFieldPtr(&foo.c);
5 comptime testParentFieldPtr(&foo.c);
6}
7
8test "@fieldParentPtr first field" {
9 testParentFieldPtrFirst(&foo.a);
10 comptime testParentFieldPtrFirst(&foo.a);
11}
12
13const Foo = struct {
14 a: bool,
15 b: f32,
16 c: i32,
17 d: i32,
18};
19
20const foo = Foo{
21 .a = true,
22 .b = 0.123,
23 .c = 1234,
24 .d = -10,
25};
26
27fn testParentFieldPtr(c: *const i32) void {
28 assertOrPanic(c == &foo.c);
29
30 const base = @fieldParentPtr(Foo, "c", c);
31 assertOrPanic(base == &foo);
32 assertOrPanic(&base.c == c);
33}
34
35fn testParentFieldPtrFirst(a: *const bool) void {
36 assertOrPanic(a == &foo.a);
37
38 const base = @fieldParentPtr(Foo, "a", a);
39 assertOrPanic(base == &foo);
40 assertOrPanic(&base.a == a);
41}
test/stage1/behavior/fn.zig created+208
...@@ -0,0 +1,208 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "params" {
4 assertOrPanic(testParamsAdd(22, 11) == 33);
5}
6fn testParamsAdd(a: i32, b: i32) i32 {
7 return a + b;
8}
9
10test "local variables" {
11 testLocVars(2);
12}
13fn testLocVars(b: i32) void {
14 const a: i32 = 1;
15 if (a + b != 3) unreachable;
16}
17
18test "void parameters" {
19 voidFun(1, void{}, 2, {});
20}
21fn voidFun(a: i32, b: void, c: i32, d: void) void {
22 const v = b;
23 const vv: void = if (a == 1) v else {};
24 assertOrPanic(a + c == 3);
25 return vv;
26}
27
28test "mutable local variables" {
29 var zero: i32 = 0;
30 assertOrPanic(zero == 0);
31
32 var i = i32(0);
33 while (i != 3) {
34 i += 1;
35 }
36 assertOrPanic(i == 3);
37}
38
39test "separate block scopes" {
40 {
41 const no_conflict: i32 = 5;
42 assertOrPanic(no_conflict == 5);
43 }
44
45 const c = x: {
46 const no_conflict = i32(10);
47 break :x no_conflict;
48 };
49 assertOrPanic(c == 10);
50}
51
52test "call function with empty string" {
53 acceptsString("");
54}
55
56fn acceptsString(foo: []u8) void {}
57
58fn @"weird function name"() i32 {
59 return 1234;
60}
61test "weird function name" {
62 assertOrPanic(@"weird function name"() == 1234);
63}
64
65test "implicit cast function unreachable return" {
66 wantsFnWithVoid(fnWithUnreachable);
67}
68
69fn wantsFnWithVoid(f: fn () void) void {}
70
71fn fnWithUnreachable() noreturn {
72 unreachable;
73}
74
75test "function pointers" {
76 const fns = []@typeOf(fn1){
77 fn1,
78 fn2,
79 fn3,
80 fn4,
81 };
82 for (fns) |f, i| {
83 assertOrPanic(f() == @intCast(u32, i) + 5);
84 }
85}
86fn fn1() u32 {
87 return 5;
88}
89fn fn2() u32 {
90 return 6;
91}
92fn fn3() u32 {
93 return 7;
94}
95fn fn4() u32 {
96 return 8;
97}
98
99test "inline function call" {
100 assertOrPanic(@inlineCall(add, 3, 9) == 12);
101}
102
103fn add(a: i32, b: i32) i32 {
104 return a + b;
105}
106
107test "number literal as an argument" {
108 numberLiteralArg(3);
109 comptime numberLiteralArg(3);
110}
111
112fn numberLiteralArg(a: var) void {
113 assertOrPanic(a == 3);
114}
115
116test "assign inline fn to const variable" {
117 const a = inlineFn;
118 a();
119}
120
121inline fn inlineFn() void {}
122
123test "pass by non-copying value" {
124 assertOrPanic(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
125}
126
127const Point = struct {
128 x: i32,
129 y: i32,
130};
131
132fn addPointCoords(pt: Point) i32 {
133 return pt.x + pt.y;
134}
135
136test "pass by non-copying value through var arg" {
137 assertOrPanic(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
138}
139
140fn addPointCoordsVar(pt: var) i32 {
141 comptime assertOrPanic(@typeOf(pt) == Point);
142 return pt.x + pt.y;
143}
144
145test "pass by non-copying value as method" {
146 var pt = Point2{ .x = 1, .y = 2 };
147 assertOrPanic(pt.addPointCoords() == 3);
148}
149
150const Point2 = struct {
151 x: i32,
152 y: i32,
153
154 fn addPointCoords(self: Point2) i32 {
155 return self.x + self.y;
156 }
157};
158
159test "pass by non-copying value as method, which is generic" {
160 var pt = Point3{ .x = 1, .y = 2 };
161 assertOrPanic(pt.addPointCoords(i32) == 3);
162}
163
164const Point3 = struct {
165 x: i32,
166 y: i32,
167
168 fn addPointCoords(self: Point3, comptime T: type) i32 {
169 return self.x + self.y;
170 }
171};
172
173test "pass by non-copying value as method, at comptime" {
174 comptime {
175 var pt = Point2{ .x = 1, .y = 2 };
176 assertOrPanic(pt.addPointCoords() == 3);
177 }
178}
179
180fn outer(y: u32) fn (u32) u32 {
181 const Y = @typeOf(y);
182 const st = struct {
183 fn get(z: u32) u32 {
184 return z + @sizeOf(Y);
185 }
186 };
187 return st.get;
188}
189
190test "return inner function which references comptime variable of outer function" {
191 var func = outer(10);
192 assertOrPanic(func(3) == 7);
193}
194
195test "extern struct with stdcallcc fn pointer" {
196 const S = extern struct {
197 ptr: stdcallcc fn () i32,
198
199 stdcallcc fn foo() i32 {
200 return 1234;
201 }
202 };
203
204 var s: S = undefined;
205 s.ptr = S.foo;
206 assertOrPanic(s.ptr() == 1234);
207}
208
test/stage1/behavior/fn_in_struct_in_comptime.zig created+17
...@@ -0,0 +1,17 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3fn get_foo() fn (*u8) usize {
4 comptime {
5 return struct {
6 fn func(ptr: *u8) usize {
7 var u = @ptrToInt(ptr);
8 return u;
9 }
10 }.func;
11 }
12}
13
14test "define a function in an anonymous struct in comptime" {
15 const foo = get_foo();
16 assertOrPanic(foo(@intToPtr(*u8, 12345)) == 12345);
17}
test/stage1/behavior/for.zig created+106
...@@ -0,0 +1,106 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const mem = std.mem;
4
5test "continue in for loop" {
6 const array = []i32{
7 1,
8 2,
9 3,
10 4,
11 5,
12 };
13 var sum: i32 = 0;
14 for (array) |x| {
15 sum += x;
16 if (x < 3) {
17 continue;
18 }
19 break;
20 }
21 if (sum != 6) unreachable;
22}
23
24test "for loop with pointer elem var" {
25 const source = "abcdefg";
26 var target: [source.len]u8 = undefined;
27 mem.copy(u8, target[0..], source);
28 mangleString(target[0..]);
29 assertOrPanic(mem.eql(u8, target, "bcdefgh"));
30}
31fn mangleString(s: []u8) void {
32 for (s) |*c| {
33 c.* += 1;
34 }
35}
36
37test "basic for loop" {
38 const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
39
40 var buffer: [expected_result.len]u8 = undefined;
41 var buf_index: usize = 0;
42
43 const array = []u8{ 9, 8, 7, 6 };
44 for (array) |item| {
45 buffer[buf_index] = item;
46 buf_index += 1;
47 }
48 for (array) |item, index| {
49 buffer[buf_index] = @intCast(u8, index);
50 buf_index += 1;
51 }
52 const array_ptr = &array;
53 for (array_ptr) |item| {
54 buffer[buf_index] = item;
55 buf_index += 1;
56 }
57 for (array_ptr) |item, index| {
58 buffer[buf_index] = @intCast(u8, index);
59 buf_index += 1;
60 }
61 const unknown_size: []const u8 = array;
62 for (unknown_size) |item| {
63 buffer[buf_index] = item;
64 buf_index += 1;
65 }
66 for (unknown_size) |item, index| {
67 buffer[buf_index] = @intCast(u8, index);
68 buf_index += 1;
69 }
70
71 assertOrPanic(mem.eql(u8, buffer[0..buf_index], expected_result));
72}
73
74test "break from outer for loop" {
75 testBreakOuter();
76 comptime testBreakOuter();
77}
78
79fn testBreakOuter() void {
80 var array = "aoeu";
81 var count: usize = 0;
82 outer: for (array) |_| {
83 for (array) |_| {
84 count += 1;
85 break :outer;
86 }
87 }
88 assertOrPanic(count == 1);
89}
90
91test "continue outer for loop" {
92 testContinueOuter();
93 comptime testContinueOuter();
94}
95
96fn testContinueOuter() void {
97 var array = "aoeu";
98 var counter: usize = 0;
99 outer: for (array) |_| {
100 for (array) |_| {
101 counter += 1;
102 continue :outer;
103 }
104 }
105 assertOrPanic(counter == array.len);
106}
test/stage1/behavior/generics.zig created+151
...@@ -0,0 +1,151 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "simple generic fn" {
4 assertOrPanic(max(i32, 3, -1) == 3);
5 assertOrPanic(max(f32, 0.123, 0.456) == 0.456);
6 assertOrPanic(add(2, 3) == 5);
7}
8
9fn max(comptime T: type, a: T, b: T) T {
10 return if (a > b) a else b;
11}
12
13fn add(comptime a: i32, b: i32) i32 {
14 return (comptime a) + b;
15}
16
17const the_max = max(u32, 1234, 5678);
18test "compile time generic eval" {
19 assertOrPanic(the_max == 5678);
20}
21
22fn gimmeTheBigOne(a: u32, b: u32) u32 {
23 return max(u32, a, b);
24}
25
26fn shouldCallSameInstance(a: u32, b: u32) u32 {
27 return max(u32, a, b);
28}
29
30fn sameButWithFloats(a: f64, b: f64) f64 {
31 return max(f64, a, b);
32}
33
34test "fn with comptime args" {
35 assertOrPanic(gimmeTheBigOne(1234, 5678) == 5678);
36 assertOrPanic(shouldCallSameInstance(34, 12) == 34);
37 assertOrPanic(sameButWithFloats(0.43, 0.49) == 0.49);
38}
39
40test "var params" {
41 assertOrPanic(max_i32(12, 34) == 34);
42 assertOrPanic(max_f64(1.2, 3.4) == 3.4);
43}
44
45comptime {
46 assertOrPanic(max_i32(12, 34) == 34);
47 assertOrPanic(max_f64(1.2, 3.4) == 3.4);
48}
49
50fn max_var(a: var, b: var) @typeOf(a + b) {
51 return if (a > b) a else b;
52}
53
54fn max_i32(a: i32, b: i32) i32 {
55 return max_var(a, b);
56}
57
58fn max_f64(a: f64, b: f64) f64 {
59 return max_var(a, b);
60}
61
62pub fn List(comptime T: type) type {
63 return SmallList(T, 8);
64}
65
66pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
67 return struct {
68 items: []T,
69 length: usize,
70 prealloc_items: [STATIC_SIZE]T,
71 };
72}
73
74test "function with return type type" {
75 var list: List(i32) = undefined;
76 var list2: List(i32) = undefined;
77 list.length = 10;
78 list2.length = 10;
79 assertOrPanic(list.prealloc_items.len == 8);
80 assertOrPanic(list2.prealloc_items.len == 8);
81}
82
83test "generic struct" {
84 var a1 = GenNode(i32){
85 .value = 13,
86 .next = null,
87 };
88 var b1 = GenNode(bool){
89 .value = true,
90 .next = null,
91 };
92 assertOrPanic(a1.value == 13);
93 assertOrPanic(a1.value == a1.getVal());
94 assertOrPanic(b1.getVal());
95}
96fn GenNode(comptime T: type) type {
97 return struct {
98 value: T,
99 next: ?*GenNode(T),
100 fn getVal(n: *const GenNode(T)) T {
101 return n.value;
102 }
103 };
104}
105
106test "const decls in struct" {
107 assertOrPanic(GenericDataThing(3).count_plus_one == 4);
108}
109fn GenericDataThing(comptime count: isize) type {
110 return struct {
111 const count_plus_one = count + 1;
112 };
113}
114
115test "use generic param in generic param" {
116 assertOrPanic(aGenericFn(i32, 3, 4) == 7);
117}
118fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
119 return a + b;
120}
121
122test "generic fn with implicit cast" {
123 assertOrPanic(getFirstByte(u8, []u8{13}) == 13);
124 assertOrPanic(getFirstByte(u16, []u16{
125 0,
126 13,
127 }) == 0);
128}
129fn getByte(ptr: ?*const u8) u8 {
130 return ptr.?.*;
131}
132fn getFirstByte(comptime T: type, mem: []const T) u8 {
133 return getByte(@ptrCast(*const u8, &mem[0]));
134}
135
136const foos = []fn (var) bool{
137 foo1,
138 foo2,
139};
140
141fn foo1(arg: var) bool {
142 return arg;
143}
144fn foo2(arg: var) bool {
145 return !arg;
146}
147
148test "array of generic fns" {
149 assertOrPanic(foos[0](true));
150 assertOrPanic(!foos[1](true));
151}
test/stage1/behavior/if.zig created+37
...@@ -0,0 +1,37 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "if statements" {
4 shouldBeEqual(1, 1);
5 firstEqlThird(2, 1, 2);
6}
7fn shouldBeEqual(a: i32, b: i32) void {
8 if (a != b) {
9 unreachable;
10 } else {
11 return;
12 }
13}
14fn firstEqlThird(a: i32, b: i32, c: i32) void {
15 if (a == b) {
16 unreachable;
17 } else if (b == c) {
18 unreachable;
19 } else if (a == c) {
20 return;
21 } else {
22 unreachable;
23 }
24}
25
26test "else if expression" {
27 assertOrPanic(elseIfExpressionF(1) == 1);
28}
29fn elseIfExpressionF(c: u8) u8 {
30 if (c == 0) {
31 return 0;
32 } else if (c == 1) {
33 return 1;
34 } else {
35 return u8(2);
36 }
37}
test/stage1/behavior/import.zig created+10
...@@ -0,0 +1,10 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const a_namespace = @import("import/a_namespace.zig");
3
4test "call fn via namespace lookup" {
5 assertOrPanic(a_namespace.foo() == 1234);
6}
7
8test "importing the same thing gives the same import" {
9 assertOrPanic(@import("std") == @import("std"));
10}
test/stage1/behavior/import/a_namespace.zig created+3
...@@ -0,0 +1,3 @@
1pub fn foo() i32 {
2 return 1234;
3}
test/stage1/behavior/incomplete_struct_param_tld.zig created+30
...@@ -0,0 +1,30 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const A = struct {
4 b: B,
5};
6
7const B = struct {
8 c: C,
9};
10
11const C = struct {
12 x: i32,
13
14 fn d(c: *const C) i32 {
15 return c.x;
16 }
17};
18
19fn foo(a: A) i32 {
20 return a.b.c.d();
21}
22
23test "incomplete struct param top level declaration" {
24 const a = A{
25 .b = B{
26 .c = C{ .x = 13 },
27 },
28 };
29 assertOrPanic(foo(a) == 13);
30}
test/stage1/behavior/inttoptr.zig created+26
...@@ -0,0 +1,26 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "casting random address to function pointer" {
6 randomAddressToFunction();
7 comptime randomAddressToFunction();
8}
9
10fn randomAddressToFunction() void {
11 var addr: usize = 0xdeadbeef;
12 var ptr = @intToPtr(fn () void, addr);
13}
14
15test "mutate through ptr initialized with constant intToPtr value" {
16 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
17}
18
19fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
20 const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef);
21 if (x) {
22 hardCodedP.* = hardCodedP.* | 10;
23 } else {
24 return;
25 }
26}
test/stage1/behavior/ir_block_deps.zig created+21
...@@ -0,0 +1,21 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3fn foo(id: u64) !i32 {
4 return switch (id) {
5 1 => getErrInt(),
6 2 => {
7 const size = try getErrInt();
8 return try getErrInt();
9 },
10 else => error.ItBroke,
11 };
12}
13
14fn getErrInt() anyerror!i32 {
15 return 0;
16}
17
18test "ir block deps" {
19 assertOrPanic((foo(1) catch unreachable) == 0);
20 assertOrPanic((foo(2) catch unreachable) == 0);
21}
test/stage1/behavior/math.zig created+500
...@@ -0,0 +1,500 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const maxInt = std.math.maxInt;
4const minInt = std.math.minInt;
5
6test "division" {
7 testDivision();
8 comptime testDivision();
9}
10fn testDivision() void {
11 assertOrPanic(div(u32, 13, 3) == 4);
12 assertOrPanic(div(f16, 1.0, 2.0) == 0.5);
13 assertOrPanic(div(f32, 1.0, 2.0) == 0.5);
14
15 assertOrPanic(divExact(u32, 55, 11) == 5);
16 assertOrPanic(divExact(i32, -55, 11) == -5);
17 assertOrPanic(divExact(f16, 55.0, 11.0) == 5.0);
18 assertOrPanic(divExact(f16, -55.0, 11.0) == -5.0);
19 assertOrPanic(divExact(f32, 55.0, 11.0) == 5.0);
20 assertOrPanic(divExact(f32, -55.0, 11.0) == -5.0);
21
22 assertOrPanic(divFloor(i32, 5, 3) == 1);
23 assertOrPanic(divFloor(i32, -5, 3) == -2);
24 assertOrPanic(divFloor(f16, 5.0, 3.0) == 1.0);
25 assertOrPanic(divFloor(f16, -5.0, 3.0) == -2.0);
26 assertOrPanic(divFloor(f32, 5.0, 3.0) == 1.0);
27 assertOrPanic(divFloor(f32, -5.0, 3.0) == -2.0);
28 assertOrPanic(divFloor(i32, -0x80000000, -2) == 0x40000000);
29 assertOrPanic(divFloor(i32, 0, -0x80000000) == 0);
30 assertOrPanic(divFloor(i32, -0x40000001, 0x40000000) == -2);
31 assertOrPanic(divFloor(i32, -0x80000000, 1) == -0x80000000);
32
33 assertOrPanic(divTrunc(i32, 5, 3) == 1);
34 assertOrPanic(divTrunc(i32, -5, 3) == -1);
35 assertOrPanic(divTrunc(f16, 5.0, 3.0) == 1.0);
36 assertOrPanic(divTrunc(f16, -5.0, 3.0) == -1.0);
37 assertOrPanic(divTrunc(f32, 5.0, 3.0) == 1.0);
38 assertOrPanic(divTrunc(f32, -5.0, 3.0) == -1.0);
39 assertOrPanic(divTrunc(f64, 5.0, 3.0) == 1.0);
40 assertOrPanic(divTrunc(f64, -5.0, 3.0) == -1.0);
41
42 comptime {
43 assertOrPanic(
44 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
45 );
46 assertOrPanic(
47 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
48 );
49 assertOrPanic(
50 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
51 );
52 assertOrPanic(
53 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
54 );
55 assertOrPanic(
56 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
57 );
58 assertOrPanic(
59 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
60 );
61 assertOrPanic(
62 4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
63 );
64 }
65}
66fn div(comptime T: type, a: T, b: T) T {
67 return a / b;
68}
69fn divExact(comptime T: type, a: T, b: T) T {
70 return @divExact(a, b);
71}
72fn divFloor(comptime T: type, a: T, b: T) T {
73 return @divFloor(a, b);
74}
75fn divTrunc(comptime T: type, a: T, b: T) T {
76 return @divTrunc(a, b);
77}
78
79test "@addWithOverflow" {
80 var result: u8 = undefined;
81 assertOrPanic(@addWithOverflow(u8, 250, 100, &result));
82 assertOrPanic(!@addWithOverflow(u8, 100, 150, &result));
83 assertOrPanic(result == 250);
84}
85
86// TODO test mulWithOverflow
87// TODO test subWithOverflow
88
89test "@shlWithOverflow" {
90 var result: u16 = undefined;
91 assertOrPanic(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
92 assertOrPanic(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
93 assertOrPanic(result == 0b1011111111111100);
94}
95
96test "@clz" {
97 testClz();
98 comptime testClz();
99}
100
101fn testClz() void {
102 assertOrPanic(clz(u8(0b00001010)) == 4);
103 assertOrPanic(clz(u8(0b10001010)) == 0);
104 assertOrPanic(clz(u8(0b00000000)) == 8);
105 assertOrPanic(clz(u128(0xffffffffffffffff)) == 64);
106 assertOrPanic(clz(u128(0x10000000000000000)) == 63);
107}
108
109fn clz(x: var) usize {
110 return @clz(x);
111}
112
113test "@ctz" {
114 testCtz();
115 comptime testCtz();
116}
117
118fn testCtz() void {
119 assertOrPanic(ctz(u8(0b10100000)) == 5);
120 assertOrPanic(ctz(u8(0b10001010)) == 1);
121 assertOrPanic(ctz(u8(0b00000000)) == 8);
122}
123
124fn ctz(x: var) usize {
125 return @ctz(x);
126}
127
128test "assignment operators" {
129 var i: u32 = 0;
130 i += 5;
131 assertOrPanic(i == 5);
132 i -= 2;
133 assertOrPanic(i == 3);
134 i *= 20;
135 assertOrPanic(i == 60);
136 i /= 3;
137 assertOrPanic(i == 20);
138 i %= 11;
139 assertOrPanic(i == 9);
140 i <<= 1;
141 assertOrPanic(i == 18);
142 i >>= 2;
143 assertOrPanic(i == 4);
144 i = 6;
145 i &= 5;
146 assertOrPanic(i == 4);
147 i ^= 6;
148 assertOrPanic(i == 2);
149 i = 6;
150 i |= 3;
151 assertOrPanic(i == 7);
152}
153
154test "three expr in a row" {
155 testThreeExprInARow(false, true);
156 comptime testThreeExprInARow(false, true);
157}
158fn testThreeExprInARow(f: bool, t: bool) void {
159 assertFalse(f or f or f);
160 assertFalse(t and t and f);
161 assertFalse(1 | 2 | 4 != 7);
162 assertFalse(3 ^ 6 ^ 8 != 13);
163 assertFalse(7 & 14 & 28 != 4);
164 assertFalse(9 << 1 << 2 != 9 << 3);
165 assertFalse(90 >> 1 >> 2 != 90 >> 3);
166 assertFalse(100 - 1 + 1000 != 1099);
167 assertFalse(5 * 4 / 2 % 3 != 1);
168 assertFalse(i32(i32(5)) != 5);
169 assertFalse(!!false);
170 assertFalse(i32(7) != --(i32(7)));
171}
172fn assertFalse(b: bool) void {
173 assertOrPanic(!b);
174}
175
176test "const number literal" {
177 const one = 1;
178 const eleven = ten + one;
179
180 assertOrPanic(eleven == 11);
181}
182const ten = 10;
183
184test "unsigned wrapping" {
185 testUnsignedWrappingEval(maxInt(u32));
186 comptime testUnsignedWrappingEval(maxInt(u32));
187}
188fn testUnsignedWrappingEval(x: u32) void {
189 const zero = x +% 1;
190 assertOrPanic(zero == 0);
191 const orig = zero -% 1;
192 assertOrPanic(orig == maxInt(u32));
193}
194
195test "signed wrapping" {
196 testSignedWrappingEval(maxInt(i32));
197 comptime testSignedWrappingEval(maxInt(i32));
198}
199fn testSignedWrappingEval(x: i32) void {
200 const min_val = x +% 1;
201 assertOrPanic(min_val == minInt(i32));
202 const max_val = min_val -% 1;
203 assertOrPanic(max_val == maxInt(i32));
204}
205
206test "negation wrapping" {
207 testNegationWrappingEval(minInt(i16));
208 comptime testNegationWrappingEval(minInt(i16));
209}
210fn testNegationWrappingEval(x: i16) void {
211 assertOrPanic(x == -32768);
212 const neg = -%x;
213 assertOrPanic(neg == -32768);
214}
215
216test "unsigned 64-bit division" {
217 test_u64_div();
218 comptime test_u64_div();
219}
220fn test_u64_div() void {
221 const result = divWithResult(1152921504606846976, 34359738365);
222 assertOrPanic(result.quotient == 33554432);
223 assertOrPanic(result.remainder == 100663296);
224}
225fn divWithResult(a: u64, b: u64) DivResult {
226 return DivResult{
227 .quotient = a / b,
228 .remainder = a % b,
229 };
230}
231const DivResult = struct {
232 quotient: u64,
233 remainder: u64,
234};
235
236test "binary not" {
237 assertOrPanic(comptime x: {
238 break :x ~u16(0b1010101010101010) == 0b0101010101010101;
239 });
240 assertOrPanic(comptime x: {
241 break :x ~u64(2147483647) == 18446744071562067968;
242 });
243 testBinaryNot(0b1010101010101010);
244}
245
246fn testBinaryNot(x: u16) void {
247 assertOrPanic(~x == 0b0101010101010101);
248}
249
250test "small int addition" {
251 var x: @IntType(false, 2) = 0;
252 assertOrPanic(x == 0);
253
254 x += 1;
255 assertOrPanic(x == 1);
256
257 x += 1;
258 assertOrPanic(x == 2);
259
260 x += 1;
261 assertOrPanic(x == 3);
262
263 var result: @typeOf(x) = 3;
264 assertOrPanic(@addWithOverflow(@typeOf(x), x, 1, &result));
265
266 assertOrPanic(result == 0);
267}
268
269test "float equality" {
270 const x: f64 = 0.012;
271 const y: f64 = x + 1.0;
272
273 testFloatEqualityImpl(x, y);
274 comptime testFloatEqualityImpl(x, y);
275}
276
277fn testFloatEqualityImpl(x: f64, y: f64) void {
278 const y2 = x + 1.0;
279 assertOrPanic(y == y2);
280}
281
282test "allow signed integer division/remainder when values are comptime known and positive or exact" {
283 assertOrPanic(5 / 3 == 1);
284 assertOrPanic(-5 / -3 == 1);
285 assertOrPanic(-6 / 3 == -2);
286
287 assertOrPanic(5 % 3 == 2);
288 assertOrPanic(-6 % 3 == 0);
289}
290
291test "hex float literal parsing" {
292 comptime assertOrPanic(0x1.0 == 1.0);
293}
294
295test "quad hex float literal parsing in range" {
296 const a = 0x1.af23456789bbaaab347645365cdep+5;
297 const b = 0x1.dedafcff354b6ae9758763545432p-9;
298 const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
299 const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
300}
301
302test "quad hex float literal parsing accurate" {
303 const a: f128 = 0x1.1111222233334444555566667777p+0;
304
305 // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
306 const expected: u128 = 0x3fff1111222233334444555566667777;
307 assertOrPanic(@bitCast(u128, a) == expected);
308}
309
310test "hex float literal within range" {
311 const a = 0x1.0p16383;
312 const b = 0x0.1p16387;
313 const c = 0x1.0p-16382;
314}
315
316test "truncating shift left" {
317 testShlTrunc(maxInt(u16));
318 comptime testShlTrunc(maxInt(u16));
319}
320fn testShlTrunc(x: u16) void {
321 const shifted = x << 1;
322 assertOrPanic(shifted == 65534);
323}
324
325test "truncating shift right" {
326 testShrTrunc(maxInt(u16));
327 comptime testShrTrunc(maxInt(u16));
328}
329fn testShrTrunc(x: u16) void {
330 const shifted = x >> 1;
331 assertOrPanic(shifted == 32767);
332}
333
334test "exact shift left" {
335 testShlExact(0b00110101);
336 comptime testShlExact(0b00110101);
337}
338fn testShlExact(x: u8) void {
339 const shifted = @shlExact(x, 2);
340 assertOrPanic(shifted == 0b11010100);
341}
342
343test "exact shift right" {
344 testShrExact(0b10110100);
345 comptime testShrExact(0b10110100);
346}
347fn testShrExact(x: u8) void {
348 const shifted = @shrExact(x, 2);
349 assertOrPanic(shifted == 0b00101101);
350}
351
352test "comptime_int addition" {
353 comptime {
354 assertOrPanic(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
355 assertOrPanic(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
356 }
357}
358
359test "comptime_int multiplication" {
360 comptime {
361 assertOrPanic(
362 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
363 );
364 assertOrPanic(
365 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
366 );
367 }
368}
369
370test "comptime_int shifting" {
371 comptime {
372 assertOrPanic((u128(1) << 127) == 0x80000000000000000000000000000000);
373 }
374}
375
376test "comptime_int multi-limb shift and mask" {
377 comptime {
378 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
379
380 assertOrPanic(u32(a & 0xffffffff) == 0xaaaaaaab);
381 a >>= 32;
382 assertOrPanic(u32(a & 0xffffffff) == 0xeeeeeeef);
383 a >>= 32;
384 assertOrPanic(u32(a & 0xffffffff) == 0xa0000001);
385 a >>= 32;
386 assertOrPanic(u32(a & 0xffffffff) == 0xefffffff);
387 a >>= 32;
388
389 assertOrPanic(a == 0);
390 }
391}
392
393test "comptime_int multi-limb partial shift right" {
394 comptime {
395 var a = 0x1ffffffffeeeeeeee;
396 a >>= 16;
397 assertOrPanic(a == 0x1ffffffffeeee);
398 }
399}
400
401test "xor" {
402 test_xor();
403 comptime test_xor();
404}
405
406fn test_xor() void {
407 assertOrPanic(0xFF ^ 0x00 == 0xFF);
408 assertOrPanic(0xF0 ^ 0x0F == 0xFF);
409 assertOrPanic(0xFF ^ 0xF0 == 0x0F);
410 assertOrPanic(0xFF ^ 0x0F == 0xF0);
411 assertOrPanic(0xFF ^ 0xFF == 0x00);
412}
413
414test "comptime_int xor" {
415 comptime {
416 assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
417 assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
418 assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
419 assertOrPanic(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
420 assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
421 assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
422 assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
423 assertOrPanic(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
424 }
425}
426
427test "f128" {
428 test_f128();
429 comptime test_f128();
430}
431
432fn make_f128(x: f128) f128 {
433 return x;
434}
435
436fn test_f128() void {
437 assertOrPanic(@sizeOf(f128) == 16);
438 assertOrPanic(make_f128(1.0) == 1.0);
439 assertOrPanic(make_f128(1.0) != 1.1);
440 assertOrPanic(make_f128(1.0) > 0.9);
441 assertOrPanic(make_f128(1.0) >= 0.9);
442 assertOrPanic(make_f128(1.0) >= 1.0);
443 should_not_be_zero(1.0);
444}
445
446fn should_not_be_zero(x: f128) void {
447 assertOrPanic(x != 0.0);
448}
449
450test "comptime float rem int" {
451 comptime {
452 var x = f32(1) % 2;
453 assertOrPanic(x == 1.0);
454 }
455}
456
457test "remainder division" {
458 comptime remdiv(f16);
459 comptime remdiv(f32);
460 comptime remdiv(f64);
461 comptime remdiv(f128);
462 remdiv(f16);
463 remdiv(f64);
464 remdiv(f128);
465}
466
467fn remdiv(comptime T: type) void {
468 assertOrPanic(T(1) == T(1) % T(2));
469 assertOrPanic(T(1) == T(7) % T(3));
470}
471
472test "@sqrt" {
473 testSqrt(f64, 12.0);
474 comptime testSqrt(f64, 12.0);
475 testSqrt(f32, 13.0);
476 comptime testSqrt(f32, 13.0);
477 testSqrt(f16, 13.0);
478 comptime testSqrt(f16, 13.0);
479
480 const x = 14.0;
481 const y = x * x;
482 const z = @sqrt(@typeOf(y), y);
483 comptime assertOrPanic(z == x);
484}
485
486fn testSqrt(comptime T: type, x: T) void {
487 assertOrPanic(@sqrt(T, x * x) == x);
488}
489
490test "comptime_int param and return" {
491 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
492 assertOrPanic(a == 137114567242441932203689521744947848950);
493
494 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
495 assertOrPanic(b == 985095453608931032642182098849559179469148836107390954364380);
496}
497
498fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
499 return a + b;
500}
test/stage1/behavior/merge_error_sets.zig created+21
...@@ -0,0 +1,21 @@
1const A = error{
2 FileNotFound,
3 NotDir,
4};
5const B = error{OutOfMemory};
6
7const C = A || B;
8
9fn foo() C!void {
10 return error.NotDir;
11}
12
13test "merge error sets" {
14 if (foo()) {
15 @panic("unexpected");
16 } else |err| switch (err) {
17 error.OutOfMemory => @panic("unexpected"),
18 error.FileNotFound => @panic("unexpected"),
19 error.NotDir => {},
20 }
21}
test/stage1/behavior/misc.zig created+687
...@@ -0,0 +1,687 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const mem = std.mem;
4const cstr = std.cstr;
5const builtin = @import("builtin");
6const maxInt = std.math.maxInt;
7
8// normal comment
9
10/// this is a documentation comment
11/// doc comment line 2
12fn emptyFunctionWithComments() void {}
13
14test "empty function with comments" {
15 emptyFunctionWithComments();
16}
17
18comptime {
19 @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal);
20}
21
22extern fn disabledExternFn() void {}
23
24test "call disabled extern fn" {
25 disabledExternFn();
26}
27
28test "@IntType builtin" {
29 assertOrPanic(@IntType(true, 8) == i8);
30 assertOrPanic(@IntType(true, 16) == i16);
31 assertOrPanic(@IntType(true, 32) == i32);
32 assertOrPanic(@IntType(true, 64) == i64);
33
34 assertOrPanic(@IntType(false, 8) == u8);
35 assertOrPanic(@IntType(false, 16) == u16);
36 assertOrPanic(@IntType(false, 32) == u32);
37 assertOrPanic(@IntType(false, 64) == u64);
38
39 assertOrPanic(i8.bit_count == 8);
40 assertOrPanic(i16.bit_count == 16);
41 assertOrPanic(i32.bit_count == 32);
42 assertOrPanic(i64.bit_count == 64);
43
44 assertOrPanic(i8.is_signed);
45 assertOrPanic(i16.is_signed);
46 assertOrPanic(i32.is_signed);
47 assertOrPanic(i64.is_signed);
48 assertOrPanic(isize.is_signed);
49
50 assertOrPanic(!u8.is_signed);
51 assertOrPanic(!u16.is_signed);
52 assertOrPanic(!u32.is_signed);
53 assertOrPanic(!u64.is_signed);
54 assertOrPanic(!usize.is_signed);
55}
56
57test "floating point primitive bit counts" {
58 assertOrPanic(f16.bit_count == 16);
59 assertOrPanic(f32.bit_count == 32);
60 assertOrPanic(f64.bit_count == 64);
61}
62
63test "short circuit" {
64 testShortCircuit(false, true);
65 comptime testShortCircuit(false, true);
66}
67
68fn testShortCircuit(f: bool, t: bool) void {
69 var hit_1 = f;
70 var hit_2 = f;
71 var hit_3 = f;
72 var hit_4 = f;
73
74 if (t or x: {
75 assertOrPanic(f);
76 break :x f;
77 }) {
78 hit_1 = t;
79 }
80 if (f or x: {
81 hit_2 = t;
82 break :x f;
83 }) {
84 assertOrPanic(f);
85 }
86
87 if (t and x: {
88 hit_3 = t;
89 break :x f;
90 }) {
91 assertOrPanic(f);
92 }
93 if (f and x: {
94 assertOrPanic(f);
95 break :x f;
96 }) {
97 assertOrPanic(f);
98 } else {
99 hit_4 = t;
100 }
101 assertOrPanic(hit_1);
102 assertOrPanic(hit_2);
103 assertOrPanic(hit_3);
104 assertOrPanic(hit_4);
105}
106
107test "truncate" {
108 assertOrPanic(testTruncate(0x10fd) == 0xfd);
109}
110fn testTruncate(x: u32) u8 {
111 return @truncate(u8, x);
112}
113
114fn first4KeysOfHomeRow() []const u8 {
115 return "aoeu";
116}
117
118test "return string from function" {
119 assertOrPanic(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
120}
121
122const g1: i32 = 1233 + 1;
123var g2: i32 = 0;
124
125test "global variables" {
126 assertOrPanic(g2 == 0);
127 g2 = g1;
128 assertOrPanic(g2 == 1234);
129}
130
131test "memcpy and memset intrinsics" {
132 var foo: [20]u8 = undefined;
133 var bar: [20]u8 = undefined;
134
135 @memset(foo[0..].ptr, 'A', foo.len);
136 @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
137
138 if (bar[11] != 'A') unreachable;
139}
140
141test "builtin static eval" {
142 const x: i32 = comptime x: {
143 break :x 1 + 2 + 3;
144 };
145 assertOrPanic(x == comptime 6);
146}
147
148test "slicing" {
149 var array: [20]i32 = undefined;
150
151 array[5] = 1234;
152
153 var slice = array[5..10];
154
155 if (slice.len != 5) unreachable;
156
157 const ptr = &slice[0];
158 if (ptr.* != 1234) unreachable;
159
160 var slice_rest = array[10..];
161 if (slice_rest.len != 10) unreachable;
162}
163
164test "constant equal function pointers" {
165 const alias = emptyFn;
166 assertOrPanic(comptime x: {
167 break :x emptyFn == alias;
168 });
169}
170
171fn emptyFn() void {}
172
173test "hex escape" {
174 assertOrPanic(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
175}
176
177test "string concatenation" {
178 assertOrPanic(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
179}
180
181test "array mult operator" {
182 assertOrPanic(mem.eql(u8, "ab" ** 5, "ababababab"));
183}
184
185test "string escapes" {
186 assertOrPanic(mem.eql(u8, "\"", "\x22"));
187 assertOrPanic(mem.eql(u8, "\'", "\x27"));
188 assertOrPanic(mem.eql(u8, "\n", "\x0a"));
189 assertOrPanic(mem.eql(u8, "\r", "\x0d"));
190 assertOrPanic(mem.eql(u8, "\t", "\x09"));
191 assertOrPanic(mem.eql(u8, "\\", "\x5c"));
192 assertOrPanic(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
193}
194
195test "multiline string" {
196 const s1 =
197 \\one
198 \\two)
199 \\three
200 ;
201 const s2 = "one\ntwo)\nthree";
202 assertOrPanic(mem.eql(u8, s1, s2));
203}
204
205test "multiline C string" {
206 const s1 =
207 c\\one
208 c\\two)
209 c\\three
210 ;
211 const s2 = c"one\ntwo)\nthree";
212 assertOrPanic(cstr.cmp(s1, s2) == 0);
213}
214
215test "type equality" {
216 assertOrPanic(*const u8 != *u8);
217}
218
219const global_a: i32 = 1234;
220const global_b: *const i32 = &global_a;
221const global_c: *const f32 = @ptrCast(*const f32, global_b);
222test "compile time global reinterpret" {
223 const d = @ptrCast(*const i32, global_c);
224 assertOrPanic(d.* == 1234);
225}
226
227test "explicit cast maybe pointers" {
228 const a: ?*i32 = undefined;
229 const b: ?*f32 = @ptrCast(?*f32, a);
230}
231
232test "generic malloc free" {
233 const a = memAlloc(u8, 10) catch unreachable;
234 memFree(u8, a);
235}
236var some_mem: [100]u8 = undefined;
237fn memAlloc(comptime T: type, n: usize) anyerror![]T {
238 return @ptrCast([*]T, &some_mem[0])[0..n];
239}
240fn memFree(comptime T: type, memory: []T) void {}
241
242test "cast undefined" {
243 const array: [100]u8 = undefined;
244 const slice = ([]const u8)(array);
245 testCastUndefined(slice);
246}
247fn testCastUndefined(x: []const u8) void {}
248
249test "cast small unsigned to larger signed" {
250 assertOrPanic(castSmallUnsignedToLargerSigned1(200) == i16(200));
251 assertOrPanic(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
252}
253fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
254 return x;
255}
256fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
257 return x;
258}
259
260test "implicit cast after unreachable" {
261 assertOrPanic(outer() == 1234);
262}
263fn inner() i32 {
264 return 1234;
265}
266fn outer() i64 {
267 return inner();
268}
269
270test "pointer dereferencing" {
271 var x = i32(3);
272 const y = &x;
273
274 y.* += 1;
275
276 assertOrPanic(x == 4);
277 assertOrPanic(y.* == 4);
278}
279
280test "call result of if else expression" {
281 assertOrPanic(mem.eql(u8, f2(true), "a"));
282 assertOrPanic(mem.eql(u8, f2(false), "b"));
283}
284fn f2(x: bool) []const u8 {
285 return (if (x) fA else fB)();
286}
287fn fA() []const u8 {
288 return "a";
289}
290fn fB() []const u8 {
291 return "b";
292}
293
294test "const expression eval handling of variables" {
295 var x = true;
296 while (x) {
297 x = false;
298 }
299}
300
301test "constant enum initialization with differing sizes" {
302 test3_1(test3_foo);
303 test3_2(test3_bar);
304}
305const Test3Foo = union(enum) {
306 One: void,
307 Two: f32,
308 Three: Test3Point,
309};
310const Test3Point = struct {
311 x: i32,
312 y: i32,
313};
314const test3_foo = Test3Foo{
315 .Three = Test3Point{
316 .x = 3,
317 .y = 4,
318 },
319};
320const test3_bar = Test3Foo{ .Two = 13 };
321fn test3_1(f: Test3Foo) void {
322 switch (f) {
323 Test3Foo.Three => |pt| {
324 assertOrPanic(pt.x == 3);
325 assertOrPanic(pt.y == 4);
326 },
327 else => unreachable,
328 }
329}
330fn test3_2(f: Test3Foo) void {
331 switch (f) {
332 Test3Foo.Two => |x| {
333 assertOrPanic(x == 13);
334 },
335 else => unreachable,
336 }
337}
338
339test "character literals" {
340 assertOrPanic('\'' == single_quote);
341}
342const single_quote = '\'';
343
344test "take address of parameter" {
345 testTakeAddressOfParameter(12.34);
346}
347fn testTakeAddressOfParameter(f: f32) void {
348 const f_ptr = &f;
349 assertOrPanic(f_ptr.* == 12.34);
350}
351
352test "pointer comparison" {
353 const a = ([]const u8)("a");
354 const b = &a;
355 assertOrPanic(ptrEql(b, b));
356}
357fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
358 return a == b;
359}
360
361test "C string concatenation" {
362 const a = c"OK" ++ c" IT " ++ c"WORKED";
363 const b = c"OK IT WORKED";
364
365 const len = cstr.len(b);
366 const len_with_null = len + 1;
367 {
368 var i: u32 = 0;
369 while (i < len_with_null) : (i += 1) {
370 assertOrPanic(a[i] == b[i]);
371 }
372 }
373 assertOrPanic(a[len] == 0);
374 assertOrPanic(b[len] == 0);
375}
376
377test "cast slice to u8 slice" {
378 assertOrPanic(@sizeOf(i32) == 4);
379 var big_thing_array = []i32{ 1, 2, 3, 4 };
380 const big_thing_slice: []i32 = big_thing_array[0..];
381 const bytes = @sliceToBytes(big_thing_slice);
382 assertOrPanic(bytes.len == 4 * 4);
383 bytes[4] = 0;
384 bytes[5] = 0;
385 bytes[6] = 0;
386 bytes[7] = 0;
387 assertOrPanic(big_thing_slice[1] == 0);
388 const big_thing_again = @bytesToSlice(i32, bytes);
389 assertOrPanic(big_thing_again[2] == 3);
390 big_thing_again[2] = -1;
391 assertOrPanic(bytes[8] == maxInt(u8));
392 assertOrPanic(bytes[9] == maxInt(u8));
393 assertOrPanic(bytes[10] == maxInt(u8));
394 assertOrPanic(bytes[11] == maxInt(u8));
395}
396
397test "pointer to void return type" {
398 testPointerToVoidReturnType() catch unreachable;
399}
400fn testPointerToVoidReturnType() anyerror!void {
401 const a = testPointerToVoidReturnType2();
402 return a.*;
403}
404const test_pointer_to_void_return_type_x = void{};
405fn testPointerToVoidReturnType2() *const void {
406 return &test_pointer_to_void_return_type_x;
407}
408
409test "non const ptr to aliased type" {
410 const int = i32;
411 assertOrPanic(?*int == ?*i32);
412}
413
414test "array 2D const double ptr" {
415 const rect_2d_vertexes = [][1]f32{
416 []f32{1.0},
417 []f32{2.0},
418 };
419 testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
420}
421
422fn testArray2DConstDoublePtr(ptr: *const f32) void {
423 const ptr2 = @ptrCast([*]const f32, ptr);
424 assertOrPanic(ptr2[0] == 1.0);
425 assertOrPanic(ptr2[1] == 2.0);
426}
427
428const Tid = builtin.TypeId;
429const AStruct = struct {
430 x: i32,
431};
432const AnEnum = enum {
433 One,
434 Two,
435};
436const AUnionEnum = union(enum) {
437 One: i32,
438 Two: void,
439};
440const AUnion = union {
441 One: void,
442 Two: void,
443};
444
445test "@typeId" {
446 comptime {
447 assertOrPanic(@typeId(type) == Tid.Type);
448 assertOrPanic(@typeId(void) == Tid.Void);
449 assertOrPanic(@typeId(bool) == Tid.Bool);
450 assertOrPanic(@typeId(noreturn) == Tid.NoReturn);
451 assertOrPanic(@typeId(i8) == Tid.Int);
452 assertOrPanic(@typeId(u8) == Tid.Int);
453 assertOrPanic(@typeId(i64) == Tid.Int);
454 assertOrPanic(@typeId(u64) == Tid.Int);
455 assertOrPanic(@typeId(f32) == Tid.Float);
456 assertOrPanic(@typeId(f64) == Tid.Float);
457 assertOrPanic(@typeId(*f32) == Tid.Pointer);
458 assertOrPanic(@typeId([2]u8) == Tid.Array);
459 assertOrPanic(@typeId(AStruct) == Tid.Struct);
460 assertOrPanic(@typeId(@typeOf(1)) == Tid.ComptimeInt);
461 assertOrPanic(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
462 assertOrPanic(@typeId(@typeOf(undefined)) == Tid.Undefined);
463 assertOrPanic(@typeId(@typeOf(null)) == Tid.Null);
464 assertOrPanic(@typeId(?i32) == Tid.Optional);
465 assertOrPanic(@typeId(anyerror!i32) == Tid.ErrorUnion);
466 assertOrPanic(@typeId(anyerror) == Tid.ErrorSet);
467 assertOrPanic(@typeId(AnEnum) == Tid.Enum);
468 assertOrPanic(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
469 assertOrPanic(@typeId(AUnionEnum) == Tid.Union);
470 assertOrPanic(@typeId(AUnion) == Tid.Union);
471 assertOrPanic(@typeId(fn () void) == Tid.Fn);
472 assertOrPanic(@typeId(@typeOf(builtin)) == Tid.Namespace);
473 // TODO bound fn
474 // TODO arg tuple
475 // TODO opaque
476 }
477}
478
479test "@typeName" {
480 const Struct = struct {};
481 const Union = union {
482 unused: u8,
483 };
484 const Enum = enum {
485 Unused,
486 };
487 comptime {
488 assertOrPanic(mem.eql(u8, @typeName(i64), "i64"));
489 assertOrPanic(mem.eql(u8, @typeName(*usize), "*usize"));
490 // https://github.com/ziglang/zig/issues/675
491 assertOrPanic(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
492 assertOrPanic(mem.eql(u8, @typeName(Struct), "Struct"));
493 assertOrPanic(mem.eql(u8, @typeName(Union), "Union"));
494 assertOrPanic(mem.eql(u8, @typeName(Enum), "Enum"));
495 }
496}
497
498fn TypeFromFn(comptime T: type) type {
499 return struct {};
500}
501
502test "double implicit cast in same expression" {
503 var x = i32(u16(nine()));
504 assertOrPanic(x == 9);
505}
506fn nine() u8 {
507 return 9;
508}
509
510test "global variable initialized to global variable array element" {
511 assertOrPanic(global_ptr == &gdt[0]);
512}
513const GDTEntry = struct {
514 field: i32,
515};
516var gdt = []GDTEntry{
517 GDTEntry{ .field = 1 },
518 GDTEntry{ .field = 2 },
519};
520var global_ptr = &gdt[0];
521
522// can't really run this test but we can make sure it has no compile error
523// and generates code
524const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
525export fn writeToVRam() void {
526 vram[0] = 'X';
527}
528
529const OpaqueA = @OpaqueType();
530const OpaqueB = @OpaqueType();
531test "@OpaqueType" {
532 assertOrPanic(*OpaqueA != *OpaqueB);
533 assertOrPanic(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
534 assertOrPanic(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
535}
536
537test "variable is allowed to be a pointer to an opaque type" {
538 var x: i32 = 1234;
539 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
540}
541fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
542 var a = ptr;
543 return a;
544}
545
546test "comptime if inside runtime while which unconditionally breaks" {
547 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
548 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
549}
550fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
551 while (cond) {
552 if (false) {}
553 break;
554 }
555}
556
557test "implicit comptime while" {
558 while (false) {
559 @compileError("bad");
560 }
561}
562
563fn fnThatClosesOverLocalConst() type {
564 const c = 1;
565 return struct {
566 fn g() i32 {
567 return c;
568 }
569 };
570}
571
572test "function closes over local const" {
573 const x = fnThatClosesOverLocalConst().g();
574 assertOrPanic(x == 1);
575}
576
577test "cold function" {
578 thisIsAColdFn();
579 comptime thisIsAColdFn();
580}
581
582fn thisIsAColdFn() void {
583 @setCold(true);
584}
585
586const PackedStruct = packed struct {
587 a: u8,
588 b: u8,
589};
590const PackedUnion = packed union {
591 a: u8,
592 b: u32,
593};
594const PackedEnum = packed enum {
595 A,
596 B,
597};
598
599test "packed struct, enum, union parameters in extern function" {
600 testPackedStuff(&(PackedStruct{
601 .a = 1,
602 .b = 2,
603 }), &(PackedUnion{ .a = 1 }), PackedEnum.A);
604}
605
606export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {}
607
608test "slicing zero length array" {
609 const s1 = ""[0..];
610 const s2 = ([]u32{})[0..];
611 assertOrPanic(s1.len == 0);
612 assertOrPanic(s2.len == 0);
613 assertOrPanic(mem.eql(u8, s1, ""));
614 assertOrPanic(mem.eql(u32, s2, []u32{}));
615}
616
617const addr1 = @ptrCast(*const u8, emptyFn);
618test "comptime cast fn to ptr" {
619 const addr2 = @ptrCast(*const u8, emptyFn);
620 comptime assertOrPanic(addr1 == addr2);
621}
622
623test "equality compare fn ptrs" {
624 var a = emptyFn;
625 assertOrPanic(a == a);
626}
627
628test "self reference through fn ptr field" {
629 const S = struct {
630 const A = struct {
631 f: fn (A) u8,
632 };
633
634 fn foo(a: A) u8 {
635 return 12;
636 }
637 };
638 var a: S.A = undefined;
639 a.f = S.foo;
640 assertOrPanic(a.f(a) == 12);
641}
642
643test "volatile load and store" {
644 var number: i32 = 1234;
645 const ptr = (*volatile i32)(&number);
646 ptr.* += 1;
647 assertOrPanic(ptr.* == 1235);
648}
649
650test "slice string literal has type []const u8" {
651 comptime {
652 assertOrPanic(@typeOf("aoeu"[0..]) == []const u8);
653 const array = []i32{ 1, 2, 3, 4 };
654 assertOrPanic(@typeOf(array[0..]) == []const i32);
655 }
656}
657
658test "pointer child field" {
659 assertOrPanic((*u32).Child == u32);
660}
661
662test "struct inside function" {
663 testStructInFn();
664 comptime testStructInFn();
665}
666
667fn testStructInFn() void {
668 const BlockKind = u32;
669
670 const Block = struct {
671 kind: BlockKind,
672 };
673
674 var block = Block{ .kind = 1234 };
675
676 block.kind += 1;
677
678 assertOrPanic(block.kind == 1235);
679}
680
681test "fn call returning scalar optional in equality expression" {
682 assertOrPanic(getNull() == null);
683}
684
685fn getNull() ?*i32 {
686 return null;
687}
test/stage1/behavior/namespace_depends_on_compile_var/a.zig created+1
...@@ -0,0 +1 @@
1pub const a_bool = true;
test/stage1/behavior/namespace_depends_on_compile_var/b.zig created+1
...@@ -0,0 +1 @@
1pub const a_bool = false;
test/stage1/behavior/namespace_depends_on_compile_var/index.zig created+14
...@@ -0,0 +1,14 @@
1const builtin = @import("builtin");
2const assertOrPanic = @import("std").debug.assertOrPanic;
3
4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {
6 assertOrPanic(some_namespace.a_bool);
7 } else {
8 assertOrPanic(!some_namespace.a_bool);
9 }
10}
11const some_namespace = switch (builtin.os) {
12 builtin.Os.linux => @import("a.zig"),
13 else => @import("b.zig"),
14};
test/stage1/behavior/new_stack_call.zig created+26
...@@ -0,0 +1,26 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4var new_stack_bytes: [1024]u8 = undefined;
5
6test "calling a function with a new stack" {
7 const arg = 1234;
8
9 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
10 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
11 _ = targetFunction(arg);
12
13 assertOrPanic(arg == 1234);
14 assertOrPanic(a < b);
15}
16
17fn targetFunction(x: i32) usize {
18 assertOrPanic(x == 1234);
19
20 var local_variable: i32 = 42;
21 const ptr = &local_variable;
22 ptr.* += 1;
23
24 assertOrPanic(local_variable == 43);
25 return @ptrToInt(ptr);
26}
test/stage1/behavior/null.zig created+162
...@@ -0,0 +1,162 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "optional type" {
4 const x: ?bool = true;
5
6 if (x) |y| {
7 if (y) {
8 // OK
9 } else {
10 unreachable;
11 }
12 } else {
13 unreachable;
14 }
15
16 const next_x: ?i32 = null;
17
18 const z = next_x orelse 1234;
19
20 assertOrPanic(z == 1234);
21
22 const final_x: ?i32 = 13;
23
24 const num = final_x orelse unreachable;
25
26 assertOrPanic(num == 13);
27}
28
29test "test maybe object and get a pointer to the inner value" {
30 var maybe_bool: ?bool = true;
31
32 if (maybe_bool) |*b| {
33 b.* = false;
34 }
35
36 assertOrPanic(maybe_bool.? == false);
37}
38
39test "rhs maybe unwrap return" {
40 const x: ?bool = true;
41 const y = x orelse return;
42}
43
44test "maybe return" {
45 maybeReturnImpl();
46 comptime maybeReturnImpl();
47}
48
49fn maybeReturnImpl() void {
50 assertOrPanic(foo(1235).?);
51 if (foo(null) != null) unreachable;
52 assertOrPanic(!foo(1234).?);
53}
54
55fn foo(x: ?i32) ?bool {
56 const value = x orelse return null;
57 return value > 1234;
58}
59
60test "if var maybe pointer" {
61 assertOrPanic(shouldBeAPlus1(Particle{
62 .a = 14,
63 .b = 1,
64 .c = 1,
65 .d = 1,
66 }) == 15);
67}
68fn shouldBeAPlus1(p: Particle) u64 {
69 var maybe_particle: ?Particle = p;
70 if (maybe_particle) |*particle| {
71 particle.a += 1;
72 }
73 if (maybe_particle) |particle| {
74 return particle.a;
75 }
76 return 0;
77}
78const Particle = struct {
79 a: u64,
80 b: u64,
81 c: u64,
82 d: u64,
83};
84
85test "null literal outside function" {
86 const is_null = here_is_a_null_literal.context == null;
87 assertOrPanic(is_null);
88
89 const is_non_null = here_is_a_null_literal.context != null;
90 assertOrPanic(!is_non_null);
91}
92const SillyStruct = struct {
93 context: ?i32,
94};
95const here_is_a_null_literal = SillyStruct{ .context = null };
96
97test "test null runtime" {
98 testTestNullRuntime(null);
99}
100fn testTestNullRuntime(x: ?i32) void {
101 assertOrPanic(x == null);
102 assertOrPanic(!(x != null));
103}
104
105test "optional void" {
106 optionalVoidImpl();
107 comptime optionalVoidImpl();
108}
109
110fn optionalVoidImpl() void {
111 assertOrPanic(bar(null) == null);
112 assertOrPanic(bar({}) != null);
113}
114
115fn bar(x: ?void) ?void {
116 if (x) |_| {
117 return {};
118 } else {
119 return null;
120 }
121}
122
123const StructWithOptional = struct {
124 field: ?i32,
125};
126
127var struct_with_optional: StructWithOptional = undefined;
128
129test "unwrap optional which is field of global var" {
130 struct_with_optional.field = null;
131 if (struct_with_optional.field) |payload| {
132 unreachable;
133 }
134 struct_with_optional.field = 1234;
135 if (struct_with_optional.field) |payload| {
136 assertOrPanic(payload == 1234);
137 } else {
138 unreachable;
139 }
140}
141
142test "null with default unwrap" {
143 const x: i32 = null orelse 1;
144 assertOrPanic(x == 1);
145}
146
147test "optional types" {
148 comptime {
149 const opt_type_struct = StructWithOptionalType{ .t = u8 };
150 assertOrPanic(opt_type_struct.t != null and opt_type_struct.t.? == u8);
151 }
152}
153
154const StructWithOptionalType = struct {
155 t: ?type,
156};
157
158test "optional pointer to 0 bit type null value at runtime" {
159 const EmptyStruct = struct {};
160 var x: ?*EmptyStruct = null;
161 assertOrPanic(x == null);
162}
test/stage1/behavior/optional.zig created+81
...@@ -0,0 +1,81 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3pub const EmptyStruct = struct {};
4
5test "optional pointer to size zero struct" {
6 var e = EmptyStruct{};
7 var o: ?*EmptyStruct = &e;
8 assertOrPanic(o != null);
9}
10
11test "equality compare nullable pointers" {
12 testNullPtrsEql();
13 comptime testNullPtrsEql();
14}
15
16fn testNullPtrsEql() void {
17 var number: i32 = 1234;
18
19 var x: ?*i32 = null;
20 var y: ?*i32 = null;
21 assertOrPanic(x == y);
22 y = &number;
23 assertOrPanic(x != y);
24 assertOrPanic(x != &number);
25 assertOrPanic(&number != x);
26 x = &number;
27 assertOrPanic(x == y);
28 assertOrPanic(x == &number);
29 assertOrPanic(&number == x);
30}
31
32test "address of unwrap optional" {
33 const S = struct {
34 const Foo = struct {
35 a: i32,
36 };
37
38 var global: ?Foo = null;
39
40 pub fn getFoo() anyerror!*Foo {
41 return &global.?;
42 }
43 };
44 S.global = S.Foo{ .a = 1234 };
45 const foo = S.getFoo() catch unreachable;
46 assertOrPanic(foo.a == 1234);
47}
48
49test "passing an optional integer as a parameter" {
50 const S = struct {
51 fn entry() bool {
52 var x: i32 = 1234;
53 return foo(x);
54 }
55
56 fn foo(x: ?i32) bool {
57 return x.? == 1234;
58 }
59 };
60 assertOrPanic(S.entry());
61 comptime assertOrPanic(S.entry());
62}
63
64test "unwrap function call with optional pointer return value" {
65 const S = struct {
66 fn entry() void {
67 assertOrPanic(foo().?.* == 1234);
68 assertOrPanic(bar() == null);
69 }
70 const global: i32 = 1234;
71 fn foo() ?*const i32 {
72 return &global;
73 }
74 fn bar() ?*i32 {
75 return null;
76 }
77 };
78 S.entry();
79 // TODO https://github.com/ziglang/zig/issues/1901
80 //comptime S.entry();
81}
test/stage1/behavior/pointers.zig created+44
...@@ -0,0 +1,44 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "dereference pointer" {
5 comptime testDerefPtr();
6 testDerefPtr();
7}
8
9fn testDerefPtr() void {
10 var x: i32 = 1234;
11 var y = &x;
12 y.* += 1;
13 assertOrPanic(x == 1235);
14}
15
16test "pointer arithmetic" {
17 var ptr = c"abcd";
18
19 assertOrPanic(ptr[0] == 'a');
20 ptr += 1;
21 assertOrPanic(ptr[0] == 'b');
22 ptr += 1;
23 assertOrPanic(ptr[0] == 'c');
24 ptr += 1;
25 assertOrPanic(ptr[0] == 'd');
26 ptr += 1;
27 assertOrPanic(ptr[0] == 0);
28 ptr -= 1;
29 assertOrPanic(ptr[0] == 'd');
30 ptr -= 1;
31 assertOrPanic(ptr[0] == 'c');
32 ptr -= 1;
33 assertOrPanic(ptr[0] == 'b');
34 ptr -= 1;
35 assertOrPanic(ptr[0] == 'a');
36}
37
38test "double pointer parsing" {
39 comptime assertOrPanic(PtrOf(PtrOf(i32)) == **i32);
40}
41
42fn PtrOf(comptime T: type) type {
43 return *T;
44}
test/stage1/behavior/popcount.zig created+25
...@@ -0,0 +1,25 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "@popCount" {
4 comptime testPopCount();
5 testPopCount();
6}
7
8fn testPopCount() void {
9 {
10 var x: u32 = 0xaa;
11 assertOrPanic(@popCount(x) == 4);
12 }
13 {
14 var x: u32 = 0xaaaaaaaa;
15 assertOrPanic(@popCount(x) == 16);
16 }
17 {
18 var x: i16 = -1;
19 assertOrPanic(@popCount(x) == 16);
20 }
21 comptime {
22 assertOrPanic(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
23 }
24}
25
test/stage1/behavior/ptrcast.zig created+52
...@@ -0,0 +1,52 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "reinterpret bytes as integer with nonzero offset" {
6 testReinterpretBytesAsInteger();
7 comptime testReinterpretBytesAsInteger();
8}
9
10fn testReinterpretBytesAsInteger() void {
11 const bytes = "\x12\x34\x56\x78\xab";
12 const expected = switch (builtin.endian) {
13 builtin.Endian.Little => 0xab785634,
14 builtin.Endian.Big => 0x345678ab,
15 };
16 assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
17}
18
19test "reinterpret bytes of an array into an extern struct" {
20 testReinterpretBytesAsExternStruct();
21 comptime testReinterpretBytesAsExternStruct();
22}
23
24fn testReinterpretBytesAsExternStruct() void {
25 var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 };
26
27 const S = extern struct {
28 a: u8,
29 b: u16,
30 c: u8,
31 };
32
33 var ptr = @ptrCast(*const S, &bytes);
34 var val = ptr.c;
35 assertOrPanic(val == 5);
36}
37
38test "reinterpret struct field at comptime" {
39 const numLittle = comptime Bytes.init(0x12345678);
40 assertOrPanic(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes));
41}
42
43const Bytes = struct {
44 bytes: [4]u8,
45
46 pub fn init(v: u32) Bytes {
47 var res: Bytes = undefined;
48 @ptrCast(*align(1) u32, &res.bytes).* = v;
49
50 return res;
51 }
52};
test/stage1/behavior/pub_enum/index.zig created+13
...@@ -0,0 +1,13 @@
1const other = @import("other.zig");
2const assertOrPanic = @import("std").debug.assertOrPanic;
3
4test "pub enum" {
5 pubEnumTest(other.APubEnum.Two);
6}
7fn pubEnumTest(foo: other.APubEnum) void {
8 assertOrPanic(foo == other.APubEnum.Two);
9}
10
11test "cast with imported symbol" {
12 assertOrPanic(other.size_t(42) == 42);
13}
test/stage1/behavior/pub_enum/other.zig created+6
...@@ -0,0 +1,6 @@
1pub const APubEnum = enum {
2 One,
3 Two,
4 Three,
5};
6pub const size_t = u64;
test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig created+37
...@@ -0,0 +1,37 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4var ok: bool = false;
5test "reference a variable in an if after an if in the 2nd switch prong" {
6 foo(true, Num.Two, false, "aoeu");
7 assertOrPanic(!ok);
8 foo(false, Num.One, false, "aoeu");
9 assertOrPanic(!ok);
10 foo(true, Num.One, false, "aoeu");
11 assertOrPanic(ok);
12}
13
14const Num = enum {
15 One,
16 Two,
17};
18
19fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
20 switch (k) {
21 Num.Two => {},
22 Num.One => {
23 if (c) {
24 const output_path = b;
25
26 if (c2) {}
27
28 a(output_path);
29 }
30 },
31 }
32}
33
34fn a(x: []const u8) void {
35 assertOrPanic(mem.eql(u8, x, "aoeu"));
36 ok = true;
37}
test/stage1/behavior/reflection.zig created+96
...@@ -0,0 +1,96 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3const reflection = @This();
4
5test "reflection: array, pointer, optional, error union type child" {
6 comptime {
7 assertOrPanic(([10]u8).Child == u8);
8 assertOrPanic((*u8).Child == u8);
9 assertOrPanic((anyerror!u8).Payload == u8);
10 assertOrPanic((?u8).Child == u8);
11 }
12}
13
14test "reflection: function return type, var args, and param types" {
15 comptime {
16 assertOrPanic(@typeOf(dummy).ReturnType == i32);
17 assertOrPanic(!@typeOf(dummy).is_var_args);
18 assertOrPanic(@typeOf(dummy_varargs).is_var_args);
19 assertOrPanic(@typeOf(dummy).arg_count == 3);
20 assertOrPanic(@ArgType(@typeOf(dummy), 0) == bool);
21 assertOrPanic(@ArgType(@typeOf(dummy), 1) == i32);
22 assertOrPanic(@ArgType(@typeOf(dummy), 2) == f32);
23 }
24}
25
26fn dummy(a: bool, b: i32, c: f32) i32 {
27 return 1234;
28}
29fn dummy_varargs(args: ...) void {}
30
31test "reflection: struct member types and names" {
32 comptime {
33 assertOrPanic(@memberCount(Foo) == 3);
34
35 assertOrPanic(@memberType(Foo, 0) == i32);
36 assertOrPanic(@memberType(Foo, 1) == bool);
37 assertOrPanic(@memberType(Foo, 2) == void);
38
39 assertOrPanic(mem.eql(u8, @memberName(Foo, 0), "one"));
40 assertOrPanic(mem.eql(u8, @memberName(Foo, 1), "two"));
41 assertOrPanic(mem.eql(u8, @memberName(Foo, 2), "three"));
42 }
43}
44
45test "reflection: enum member types and names" {
46 comptime {
47 assertOrPanic(@memberCount(Bar) == 4);
48
49 assertOrPanic(@memberType(Bar, 0) == void);
50 assertOrPanic(@memberType(Bar, 1) == i32);
51 assertOrPanic(@memberType(Bar, 2) == bool);
52 assertOrPanic(@memberType(Bar, 3) == f64);
53
54 assertOrPanic(mem.eql(u8, @memberName(Bar, 0), "One"));
55 assertOrPanic(mem.eql(u8, @memberName(Bar, 1), "Two"));
56 assertOrPanic(mem.eql(u8, @memberName(Bar, 2), "Three"));
57 assertOrPanic(mem.eql(u8, @memberName(Bar, 3), "Four"));
58 }
59}
60
61test "reflection: @field" {
62 var f = Foo{
63 .one = 42,
64 .two = true,
65 .three = void{},
66 };
67
68 assertOrPanic(f.one == f.one);
69 assertOrPanic(@field(f, "o" ++ "ne") == f.one);
70 assertOrPanic(@field(f, "t" ++ "wo") == f.two);
71 assertOrPanic(@field(f, "th" ++ "ree") == f.three);
72 assertOrPanic(@field(Foo, "const" ++ "ant") == Foo.constant);
73 assertOrPanic(@field(Bar, "O" ++ "ne") == Bar.One);
74 assertOrPanic(@field(Bar, "T" ++ "wo") == Bar.Two);
75 assertOrPanic(@field(Bar, "Th" ++ "ree") == Bar.Three);
76 assertOrPanic(@field(Bar, "F" ++ "our") == Bar.Four);
77 assertOrPanic(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
78 @field(f, "o" ++ "ne") = 4;
79 assertOrPanic(f.one == 4);
80}
81
82const Foo = struct {
83 const constant = 52;
84
85 one: i32,
86 two: bool,
87 three: void,
88};
89
90const Bar = union(enum) {
91 One: void,
92 Two: i32,
93 Three: bool,
94 Four: f64,
95};
96
test/stage1/behavior/sizeof_and_typeof.zig created+69
...@@ -0,0 +1,69 @@
1const builtin = @import("builtin");
2const assertOrPanic = @import("std").debug.assertOrPanic;
3
4test "@sizeOf and @typeOf" {
5 const y: @typeOf(x) = 120;
6 assertOrPanic(@sizeOf(@typeOf(y)) == 2);
7}
8const x: u16 = 13;
9const z: @typeOf(x) = 19;
10
11const A = struct {
12 a: u8,
13 b: u32,
14 c: u8,
15 d: u3,
16 e: u5,
17 f: u16,
18 g: u16,
19};
20
21const P = packed struct {
22 a: u8,
23 b: u32,
24 c: u8,
25 d: u3,
26 e: u5,
27 f: u16,
28 g: u16,
29};
30
31test "@byteOffsetOf" {
32 // Packed structs have fixed memory layout
33 assertOrPanic(@byteOffsetOf(P, "a") == 0);
34 assertOrPanic(@byteOffsetOf(P, "b") == 1);
35 assertOrPanic(@byteOffsetOf(P, "c") == 5);
36 assertOrPanic(@byteOffsetOf(P, "d") == 6);
37 assertOrPanic(@byteOffsetOf(P, "e") == 6);
38 assertOrPanic(@byteOffsetOf(P, "f") == 7);
39 assertOrPanic(@byteOffsetOf(P, "g") == 9);
40
41 // Normal struct fields can be moved/padded
42 var a: A = undefined;
43 assertOrPanic(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
44 assertOrPanic(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
45 assertOrPanic(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
46 assertOrPanic(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
47 assertOrPanic(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
48 assertOrPanic(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
49 assertOrPanic(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
50}
51
52test "@bitOffsetOf" {
53 // Packed structs have fixed memory layout
54 assertOrPanic(@bitOffsetOf(P, "a") == 0);
55 assertOrPanic(@bitOffsetOf(P, "b") == 8);
56 assertOrPanic(@bitOffsetOf(P, "c") == 40);
57 assertOrPanic(@bitOffsetOf(P, "d") == 48);
58 assertOrPanic(@bitOffsetOf(P, "e") == 51);
59 assertOrPanic(@bitOffsetOf(P, "f") == 56);
60 assertOrPanic(@bitOffsetOf(P, "g") == 72);
61
62 assertOrPanic(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
63 assertOrPanic(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
64 assertOrPanic(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
65 assertOrPanic(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
66 assertOrPanic(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
67 assertOrPanic(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
68 assertOrPanic(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
69}
test/stage1/behavior/slice.zig created+40
...@@ -0,0 +1,40 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4const x = @intToPtr([*]i32, 0x1000)[0..0x500];
5const y = x[0x100..];
6test "compile time slice of pointer to hard coded address" {
7 assertOrPanic(@ptrToInt(x.ptr) == 0x1000);
8 assertOrPanic(x.len == 0x500);
9
10 assertOrPanic(@ptrToInt(y.ptr) == 0x1100);
11 assertOrPanic(y.len == 0x400);
12}
13
14test "slice child property" {
15 var array: [5]i32 = undefined;
16 var slice = array[0..];
17 assertOrPanic(@typeOf(slice).Child == i32);
18}
19
20test "runtime safety lets us slice from len..len" {
21 var an_array = []u8{
22 1,
23 2,
24 3,
25 };
26 assertOrPanic(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
27}
28
29fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
30 return a_slice[start..end];
31}
32
33test "implicitly cast array of size 0 to slice" {
34 var msg = []u8{};
35 assertLenIsZero(msg);
36}
37
38fn assertLenIsZero(msg: []const u8) void {
39 assertOrPanic(msg.len == 0);
40}
test/stage1/behavior/struct.zig created+470
...@@ -0,0 +1,470 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const StructWithNoFields = struct {
7 fn add(a: i32, b: i32) i32 {
8 return a + b;
9 }
10};
11const empty_global_instance = StructWithNoFields{};
12
13test "call struct static method" {
14 const result = StructWithNoFields.add(3, 4);
15 assertOrPanic(result == 7);
16}
17
18test "return empty struct instance" {
19 _ = returnEmptyStructInstance();
20}
21fn returnEmptyStructInstance() StructWithNoFields {
22 return empty_global_instance;
23}
24
25const should_be_11 = StructWithNoFields.add(5, 6);
26
27test "invoke static method in global scope" {
28 assertOrPanic(should_be_11 == 11);
29}
30
31test "void struct fields" {
32 const foo = VoidStructFieldsFoo{
33 .a = void{},
34 .b = 1,
35 .c = void{},
36 };
37 assertOrPanic(foo.b == 1);
38 assertOrPanic(@sizeOf(VoidStructFieldsFoo) == 4);
39}
40const VoidStructFieldsFoo = struct {
41 a: void,
42 b: i32,
43 c: void,
44};
45
46test "structs" {
47 var foo: StructFoo = undefined;
48 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
49 foo.a += 1;
50 foo.b = foo.a == 1;
51 testFoo(foo);
52 testMutation(&foo);
53 assertOrPanic(foo.c == 100);
54}
55const StructFoo = struct {
56 a: i32,
57 b: bool,
58 c: f32,
59};
60fn testFoo(foo: StructFoo) void {
61 assertOrPanic(foo.b);
62}
63fn testMutation(foo: *StructFoo) void {
64 foo.c = 100;
65}
66
67const Node = struct {
68 val: Val,
69 next: *Node,
70};
71
72const Val = struct {
73 x: i32,
74};
75
76test "struct point to self" {
77 var root: Node = undefined;
78 root.val.x = 1;
79
80 var node: Node = undefined;
81 node.next = &root;
82 node.val.x = 2;
83
84 root.next = &node;
85
86 assertOrPanic(node.next.next.next.val.x == 1);
87}
88
89test "struct byval assign" {
90 var foo1: StructFoo = undefined;
91 var foo2: StructFoo = undefined;
92
93 foo1.a = 1234;
94 foo2.a = 0;
95 assertOrPanic(foo2.a == 0);
96 foo2 = foo1;
97 assertOrPanic(foo2.a == 1234);
98}
99
100fn structInitializer() void {
101 const val = Val{ .x = 42 };
102 assertOrPanic(val.x == 42);
103}
104
105test "fn call of struct field" {
106 assertOrPanic(callStructField(Foo{ .ptr = aFunc }) == 13);
107}
108
109const Foo = struct {
110 ptr: fn () i32,
111};
112
113fn aFunc() i32 {
114 return 13;
115}
116
117fn callStructField(foo: Foo) i32 {
118 return foo.ptr();
119}
120
121test "store member function in variable" {
122 const instance = MemberFnTestFoo{ .x = 1234 };
123 const memberFn = MemberFnTestFoo.member;
124 const result = memberFn(instance);
125 assertOrPanic(result == 1234);
126}
127const MemberFnTestFoo = struct {
128 x: i32,
129 fn member(foo: MemberFnTestFoo) i32 {
130 return foo.x;
131 }
132};
133
134test "call member function directly" {
135 const instance = MemberFnTestFoo{ .x = 1234 };
136 const result = MemberFnTestFoo.member(instance);
137 assertOrPanic(result == 1234);
138}
139
140test "member functions" {
141 const r = MemberFnRand{ .seed = 1234 };
142 assertOrPanic(r.getSeed() == 1234);
143}
144const MemberFnRand = struct {
145 seed: u32,
146 pub fn getSeed(r: *const MemberFnRand) u32 {
147 return r.seed;
148 }
149};
150
151test "return struct byval from function" {
152 const bar = makeBar(1234, 5678);
153 assertOrPanic(bar.y == 5678);
154}
155const Bar = struct {
156 x: i32,
157 y: i32,
158};
159fn makeBar(x: i32, y: i32) Bar {
160 return Bar{
161 .x = x,
162 .y = y,
163 };
164}
165
166test "empty struct method call" {
167 const es = EmptyStruct{};
168 assertOrPanic(es.method() == 1234);
169}
170const EmptyStruct = struct {
171 fn method(es: *const EmptyStruct) i32 {
172 return 1234;
173 }
174};
175
176test "return empty struct from fn" {
177 _ = testReturnEmptyStructFromFn();
178}
179const EmptyStruct2 = struct {};
180fn testReturnEmptyStructFromFn() EmptyStruct2 {
181 return EmptyStruct2{};
182}
183
184test "pass slice of empty struct to fn" {
185 assertOrPanic(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
186}
187fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
188 return slice.len;
189}
190
191const APackedStruct = packed struct {
192 x: u8,
193 y: u8,
194};
195
196test "packed struct" {
197 var foo = APackedStruct{
198 .x = 1,
199 .y = 2,
200 };
201 foo.y += 1;
202 const four = foo.x + foo.y;
203 assertOrPanic(four == 4);
204}
205
206const BitField1 = packed struct {
207 a: u3,
208 b: u3,
209 c: u2,
210};
211
212const bit_field_1 = BitField1{
213 .a = 1,
214 .b = 2,
215 .c = 3,
216};
217
218test "bit field access" {
219 var data = bit_field_1;
220 assertOrPanic(getA(&data) == 1);
221 assertOrPanic(getB(&data) == 2);
222 assertOrPanic(getC(&data) == 3);
223 comptime assertOrPanic(@sizeOf(BitField1) == 1);
224
225 data.b += 1;
226 assertOrPanic(data.b == 3);
227
228 data.a += 1;
229 assertOrPanic(data.a == 2);
230 assertOrPanic(data.b == 3);
231}
232
233fn getA(data: *const BitField1) u3 {
234 return data.a;
235}
236
237fn getB(data: *const BitField1) u3 {
238 return data.b;
239}
240
241fn getC(data: *const BitField1) u2 {
242 return data.c;
243}
244
245const Foo24Bits = packed struct {
246 field: u24,
247};
248const Foo96Bits = packed struct {
249 a: u24,
250 b: u24,
251 c: u24,
252 d: u24,
253};
254
255test "packed struct 24bits" {
256 comptime {
257 assertOrPanic(@sizeOf(Foo24Bits) == 3);
258 assertOrPanic(@sizeOf(Foo96Bits) == 12);
259 }
260
261 var value = Foo96Bits{
262 .a = 0,
263 .b = 0,
264 .c = 0,
265 .d = 0,
266 };
267 value.a += 1;
268 assertOrPanic(value.a == 1);
269 assertOrPanic(value.b == 0);
270 assertOrPanic(value.c == 0);
271 assertOrPanic(value.d == 0);
272
273 value.b += 1;
274 assertOrPanic(value.a == 1);
275 assertOrPanic(value.b == 1);
276 assertOrPanic(value.c == 0);
277 assertOrPanic(value.d == 0);
278
279 value.c += 1;
280 assertOrPanic(value.a == 1);
281 assertOrPanic(value.b == 1);
282 assertOrPanic(value.c == 1);
283 assertOrPanic(value.d == 0);
284
285 value.d += 1;
286 assertOrPanic(value.a == 1);
287 assertOrPanic(value.b == 1);
288 assertOrPanic(value.c == 1);
289 assertOrPanic(value.d == 1);
290}
291
292const FooArray24Bits = packed struct {
293 a: u16,
294 b: [2]Foo24Bits,
295 c: u16,
296};
297
298test "packed array 24bits" {
299 comptime {
300 assertOrPanic(@sizeOf([9]Foo24Bits) == 9 * 3);
301 assertOrPanic(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
302 }
303
304 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
305 bytes[bytes.len - 1] = 0xaa;
306 const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
307 assertOrPanic(ptr.a == 0);
308 assertOrPanic(ptr.b[0].field == 0);
309 assertOrPanic(ptr.b[1].field == 0);
310 assertOrPanic(ptr.c == 0);
311
312 ptr.a = maxInt(u16);
313 assertOrPanic(ptr.a == maxInt(u16));
314 assertOrPanic(ptr.b[0].field == 0);
315 assertOrPanic(ptr.b[1].field == 0);
316 assertOrPanic(ptr.c == 0);
317
318 ptr.b[0].field = maxInt(u24);
319 assertOrPanic(ptr.a == maxInt(u16));
320 assertOrPanic(ptr.b[0].field == maxInt(u24));
321 assertOrPanic(ptr.b[1].field == 0);
322 assertOrPanic(ptr.c == 0);
323
324 ptr.b[1].field = maxInt(u24);
325 assertOrPanic(ptr.a == maxInt(u16));
326 assertOrPanic(ptr.b[0].field == maxInt(u24));
327 assertOrPanic(ptr.b[1].field == maxInt(u24));
328 assertOrPanic(ptr.c == 0);
329
330 ptr.c = maxInt(u16);
331 assertOrPanic(ptr.a == maxInt(u16));
332 assertOrPanic(ptr.b[0].field == maxInt(u24));
333 assertOrPanic(ptr.b[1].field == maxInt(u24));
334 assertOrPanic(ptr.c == maxInt(u16));
335
336 assertOrPanic(bytes[bytes.len - 1] == 0xaa);
337}
338
339const FooStructAligned = packed struct {
340 a: u8,
341 b: u8,
342};
343
344const FooArrayOfAligned = packed struct {
345 a: [2]FooStructAligned,
346};
347
348test "aligned array of packed struct" {
349 comptime {
350 assertOrPanic(@sizeOf(FooStructAligned) == 2);
351 assertOrPanic(@sizeOf(FooArrayOfAligned) == 2 * 2);
352 }
353
354 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
355 const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
356
357 assertOrPanic(ptr.a[0].a == 0xbb);
358 assertOrPanic(ptr.a[0].b == 0xbb);
359 assertOrPanic(ptr.a[1].a == 0xbb);
360 assertOrPanic(ptr.a[1].b == 0xbb);
361}
362
363test "runtime struct initialization of bitfield" {
364 const s1 = Nibbles{
365 .x = x1,
366 .y = x1,
367 };
368 const s2 = Nibbles{
369 .x = @intCast(u4, x2),
370 .y = @intCast(u4, x2),
371 };
372
373 assertOrPanic(s1.x == x1);
374 assertOrPanic(s1.y == x1);
375 assertOrPanic(s2.x == @intCast(u4, x2));
376 assertOrPanic(s2.y == @intCast(u4, x2));
377}
378
379var x1 = u4(1);
380var x2 = u8(2);
381
382const Nibbles = packed struct {
383 x: u4,
384 y: u4,
385};
386
387const Bitfields = packed struct {
388 f1: u16,
389 f2: u16,
390 f3: u8,
391 f4: u8,
392 f5: u4,
393 f6: u4,
394 f7: u8,
395};
396
397test "native bit field understands endianness" {
398 var all: u64 = 0x7765443322221111;
399 var bytes: [8]u8 = undefined;
400 @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
401 var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
402
403 assertOrPanic(bitfields.f1 == 0x1111);
404 assertOrPanic(bitfields.f2 == 0x2222);
405 assertOrPanic(bitfields.f3 == 0x33);
406 assertOrPanic(bitfields.f4 == 0x44);
407 assertOrPanic(bitfields.f5 == 0x5);
408 assertOrPanic(bitfields.f6 == 0x6);
409 assertOrPanic(bitfields.f7 == 0x77);
410}
411
412test "align 1 field before self referential align 8 field as slice return type" {
413 const result = alloc(Expr);
414 assertOrPanic(result.len == 0);
415}
416
417const Expr = union(enum) {
418 Literal: u8,
419 Question: *Expr,
420};
421
422fn alloc(comptime T: type) []T {
423 return []T{};
424}
425
426test "call method with mutable reference to struct with no fields" {
427 const S = struct {
428 fn doC(s: *const @This()) bool {
429 return true;
430 }
431 fn do(s: *@This()) bool {
432 return true;
433 }
434 };
435
436 var s = S{};
437 assertOrPanic(S.doC(&s));
438 assertOrPanic(s.doC());
439 assertOrPanic(S.do(&s));
440 assertOrPanic(s.do());
441}
442
443test "implicit cast packed struct field to const ptr" {
444 const LevelUpMove = packed struct {
445 move_id: u9,
446 level: u7,
447
448 fn toInt(value: u7) u7 {
449 return value;
450 }
451 };
452
453 var lup: LevelUpMove = undefined;
454 lup.level = 12;
455 const res = LevelUpMove.toInt(lup.level);
456 assertOrPanic(res == 12);
457}
458
459test "pointer to packed struct member in a stack variable" {
460 const S = packed struct {
461 a: u2,
462 b: u2,
463 };
464
465 var s = S{ .a = 2, .b = 0 };
466 var b_ptr = &s.b;
467 assertOrPanic(s.b == 0);
468 b_ptr.* = 2;
469 assertOrPanic(s.b == 2);
470}
test/stage1/behavior/struct_contains_null_ptr_itself.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?*NodeLineComment = null;
6 assertOrPanic(x == null);
7}
8
9pub const Node = struct {
10 id: Id,
11 comment: ?*NodeLineComment,
12
13 pub const Id = enum {
14 Root,
15 LineComment,
16 };
17};
18
19pub const NodeLineComment = struct {
20 base: Node,
21};
test/stage1/behavior/struct_contains_slice_of_itself.zig created+85
...@@ -0,0 +1,85 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const Node = struct {
4 payload: i32,
5 children: []Node,
6};
7
8const NodeAligned = struct {
9 payload: i32,
10 children: []align(@alignOf(NodeAligned)) NodeAligned,
11};
12
13test "struct contains slice of itself" {
14 var other_nodes = []Node{
15 Node{
16 .payload = 31,
17 .children = []Node{},
18 },
19 Node{
20 .payload = 32,
21 .children = []Node{},
22 },
23 };
24 var nodes = []Node{
25 Node{
26 .payload = 1,
27 .children = []Node{},
28 },
29 Node{
30 .payload = 2,
31 .children = []Node{},
32 },
33 Node{
34 .payload = 3,
35 .children = other_nodes[0..],
36 },
37 };
38 const root = Node{
39 .payload = 1234,
40 .children = nodes[0..],
41 };
42 assertOrPanic(root.payload == 1234);
43 assertOrPanic(root.children[0].payload == 1);
44 assertOrPanic(root.children[1].payload == 2);
45 assertOrPanic(root.children[2].payload == 3);
46 assertOrPanic(root.children[2].children[0].payload == 31);
47 assertOrPanic(root.children[2].children[1].payload == 32);
48}
49
50test "struct contains aligned slice of itself" {
51 var other_nodes = []NodeAligned{
52 NodeAligned{
53 .payload = 31,
54 .children = []NodeAligned{},
55 },
56 NodeAligned{
57 .payload = 32,
58 .children = []NodeAligned{},
59 },
60 };
61 var nodes = []NodeAligned{
62 NodeAligned{
63 .payload = 1,
64 .children = []NodeAligned{},
65 },
66 NodeAligned{
67 .payload = 2,
68 .children = []NodeAligned{},
69 },
70 NodeAligned{
71 .payload = 3,
72 .children = other_nodes[0..],
73 },
74 };
75 const root = NodeAligned{
76 .payload = 1234,
77 .children = nodes[0..],
78 };
79 assertOrPanic(root.payload == 1234);
80 assertOrPanic(root.children[0].payload == 1);
81 assertOrPanic(root.children[1].payload == 2);
82 assertOrPanic(root.children[2].payload == 3);
83 assertOrPanic(root.children[2].children[0].payload == 31);
84 assertOrPanic(root.children[2].children[1].payload == 32);
85}
test/stage1/behavior/switch.zig created+271
...@@ -0,0 +1,271 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "switch with numbers" {
4 testSwitchWithNumbers(13);
5}
6
7fn testSwitchWithNumbers(x: u32) void {
8 const result = switch (x) {
9 1, 2, 3, 4...8 => false,
10 13 => true,
11 else => false,
12 };
13 assertOrPanic(result);
14}
15
16test "switch with all ranges" {
17 assertOrPanic(testSwitchWithAllRanges(50, 3) == 1);
18 assertOrPanic(testSwitchWithAllRanges(101, 0) == 2);
19 assertOrPanic(testSwitchWithAllRanges(300, 5) == 3);
20 assertOrPanic(testSwitchWithAllRanges(301, 6) == 6);
21}
22
23fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
24 return switch (x) {
25 0...100 => 1,
26 101...200 => 2,
27 201...300 => 3,
28 else => y,
29 };
30}
31
32test "implicit comptime switch" {
33 const x = 3 + 4;
34 const result = switch (x) {
35 3 => 10,
36 4 => 11,
37 5, 6 => 12,
38 7, 8 => 13,
39 else => 14,
40 };
41
42 comptime {
43 assertOrPanic(result + 1 == 14);
44 }
45}
46
47test "switch on enum" {
48 const fruit = Fruit.Orange;
49 nonConstSwitchOnEnum(fruit);
50}
51const Fruit = enum {
52 Apple,
53 Orange,
54 Banana,
55};
56fn nonConstSwitchOnEnum(fruit: Fruit) void {
57 switch (fruit) {
58 Fruit.Apple => unreachable,
59 Fruit.Orange => {},
60 Fruit.Banana => unreachable,
61 }
62}
63
64test "switch statement" {
65 nonConstSwitch(SwitchStatmentFoo.C);
66}
67fn nonConstSwitch(foo: SwitchStatmentFoo) void {
68 const val = switch (foo) {
69 SwitchStatmentFoo.A => i32(1),
70 SwitchStatmentFoo.B => 2,
71 SwitchStatmentFoo.C => 3,
72 SwitchStatmentFoo.D => 4,
73 };
74 assertOrPanic(val == 3);
75}
76const SwitchStatmentFoo = enum {
77 A,
78 B,
79 C,
80 D,
81};
82
83test "switch prong with variable" {
84 switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
85 switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
86 switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
87}
88const SwitchProngWithVarEnum = union(enum) {
89 One: i32,
90 Two: f32,
91 Meh: void,
92};
93fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void {
94 switch (a) {
95 SwitchProngWithVarEnum.One => |x| {
96 assertOrPanic(x == 13);
97 },
98 SwitchProngWithVarEnum.Two => |x| {
99 assertOrPanic(x == 13.0);
100 },
101 SwitchProngWithVarEnum.Meh => |x| {
102 const v: void = x;
103 },
104 }
105}
106
107test "switch on enum using pointer capture" {
108 testSwitchEnumPtrCapture();
109 comptime testSwitchEnumPtrCapture();
110}
111
112fn testSwitchEnumPtrCapture() void {
113 var value = SwitchProngWithVarEnum{ .One = 1234 };
114 switch (value) {
115 SwitchProngWithVarEnum.One => |*x| x.* += 1,
116 else => unreachable,
117 }
118 switch (value) {
119 SwitchProngWithVarEnum.One => |x| assertOrPanic(x == 1235),
120 else => unreachable,
121 }
122}
123
124test "switch with multiple expressions" {
125 const x = switch (returnsFive()) {
126 1, 2, 3 => 1,
127 4, 5, 6 => 2,
128 else => i32(3),
129 };
130 assertOrPanic(x == 2);
131}
132fn returnsFive() i32 {
133 return 5;
134}
135
136const Number = union(enum) {
137 One: u64,
138 Two: u8,
139 Three: f32,
140};
141
142const number = Number{ .Three = 1.23 };
143
144fn returnsFalse() bool {
145 switch (number) {
146 Number.One => |x| return x > 1234,
147 Number.Two => |x| return x == 'a',
148 Number.Three => |x| return x > 12.34,
149 }
150}
151test "switch on const enum with var" {
152 assertOrPanic(!returnsFalse());
153}
154
155test "switch on type" {
156 assertOrPanic(trueIfBoolFalseOtherwise(bool));
157 assertOrPanic(!trueIfBoolFalseOtherwise(i32));
158}
159
160fn trueIfBoolFalseOtherwise(comptime T: type) bool {
161 return switch (T) {
162 bool => true,
163 else => false,
164 };
165}
166
167test "switch handles all cases of number" {
168 testSwitchHandleAllCases();
169 comptime testSwitchHandleAllCases();
170}
171
172fn testSwitchHandleAllCases() void {
173 assertOrPanic(testSwitchHandleAllCasesExhaustive(0) == 3);
174 assertOrPanic(testSwitchHandleAllCasesExhaustive(1) == 2);
175 assertOrPanic(testSwitchHandleAllCasesExhaustive(2) == 1);
176 assertOrPanic(testSwitchHandleAllCasesExhaustive(3) == 0);
177
178 assertOrPanic(testSwitchHandleAllCasesRange(100) == 0);
179 assertOrPanic(testSwitchHandleAllCasesRange(200) == 1);
180 assertOrPanic(testSwitchHandleAllCasesRange(201) == 2);
181 assertOrPanic(testSwitchHandleAllCasesRange(202) == 4);
182 assertOrPanic(testSwitchHandleAllCasesRange(230) == 3);
183}
184
185fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
186 return switch (x) {
187 0 => u2(3),
188 1 => 2,
189 2 => 1,
190 3 => 0,
191 };
192}
193
194fn testSwitchHandleAllCasesRange(x: u8) u8 {
195 return switch (x) {
196 0...100 => u8(0),
197 101...200 => 1,
198 201, 203 => 2,
199 202 => 4,
200 204...255 => 3,
201 };
202}
203
204test "switch all prongs unreachable" {
205 testAllProngsUnreachable();
206 comptime testAllProngsUnreachable();
207}
208
209fn testAllProngsUnreachable() void {
210 assertOrPanic(switchWithUnreachable(1) == 2);
211 assertOrPanic(switchWithUnreachable(2) == 10);
212}
213
214fn switchWithUnreachable(x: i32) i32 {
215 while (true) {
216 switch (x) {
217 1 => return 2,
218 2 => break,
219 else => continue,
220 }
221 }
222 return 10;
223}
224
225fn return_a_number() anyerror!i32 {
226 return 1;
227}
228
229test "capture value of switch with all unreachable prongs" {
230 const x = return_a_number() catch |err| switch (err) {
231 else => unreachable,
232 };
233 assertOrPanic(x == 1);
234}
235
236test "switching on booleans" {
237 testSwitchOnBools();
238 comptime testSwitchOnBools();
239}
240
241fn testSwitchOnBools() void {
242 assertOrPanic(testSwitchOnBoolsTrueAndFalse(true) == false);
243 assertOrPanic(testSwitchOnBoolsTrueAndFalse(false) == true);
244
245 assertOrPanic(testSwitchOnBoolsTrueWithElse(true) == false);
246 assertOrPanic(testSwitchOnBoolsTrueWithElse(false) == true);
247
248 assertOrPanic(testSwitchOnBoolsFalseWithElse(true) == false);
249 assertOrPanic(testSwitchOnBoolsFalseWithElse(false) == true);
250}
251
252fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
253 return switch (x) {
254 true => false,
255 false => true,
256 };
257}
258
259fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
260 return switch (x) {
261 true => false,
262 else => true,
263 };
264}
265
266fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
267 return switch (x) {
268 false => true,
269 else => false,
270 };
271}
test/stage1/behavior/switch_prong_err_enum.zig created+30
...@@ -0,0 +1,30 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3var read_count: u64 = 0;
4
5fn readOnce() anyerror!u64 {
6 read_count += 1;
7 return read_count;
8}
9
10const FormValue = union(enum) {
11 Address: u64,
12 Other: bool,
13};
14
15fn doThing(form_id: u64) anyerror!FormValue {
16 return switch (form_id) {
17 17 => FormValue{ .Address = try readOnce() },
18 else => error.InvalidDebugInfo,
19 };
20}
21
22test "switch prong returns error enum" {
23 switch (doThing(17) catch unreachable) {
24 FormValue.Address => |payload| {
25 assertOrPanic(payload == 1);
26 },
27 else => unreachable,
28 }
29 assertOrPanic(read_count == 1);
30}
test/stage1/behavior/switch_prong_implicit_cast.zig created+22
...@@ -0,0 +1,22 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const FormValue = union(enum) {
4 One: void,
5 Two: bool,
6};
7
8fn foo(id: u64) !FormValue {
9 return switch (id) {
10 2 => FormValue{ .Two = true },
11 1 => FormValue{ .One = {} },
12 else => return error.Whatever,
13 };
14}
15
16test "switch prong implicit cast" {
17 const result = switch (foo(2) catch unreachable) {
18 FormValue.One => false,
19 FormValue.Two => |x| x,
20 };
21 assertOrPanic(result);
22}
test/stage1/behavior/syntax.zig created+60
...@@ -0,0 +1,60 @@
1// Test trailing comma syntax
2// zig fmt: off
3
4const struct_trailing_comma = struct { x: i32, y: i32, };
5const struct_no_comma = struct { x: i32, y: i32 };
6const struct_fn_no_comma = struct { fn m() void {} y: i32 };
7
8const enum_no_comma = enum { A, B };
9
10fn container_init() void {
11 const S = struct { x: i32, y: i32 };
12 _ = S { .x = 1, .y = 2 };
13 _ = S { .x = 1, .y = 2, };
14}
15
16fn type_expr_return1() if (true) A {}
17fn type_expr_return2() for (true) |_| A {}
18fn type_expr_return3() while (true) A {}
19fn type_expr_return4() comptime A {}
20
21fn switch_cases(x: i32) void {
22 switch (x) {
23 1,2,3 => {},
24 4,5, => {},
25 6...8, => {},
26 else => {},
27 }
28}
29
30fn switch_prongs(x: i32) void {
31 switch (x) {
32 0 => {},
33 else => {},
34 }
35 switch (x) {
36 0 => {},
37 else => {}
38 }
39}
40
41const fn_no_comma = fn(i32, i32)void;
42const fn_trailing_comma = fn(i32, i32,)void;
43
44fn fn_calls() void {
45 fn add(x: i32, y: i32,) i32 { x + y };
46 _ = add(1, 2);
47 _ = add(1, 2,);
48}
49
50fn asm_lists() void {
51 if (false) { // Build AST but don't analyze
52 asm ("not real assembly"
53 :[a] "x" (x),);
54 asm ("not real assembly"
55 :[a] "x" (->i32),:[a] "x" (1),);
56 asm ("still not real assembly"
57 :::"a","b",);
58 }
59}
60
test/stage1/behavior/this.zig created+35
...@@ -0,0 +1,35 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const module = @This();
4
5fn Point(comptime T: type) type {
6 return struct {
7 const Self = @This();
8 x: T,
9 y: T,
10
11 fn addOne(self: *Self) void {
12 self.x += 1;
13 self.y += 1;
14 }
15 };
16}
17
18fn add(x: i32, y: i32) i32 {
19 return x + y;
20}
21
22test "this refer to module call private fn" {
23 assertOrPanic(module.add(1, 2) == 3);
24}
25
26test "this refer to container" {
27 var pt = Point(i32){
28 .x = 12,
29 .y = 34,
30 };
31 pt.addOne();
32 assertOrPanic(pt.x == 13);
33 assertOrPanic(pt.y == 35);
34}
35
test/stage1/behavior/truncate.zig created+8
...@@ -0,0 +1,8 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "truncate u0 to larger integer allowed and has comptime known result" {
5 var x: u0 = 0;
6 const y = @truncate(u8, x);
7 comptime assertOrPanic(y == 0);
8}
test/stage1/behavior/try.zig created+43
...@@ -0,0 +1,43 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "try on error union" {
4 tryOnErrorUnionImpl();
5 comptime tryOnErrorUnionImpl();
6}
7
8fn tryOnErrorUnionImpl() void {
9 const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
10 error.ItBroke, error.NoMem => 1,
11 error.CrappedOut => i32(2),
12 else => unreachable,
13 };
14 assertOrPanic(x == 11);
15}
16
17fn returnsTen() anyerror!i32 {
18 return 10;
19}
20
21test "try without vars" {
22 const result1 = if (failIfTrue(true)) 1 else |_| i32(2);
23 assertOrPanic(result1 == 2);
24
25 const result2 = if (failIfTrue(false)) 1 else |_| i32(2);
26 assertOrPanic(result2 == 1);
27}
28
29fn failIfTrue(ok: bool) anyerror!void {
30 if (ok) {
31 return error.ItBroke;
32 } else {
33 return;
34 }
35}
36
37test "try then not executed with assignment" {
38 if (failIfTrue(true)) {
39 unreachable;
40 } else |err| {
41 assertOrPanic(err == error.ItBroke);
42 }
43}
test/stage1/behavior/type_info.zig created+264
...@@ -0,0 +1,264 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3const TypeInfo = @import("builtin").TypeInfo;
4const TypeId = @import("builtin").TypeId;
5
6test "type info: tag type, void info" {
7 testBasic();
8 comptime testBasic();
9}
10
11fn testBasic() void {
12 assertOrPanic(@TagType(TypeInfo) == TypeId);
13 const void_info = @typeInfo(void);
14 assertOrPanic(TypeId(void_info) == TypeId.Void);
15 assertOrPanic(void_info.Void == {});
16}
17
18test "type info: integer, floating point type info" {
19 testIntFloat();
20 comptime testIntFloat();
21}
22
23fn testIntFloat() void {
24 const u8_info = @typeInfo(u8);
25 assertOrPanic(TypeId(u8_info) == TypeId.Int);
26 assertOrPanic(!u8_info.Int.is_signed);
27 assertOrPanic(u8_info.Int.bits == 8);
28
29 const f64_info = @typeInfo(f64);
30 assertOrPanic(TypeId(f64_info) == TypeId.Float);
31 assertOrPanic(f64_info.Float.bits == 64);
32}
33
34test "type info: pointer type info" {
35 testPointer();
36 comptime testPointer();
37}
38
39fn testPointer() void {
40 const u32_ptr_info = @typeInfo(*u32);
41 assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer);
42 assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
43 assertOrPanic(u32_ptr_info.Pointer.is_const == false);
44 assertOrPanic(u32_ptr_info.Pointer.is_volatile == false);
45 assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(u32));
46 assertOrPanic(u32_ptr_info.Pointer.child == u32);
47}
48
49test "type info: unknown length pointer type info" {
50 testUnknownLenPtr();
51 comptime testUnknownLenPtr();
52}
53
54fn testUnknownLenPtr() void {
55 const u32_ptr_info = @typeInfo([*]const volatile f64);
56 assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer);
57 assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
58 assertOrPanic(u32_ptr_info.Pointer.is_const == true);
59 assertOrPanic(u32_ptr_info.Pointer.is_volatile == true);
60 assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(f64));
61 assertOrPanic(u32_ptr_info.Pointer.child == f64);
62}
63
64test "type info: slice type info" {
65 testSlice();
66 comptime testSlice();
67}
68
69fn testSlice() void {
70 const u32_slice_info = @typeInfo([]u32);
71 assertOrPanic(TypeId(u32_slice_info) == TypeId.Pointer);
72 assertOrPanic(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
73 assertOrPanic(u32_slice_info.Pointer.is_const == false);
74 assertOrPanic(u32_slice_info.Pointer.is_volatile == false);
75 assertOrPanic(u32_slice_info.Pointer.alignment == 4);
76 assertOrPanic(u32_slice_info.Pointer.child == u32);
77}
78
79test "type info: array type info" {
80 testArray();
81 comptime testArray();
82}
83
84fn testArray() void {
85 const arr_info = @typeInfo([42]bool);
86 assertOrPanic(TypeId(arr_info) == TypeId.Array);
87 assertOrPanic(arr_info.Array.len == 42);
88 assertOrPanic(arr_info.Array.child == bool);
89}
90
91test "type info: optional type info" {
92 testOptional();
93 comptime testOptional();
94}
95
96fn testOptional() void {
97 const null_info = @typeInfo(?void);
98 assertOrPanic(TypeId(null_info) == TypeId.Optional);
99 assertOrPanic(null_info.Optional.child == void);
100}
101
102test "type info: promise info" {
103 testPromise();
104 comptime testPromise();
105}
106
107fn testPromise() void {
108 const null_promise_info = @typeInfo(promise);
109 assertOrPanic(TypeId(null_promise_info) == TypeId.Promise);
110 assertOrPanic(null_promise_info.Promise.child == null);
111
112 const promise_info = @typeInfo(promise->usize);
113 assertOrPanic(TypeId(promise_info) == TypeId.Promise);
114 assertOrPanic(promise_info.Promise.child.? == usize);
115}
116
117test "type info: error set, error union info" {
118 testErrorSet();
119 comptime testErrorSet();
120}
121
122fn testErrorSet() void {
123 const TestErrorSet = error{
124 First,
125 Second,
126 Third,
127 };
128
129 const error_set_info = @typeInfo(TestErrorSet);
130 assertOrPanic(TypeId(error_set_info) == TypeId.ErrorSet);
131 assertOrPanic(error_set_info.ErrorSet.errors.len == 3);
132 assertOrPanic(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
133 assertOrPanic(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
134
135 const error_union_info = @typeInfo(TestErrorSet!usize);
136 assertOrPanic(TypeId(error_union_info) == TypeId.ErrorUnion);
137 assertOrPanic(error_union_info.ErrorUnion.error_set == TestErrorSet);
138 assertOrPanic(error_union_info.ErrorUnion.payload == usize);
139}
140
141test "type info: enum info" {
142 testEnum();
143 comptime testEnum();
144}
145
146fn testEnum() void {
147 const Os = enum {
148 Windows,
149 Macos,
150 Linux,
151 FreeBSD,
152 };
153
154 const os_info = @typeInfo(Os);
155 assertOrPanic(TypeId(os_info) == TypeId.Enum);
156 assertOrPanic(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
157 assertOrPanic(os_info.Enum.fields.len == 4);
158 assertOrPanic(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
159 assertOrPanic(os_info.Enum.fields[3].value == 3);
160 assertOrPanic(os_info.Enum.tag_type == u2);
161 assertOrPanic(os_info.Enum.defs.len == 0);
162}
163
164test "type info: union info" {
165 testUnion();
166 comptime testUnion();
167}
168
169fn testUnion() void {
170 const typeinfo_info = @typeInfo(TypeInfo);
171 assertOrPanic(TypeId(typeinfo_info) == TypeId.Union);
172 assertOrPanic(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
173 assertOrPanic(typeinfo_info.Union.tag_type.? == TypeId);
174 assertOrPanic(typeinfo_info.Union.fields.len == 24);
175 assertOrPanic(typeinfo_info.Union.fields[4].enum_field != null);
176 assertOrPanic(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
177 assertOrPanic(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
178 assertOrPanic(typeinfo_info.Union.defs.len == 20);
179
180 const TestNoTagUnion = union {
181 Foo: void,
182 Bar: u32,
183 };
184
185 const notag_union_info = @typeInfo(TestNoTagUnion);
186 assertOrPanic(TypeId(notag_union_info) == TypeId.Union);
187 assertOrPanic(notag_union_info.Union.tag_type == null);
188 assertOrPanic(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
189 assertOrPanic(notag_union_info.Union.fields.len == 2);
190 assertOrPanic(notag_union_info.Union.fields[0].enum_field == null);
191 assertOrPanic(notag_union_info.Union.fields[1].field_type == u32);
192
193 const TestExternUnion = extern union {
194 foo: *c_void,
195 };
196
197 const extern_union_info = @typeInfo(TestExternUnion);
198 assertOrPanic(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
199 assertOrPanic(extern_union_info.Union.tag_type == null);
200 assertOrPanic(extern_union_info.Union.fields[0].enum_field == null);
201 assertOrPanic(extern_union_info.Union.fields[0].field_type == *c_void);
202}
203
204test "type info: struct info" {
205 testStruct();
206 comptime testStruct();
207}
208
209fn testStruct() void {
210 const struct_info = @typeInfo(TestStruct);
211 assertOrPanic(TypeId(struct_info) == TypeId.Struct);
212 assertOrPanic(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
213 assertOrPanic(struct_info.Struct.fields.len == 3);
214 assertOrPanic(struct_info.Struct.fields[1].offset == null);
215 assertOrPanic(struct_info.Struct.fields[2].field_type == *TestStruct);
216 assertOrPanic(struct_info.Struct.defs.len == 2);
217 assertOrPanic(struct_info.Struct.defs[0].is_pub);
218 assertOrPanic(!struct_info.Struct.defs[0].data.Fn.is_extern);
219 assertOrPanic(struct_info.Struct.defs[0].data.Fn.lib_name == null);
220 assertOrPanic(struct_info.Struct.defs[0].data.Fn.return_type == void);
221 assertOrPanic(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
222}
223
224const TestStruct = packed struct {
225 const Self = @This();
226
227 fieldA: usize,
228 fieldB: void,
229 fieldC: *Self,
230
231 pub fn foo(self: *const Self) void {}
232};
233
234test "type info: function type info" {
235 testFunction();
236 comptime testFunction();
237}
238
239fn testFunction() void {
240 const fn_info = @typeInfo(@typeOf(foo));
241 assertOrPanic(TypeId(fn_info) == TypeId.Fn);
242 assertOrPanic(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
243 assertOrPanic(fn_info.Fn.is_generic);
244 assertOrPanic(fn_info.Fn.args.len == 2);
245 assertOrPanic(fn_info.Fn.is_var_args);
246 assertOrPanic(fn_info.Fn.return_type == null);
247 assertOrPanic(fn_info.Fn.async_allocator_type == null);
248
249 const test_instance: TestStruct = undefined;
250 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
251 assertOrPanic(TypeId(bound_fn_info) == TypeId.BoundFn);
252 assertOrPanic(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
253}
254
255fn foo(comptime a: usize, b: bool, args: ...) usize {
256 return 0;
257}
258
259test "typeInfo with comptime parameter in struct fn def" {
260 const S = struct {
261 pub fn func(comptime x: f32) void {}
262 };
263 comptime var info = @typeInfo(S);
264}
test/stage1/behavior/undefined.zig created+69
...@@ -0,0 +1,69 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3
4fn initStaticArray() [10]i32 {
5 var array: [10]i32 = undefined;
6 array[0] = 1;
7 array[4] = 2;
8 array[7] = 3;
9 array[9] = 4;
10 return array;
11}
12const static_array = initStaticArray();
13test "init static array to undefined" {
14 assertOrPanic(static_array[0] == 1);
15 assertOrPanic(static_array[4] == 2);
16 assertOrPanic(static_array[7] == 3);
17 assertOrPanic(static_array[9] == 4);
18
19 comptime {
20 assertOrPanic(static_array[0] == 1);
21 assertOrPanic(static_array[4] == 2);
22 assertOrPanic(static_array[7] == 3);
23 assertOrPanic(static_array[9] == 4);
24 }
25}
26
27const Foo = struct {
28 x: i32,
29
30 fn setFooXMethod(foo: *Foo) void {
31 foo.x = 3;
32 }
33};
34
35fn setFooX(foo: *Foo) void {
36 foo.x = 2;
37}
38
39test "assign undefined to struct" {
40 comptime {
41 var foo: Foo = undefined;
42 setFooX(&foo);
43 assertOrPanic(foo.x == 2);
44 }
45 {
46 var foo: Foo = undefined;
47 setFooX(&foo);
48 assertOrPanic(foo.x == 2);
49 }
50}
51
52test "assign undefined to struct with method" {
53 comptime {
54 var foo: Foo = undefined;
55 foo.setFooXMethod();
56 assertOrPanic(foo.x == 3);
57 }
58 {
59 var foo: Foo = undefined;
60 foo.setFooXMethod();
61 assertOrPanic(foo.x == 3);
62 }
63}
64
65test "type name of undefined" {
66 const x = undefined;
67 assertOrPanic(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
68}
69
test/stage1/behavior/underscore.zig created+28
...@@ -0,0 +1,28 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "ignore lval with underscore" {
5 _ = false;
6}
7
8test "ignore lval with underscore (for loop)" {
9 for ([]void{}) |_, i| {
10 for ([]void{}) |_, j| {
11 break;
12 }
13 break;
14 }
15}
16
17test "ignore lval with underscore (while loop)" {
18 while (optionalReturnError()) |_| {
19 while (optionalReturnError()) |_| {
20 break;
21 } else |_| {}
22 break;
23 } else |_| {}
24}
25
26fn optionalReturnError() !?u32 {
27 return error.optionalReturnError;
28}
test/stage1/behavior/union.zig created+352
...@@ -0,0 +1,352 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const Value = union(enum) {
4 Int: u64,
5 Array: [9]u8,
6};
7
8const Agg = struct {
9 val1: Value,
10 val2: Value,
11};
12
13const v1 = Value{ .Int = 1234 };
14const v2 = Value{ .Array = []u8{3} ** 9 };
15
16const err = (anyerror!Agg)(Agg{
17 .val1 = v1,
18 .val2 = v2,
19});
20
21const array = []Value{
22 v1,
23 v2,
24 v1,
25 v2,
26};
27
28test "unions embedded in aggregate types" {
29 switch (array[1]) {
30 Value.Array => |arr| assertOrPanic(arr[4] == 3),
31 else => unreachable,
32 }
33 switch ((err catch unreachable).val1) {
34 Value.Int => |x| assertOrPanic(x == 1234),
35 else => unreachable,
36 }
37}
38
39const Foo = union {
40 float: f64,
41 int: i32,
42};
43
44test "basic unions" {
45 var foo = Foo{ .int = 1 };
46 assertOrPanic(foo.int == 1);
47 foo = Foo{ .float = 12.34 };
48 assertOrPanic(foo.float == 12.34);
49}
50
51test "comptime union field access" {
52 comptime {
53 var foo = Foo{ .int = 0 };
54 assertOrPanic(foo.int == 0);
55
56 foo = Foo{ .float = 42.42 };
57 assertOrPanic(foo.float == 42.42);
58 }
59}
60
61test "init union with runtime value" {
62 var foo: Foo = undefined;
63
64 setFloat(&foo, 12.34);
65 assertOrPanic(foo.float == 12.34);
66
67 setInt(&foo, 42);
68 assertOrPanic(foo.int == 42);
69}
70
71fn setFloat(foo: *Foo, x: f64) void {
72 foo.* = Foo{ .float = x };
73}
74
75fn setInt(foo: *Foo, x: i32) void {
76 foo.* = Foo{ .int = x };
77}
78
79const FooExtern = extern union {
80 float: f64,
81 int: i32,
82};
83
84test "basic extern unions" {
85 var foo = FooExtern{ .int = 1 };
86 assertOrPanic(foo.int == 1);
87 foo.float = 12.34;
88 assertOrPanic(foo.float == 12.34);
89}
90
91const Letter = enum {
92 A,
93 B,
94 C,
95};
96const Payload = union(Letter) {
97 A: i32,
98 B: f64,
99 C: bool,
100};
101
102test "union with specified enum tag" {
103 doTest();
104 comptime doTest();
105}
106
107fn doTest() void {
108 assertOrPanic(bar(Payload{ .A = 1234 }) == -10);
109}
110
111fn bar(value: Payload) i32 {
112 assertOrPanic(Letter(value) == Letter.A);
113 return switch (value) {
114 Payload.A => |x| return x - 1244,
115 Payload.B => |x| if (x == 12.34) i32(20) else 21,
116 Payload.C => |x| if (x) i32(30) else 31,
117 };
118}
119
120const MultipleChoice = union(enum(u32)) {
121 A = 20,
122 B = 40,
123 C = 60,
124 D = 1000,
125};
126test "simple union(enum(u32))" {
127 var x = MultipleChoice.C;
128 assertOrPanic(x == MultipleChoice.C);
129 assertOrPanic(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
130}
131
132const MultipleChoice2 = union(enum(u32)) {
133 Unspecified1: i32,
134 A: f32 = 20,
135 Unspecified2: void,
136 B: bool = 40,
137 Unspecified3: i32,
138 C: i8 = 60,
139 Unspecified4: void,
140 D: void = 1000,
141 Unspecified5: i32,
142};
143
144test "union(enum(u32)) with specified and unspecified tag values" {
145 comptime assertOrPanic(@TagType(@TagType(MultipleChoice2)) == u32);
146 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
147 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
148}
149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
151 assertOrPanic(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);
152 assertOrPanic(1123 == switch (x) {
153 MultipleChoice2.A => 1,
154 MultipleChoice2.B => 2,
155 MultipleChoice2.C => |v| i32(1000) + v,
156 MultipleChoice2.D => 4,
157 MultipleChoice2.Unspecified1 => 5,
158 MultipleChoice2.Unspecified2 => 6,
159 MultipleChoice2.Unspecified3 => 7,
160 MultipleChoice2.Unspecified4 => 8,
161 MultipleChoice2.Unspecified5 => 9,
162 });
163}
164
165const ExternPtrOrInt = extern union {
166 ptr: *u8,
167 int: u64,
168};
169test "extern union size" {
170 comptime assertOrPanic(@sizeOf(ExternPtrOrInt) == 8);
171}
172
173const PackedPtrOrInt = packed union {
174 ptr: *u8,
175 int: u64,
176};
177test "extern union size" {
178 comptime assertOrPanic(@sizeOf(PackedPtrOrInt) == 8);
179}
180
181const ZeroBits = union {
182 OnlyField: void,
183};
184test "union with only 1 field which is void should be zero bits" {
185 comptime assertOrPanic(@sizeOf(ZeroBits) == 0);
186}
187
188const TheTag = enum {
189 A,
190 B,
191 C,
192};
193const TheUnion = union(TheTag) {
194 A: i32,
195 B: i32,
196 C: i32,
197};
198test "union field access gives the enum values" {
199 assertOrPanic(TheUnion.A == TheTag.A);
200 assertOrPanic(TheUnion.B == TheTag.B);
201 assertOrPanic(TheUnion.C == TheTag.C);
202}
203
204test "cast union to tag type of union" {
205 testCastUnionToTagType(TheUnion{ .B = 1234 });
206 comptime testCastUnionToTagType(TheUnion{ .B = 1234 });
207}
208
209fn testCastUnionToTagType(x: TheUnion) void {
210 assertOrPanic(TheTag(x) == TheTag.B);
211}
212
213test "cast tag type of union to union" {
214 var x: Value2 = Letter2.B;
215 assertOrPanic(Letter2(x) == Letter2.B);
216}
217const Letter2 = enum {
218 A,
219 B,
220 C,
221};
222const Value2 = union(Letter2) {
223 A: i32,
224 B,
225 C,
226};
227
228test "implicit cast union to its tag type" {
229 var x: Value2 = Letter2.B;
230 assertOrPanic(x == Letter2.B);
231 giveMeLetterB(x);
232}
233fn giveMeLetterB(x: Letter2) void {
234 assertOrPanic(x == Value2.B);
235}
236
237pub const PackThis = union(enum) {
238 Invalid: bool,
239 StringLiteral: u2,
240};
241
242test "constant packed union" {
243 testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }});
244}
245
246fn testConstPackedUnion(expected_tokens: []const PackThis) void {
247 assertOrPanic(expected_tokens[0].StringLiteral == 1);
248}
249
250test "switch on union with only 1 field" {
251 var r: PartialInst = undefined;
252 r = PartialInst.Compiled;
253 switch (r) {
254 PartialInst.Compiled => {
255 var z: PartialInstWithPayload = undefined;
256 z = PartialInstWithPayload{ .Compiled = 1234 };
257 switch (z) {
258 PartialInstWithPayload.Compiled => |x| {
259 assertOrPanic(x == 1234);
260 return;
261 },
262 }
263 },
264 }
265 unreachable;
266}
267
268const PartialInst = union(enum) {
269 Compiled,
270};
271
272const PartialInstWithPayload = union(enum) {
273 Compiled: i32,
274};
275
276test "access a member of tagged union with conflicting enum tag name" {
277 const Bar = union(enum) {
278 A: A,
279 B: B,
280
281 const A = u8;
282 const B = void;
283 };
284
285 comptime assertOrPanic(Bar.A == u8);
286}
287
288test "tagged union initialization with runtime void" {
289 assertOrPanic(testTaggedUnionInit({}));
290}
291
292const TaggedUnionWithAVoid = union(enum) {
293 A,
294 B: i32,
295};
296
297fn testTaggedUnionInit(x: var) bool {
298 const y = TaggedUnionWithAVoid{ .A = x };
299 return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A;
300}
301
302pub const UnionEnumNoPayloads = union(enum) {
303 A,
304 B,
305};
306
307test "tagged union with no payloads" {
308 const a = UnionEnumNoPayloads{ .B = {} };
309 switch (a) {
310 @TagType(UnionEnumNoPayloads).A => @panic("wrong"),
311 @TagType(UnionEnumNoPayloads).B => {},
312 }
313}
314
315test "union with only 1 field casted to its enum type" {
316 const Literal = union(enum) {
317 Number: f64,
318 Bool: bool,
319 };
320
321 const Expr = union(enum) {
322 Literal: Literal,
323 };
324
325 var e = Expr{ .Literal = Literal{ .Bool = true } };
326 const Tag = @TagType(Expr);
327 comptime assertOrPanic(@TagType(Tag) == comptime_int);
328 var t = Tag(e);
329 assertOrPanic(t == Expr.Literal);
330}
331
332test "union with only 1 field casted to its enum type which has enum value specified" {
333 const Literal = union(enum) {
334 Number: f64,
335 Bool: bool,
336 };
337
338 const Tag = enum {
339 Literal = 33,
340 };
341
342 const Expr = union(Tag) {
343 Literal: Literal,
344 };
345
346 var e = Expr{ .Literal = Literal{ .Bool = true } };
347 comptime assertOrPanic(@TagType(Tag) == comptime_int);
348 var t = Tag(e);
349 assertOrPanic(t == Expr.Literal);
350 assertOrPanic(@enumToInt(t) == 33);
351 comptime assertOrPanic(@enumToInt(t) == 33);
352}
test/stage1/behavior/var_args.zig created+84
...@@ -0,0 +1,84 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3fn add(args: ...) i32 {
4 var sum = i32(0);
5 {
6 comptime var i: usize = 0;
7 inline while (i < args.len) : (i += 1) {
8 sum += args[i];
9 }
10 }
11 return sum;
12}
13
14test "add arbitrary args" {
15 assertOrPanic(add(i32(1), i32(2), i32(3), i32(4)) == 10);
16 assertOrPanic(add(i32(1234)) == 1234);
17 assertOrPanic(add() == 0);
18}
19
20fn readFirstVarArg(args: ...) void {
21 const value = args[0];
22}
23
24test "send void arg to var args" {
25 readFirstVarArg({});
26}
27
28test "pass args directly" {
29 assertOrPanic(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
30 assertOrPanic(addSomeStuff(i32(1234)) == 1234);
31 assertOrPanic(addSomeStuff() == 0);
32}
33
34fn addSomeStuff(args: ...) i32 {
35 return add(args);
36}
37
38test "runtime parameter before var args" {
39 assertOrPanic(extraFn(10) == 0);
40 assertOrPanic(extraFn(10, false) == 1);
41 assertOrPanic(extraFn(10, false, true) == 2);
42
43 // TODO issue #313
44 //comptime {
45 // assertOrPanic(extraFn(10) == 0);
46 // assertOrPanic(extraFn(10, false) == 1);
47 // assertOrPanic(extraFn(10, false, true) == 2);
48 //}
49}
50
51fn extraFn(extra: u32, args: ...) usize {
52 if (args.len >= 1) {
53 assertOrPanic(args[0] == false);
54 }
55 if (args.len >= 2) {
56 assertOrPanic(args[1] == true);
57 }
58 return args.len;
59}
60
61const foos = []fn (...) bool{
62 foo1,
63 foo2,
64};
65
66fn foo1(args: ...) bool {
67 return true;
68}
69fn foo2(args: ...) bool {
70 return false;
71}
72
73test "array of var args functions" {
74 assertOrPanic(foos[0]());
75 assertOrPanic(!foos[1]());
76}
77
78test "pass zero length array to var args param" {
79 doNothingWithFirstArg("");
80}
81
82fn doNothingWithFirstArg(args: ...) void {
83 const a = args[0];
84}
test/stage1/behavior/void.zig created+35
...@@ -0,0 +1,35 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const Foo = struct {
4 a: void,
5 b: i32,
6 c: void,
7};
8
9test "compare void with void compile time known" {
10 comptime {
11 const foo = Foo{
12 .a = {},
13 .b = 1,
14 .c = {},
15 };
16 assertOrPanic(foo.a == {});
17 }
18}
19
20test "iterate over a void slice" {
21 var j: usize = 0;
22 for (times(10)) |_, i| {
23 assertOrPanic(i == j);
24 j += 1;
25 }
26}
27
28fn times(n: usize) []const void {
29 return ([*]void)(undefined)[0..n];
30}
31
32test "void optional" {
33 var x: ?void = {};
34 assertOrPanic(x != null);
35}
test/stage1/behavior/while.zig created+228
...@@ -0,0 +1,228 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "while loop" {
4 var i: i32 = 0;
5 while (i < 4) {
6 i += 1;
7 }
8 assertOrPanic(i == 4);
9 assertOrPanic(whileLoop1() == 1);
10}
11fn whileLoop1() i32 {
12 return whileLoop2();
13}
14fn whileLoop2() i32 {
15 while (true) {
16 return 1;
17 }
18}
19
20test "static eval while" {
21 assertOrPanic(static_eval_while_number == 1);
22}
23const static_eval_while_number = staticWhileLoop1();
24fn staticWhileLoop1() i32 {
25 return whileLoop2();
26}
27fn staticWhileLoop2() i32 {
28 while (true) {
29 return 1;
30 }
31}
32
33test "continue and break" {
34 runContinueAndBreakTest();
35 assertOrPanic(continue_and_break_counter == 8);
36}
37var continue_and_break_counter: i32 = 0;
38fn runContinueAndBreakTest() void {
39 var i: i32 = 0;
40 while (true) {
41 continue_and_break_counter += 2;
42 i += 1;
43 if (i < 4) {
44 continue;
45 }
46 break;
47 }
48 assertOrPanic(i == 4);
49}
50
51test "return with implicit cast from while loop" {
52 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
53}
54fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
55 while (true) {
56 return;
57 }
58}
59
60test "while with continue expression" {
61 var sum: i32 = 0;
62 {
63 var i: i32 = 0;
64 while (i < 10) : (i += 1) {
65 if (i == 5) continue;
66 sum += i;
67 }
68 }
69 assertOrPanic(sum == 40);
70}
71
72test "while with else" {
73 var sum: i32 = 0;
74 var i: i32 = 0;
75 var got_else: i32 = 0;
76 while (i < 10) : (i += 1) {
77 sum += 1;
78 } else {
79 got_else += 1;
80 }
81 assertOrPanic(sum == 10);
82 assertOrPanic(got_else == 1);
83}
84
85test "while with optional as condition" {
86 numbers_left = 10;
87 var sum: i32 = 0;
88 while (getNumberOrNull()) |value| {
89 sum += value;
90 }
91 assertOrPanic(sum == 45);
92}
93
94test "while with optional as condition with else" {
95 numbers_left = 10;
96 var sum: i32 = 0;
97 var got_else: i32 = 0;
98 while (getNumberOrNull()) |value| {
99 sum += value;
100 assertOrPanic(got_else == 0);
101 } else {
102 got_else += 1;
103 }
104 assertOrPanic(sum == 45);
105 assertOrPanic(got_else == 1);
106}
107
108test "while with error union condition" {
109 numbers_left = 10;
110 var sum: i32 = 0;
111 var got_else: i32 = 0;
112 while (getNumberOrErr()) |value| {
113 sum += value;
114 } else |err| {
115 assertOrPanic(err == error.OutOfNumbers);
116 got_else += 1;
117 }
118 assertOrPanic(sum == 45);
119 assertOrPanic(got_else == 1);
120}
121
122var numbers_left: i32 = undefined;
123fn getNumberOrErr() anyerror!i32 {
124 return if (numbers_left == 0) error.OutOfNumbers else x: {
125 numbers_left -= 1;
126 break :x numbers_left;
127 };
128}
129fn getNumberOrNull() ?i32 {
130 return if (numbers_left == 0) null else x: {
131 numbers_left -= 1;
132 break :x numbers_left;
133 };
134}
135
136test "while on optional with else result follow else prong" {
137 const result = while (returnNull()) |value| {
138 break value;
139 } else
140 i32(2);
141 assertOrPanic(result == 2);
142}
143
144test "while on optional with else result follow break prong" {
145 const result = while (returnOptional(10)) |value| {
146 break value;
147 } else
148 i32(2);
149 assertOrPanic(result == 10);
150}
151
152test "while on error union with else result follow else prong" {
153 const result = while (returnError()) |value| {
154 break value;
155 } else |err|
156 i32(2);
157 assertOrPanic(result == 2);
158}
159
160test "while on error union with else result follow break prong" {
161 const result = while (returnSuccess(10)) |value| {
162 break value;
163 } else |err|
164 i32(2);
165 assertOrPanic(result == 10);
166}
167
168test "while on bool with else result follow else prong" {
169 const result = while (returnFalse()) {
170 break i32(10);
171 } else
172 i32(2);
173 assertOrPanic(result == 2);
174}
175
176test "while on bool with else result follow break prong" {
177 const result = while (returnTrue()) {
178 break i32(10);
179 } else
180 i32(2);
181 assertOrPanic(result == 10);
182}
183
184test "break from outer while loop" {
185 testBreakOuter();
186 comptime testBreakOuter();
187}
188
189fn testBreakOuter() void {
190 outer: while (true) {
191 while (true) {
192 break :outer;
193 }
194 }
195}
196
197test "continue outer while loop" {
198 testContinueOuter();
199 comptime testContinueOuter();
200}
201
202fn testContinueOuter() void {
203 var i: usize = 0;
204 outer: while (i < 10) : (i += 1) {
205 while (true) {
206 continue :outer;
207 }
208 }
209}
210
211fn returnNull() ?i32 {
212 return null;
213}
214fn returnOptional(x: i32) ?i32 {
215 return x;
216}
217fn returnError() anyerror!i32 {
218 return error.YouWantedAnError;
219}
220fn returnSuccess(x: i32) anyerror!i32 {
221 return x;
222}
223fn returnFalse() bool {
224 return false;
225}
226fn returnTrue() bool {
227 return true;
228}
test/stage1/behavior/widening.zig created+28
...@@ -0,0 +1,28 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const mem = std.mem;
4
5test "integer widening" {
6 var a: u8 = 250;
7 var b: u16 = a;
8 var c: u32 = b;
9 var d: u64 = c;
10 var e: u64 = d;
11 var f: u128 = e;
12 assertOrPanic(f == a);
13}
14
15test "implicit unsigned integer to signed integer" {
16 var a: u8 = 250;
17 var b: i16 = a;
18 assertOrPanic(b == 250);
19}
20
21test "float widening" {
22 var a: f16 = 12.34;
23 var b: f32 = a;
24 var c: f64 = b;
25 var d: f128 = c;
26 assertOrPanic(d == a);
27}
28