authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-28 16:59:35-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-28 16:59:35-04:00
log928ce5e326ccd1b7456002c28f34975b5bc4b13f
tree5706376fe74103223511f5a4954ce2dff0b08d0e
parent2f3ad48c9b35ccac377e710a4eee6b35f60b119f
parente8a9caa3dd0aef7b745b8197afecec90598b2cdd
signaturelock-open Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into llvm9


47 files changed, 3555 insertions(+), 1739 deletions(-)

src/all_types.hpp+118-31
...@@ -47,6 +47,19 @@ struct ResultLocPeer;...@@ -47,6 +47,19 @@ struct ResultLocPeer;
47struct ResultLocPeerParent;47struct ResultLocPeerParent;
48struct ResultLocBitCast;48struct ResultLocBitCast;
4949
50enum PtrLen {
51 PtrLenUnknown,
52 PtrLenSingle,
53 PtrLenC,
54};
55
56enum UndefAllowed {
57 UndefOk,
58 UndefBad,
59 LazyOkNoUndef,
60 LazyOk,
61};
62
50enum X64CABIClass {63enum X64CABIClass {
51 X64CABIClass_Unknown,64 X64CABIClass_Unknown,
52 X64CABIClass_MEMORY,65 X64CABIClass_MEMORY,
...@@ -69,9 +82,9 @@ struct IrExecutable {...@@ -69,9 +82,9 @@ struct IrExecutable {
69 IrExecutable *source_exec;82 IrExecutable *source_exec;
70 IrAnalyze *analysis;83 IrAnalyze *analysis;
71 Scope *begin_scope;84 Scope *begin_scope;
85 ErrorMsg *first_err_trace_msg;
72 ZigList<Tld *> tld_list;86 ZigList<Tld *> tld_list;
7387
74 bool invalid;
75 bool is_inline;88 bool is_inline;
76 bool is_generic_instantiation;89 bool is_generic_instantiation;
77 bool need_err_code_spill;90 bool need_err_code_spill;
...@@ -255,6 +268,7 @@ enum ConstValSpecial {...@@ -255,6 +268,7 @@ enum ConstValSpecial {
255 ConstValSpecialRuntime,268 ConstValSpecialRuntime,
256 ConstValSpecialStatic,269 ConstValSpecialStatic,
257 ConstValSpecialUndef,270 ConstValSpecialUndef,
271 ConstValSpecialLazy,
258};272};
259273
260enum RuntimeHintErrorUnion {274enum RuntimeHintErrorUnion {
...@@ -291,6 +305,82 @@ struct ConstGlobalRefs {...@@ -291,6 +305,82 @@ struct ConstGlobalRefs {
291 uint32_t align;305 uint32_t align;
292};306};
293307
308enum LazyValueId {
309 LazyValueIdInvalid,
310 LazyValueIdAlignOf,
311 LazyValueIdPtrType,
312 LazyValueIdOptType,
313 LazyValueIdSliceType,
314 LazyValueIdFnType,
315 LazyValueIdErrUnionType,
316};
317
318struct LazyValue {
319 LazyValueId id;
320};
321
322struct LazyValueAlignOf {
323 LazyValue base;
324
325 IrAnalyze *ira;
326 IrInstruction *target_type;
327};
328
329struct LazyValueSliceType {
330 LazyValue base;
331
332 IrAnalyze *ira;
333 IrInstruction *elem_type;
334 IrInstruction *align_inst; // can be null
335
336 bool is_const;
337 bool is_volatile;
338 bool is_allowzero;
339};
340
341struct LazyValuePtrType {
342 LazyValue base;
343
344 IrAnalyze *ira;
345 IrInstruction *elem_type;
346 IrInstruction *align_inst; // can be null
347
348 PtrLen ptr_len;
349 uint32_t bit_offset_in_host;
350
351 uint32_t host_int_bytes;
352 bool is_const;
353 bool is_volatile;
354 bool is_allowzero;
355};
356
357struct LazyValueOptType {
358 LazyValue base;
359
360 IrAnalyze *ira;
361 IrInstruction *payload_type;
362};
363
364struct LazyValueFnType {
365 LazyValue base;
366
367 IrAnalyze *ira;
368 AstNode *proto_node;
369 IrInstruction **param_types;
370 IrInstruction *align_inst; // can be null
371 IrInstruction *return_type;
372
373 bool is_generic;
374};
375
376struct LazyValueErrUnionType {
377 LazyValue base;
378
379 IrAnalyze *ira;
380 IrInstruction *err_set_type;
381 IrInstruction *payload_type;
382};
383
294struct ConstExprValue {384struct ConstExprValue {
295 ZigType *type;385 ZigType *type;
296 ConstValSpecial special;386 ConstValSpecial special;
...@@ -318,6 +408,7 @@ struct ConstExprValue {...@@ -318,6 +408,7 @@ struct ConstExprValue {
318 ConstPtrValue x_ptr;408 ConstPtrValue x_ptr;
319 ConstArgTuple x_arg_tuple;409 ConstArgTuple x_arg_tuple;
320 Buf *x_enum_literal;410 Buf *x_enum_literal;
411 LazyValue *x_lazy;
321412
322 // populated if special == ConstValSpecialRuntime413 // populated if special == ConstValSpecialRuntime
323 RuntimeHintErrorUnion rh_error_union;414 RuntimeHintErrorUnion rh_error_union;
...@@ -364,6 +455,7 @@ enum TldResolution {...@@ -364,6 +455,7 @@ enum TldResolution {
364 TldResolutionUnresolved,455 TldResolutionUnresolved,
365 TldResolutionResolving,456 TldResolutionResolving,
366 TldResolutionInvalid,457 TldResolutionInvalid,
458 TldResolutionOkLazy,
367 TldResolutionOk,459 TldResolutionOk,
368};460};
369461
...@@ -420,10 +512,12 @@ struct TypeEnumField {...@@ -420,10 +512,12 @@ struct TypeEnumField {
420512
421struct TypeUnionField {513struct TypeUnionField {
422 Buf *name;514 Buf *name;
515 ZigType *type_entry; // available after ResolveStatusSizeKnown
516 ConstExprValue *type_val; // available after ResolveStatusZeroBitsKnown
423 TypeEnumField *enum_field;517 TypeEnumField *enum_field;
424 ZigType *type_entry;
425 AstNode *decl_node;518 AstNode *decl_node;
426 uint32_t gen_index;519 uint32_t gen_index;
520 uint32_t align;
427};521};
428522
429enum NodeType {523enum NodeType {
...@@ -849,6 +943,8 @@ struct AstNodeStructField {...@@ -849,6 +943,8 @@ struct AstNodeStructField {
849 Buf *name;943 Buf *name;
850 AstNode *type;944 AstNode *type;
851 AstNode *value;945 AstNode *value;
946 // populated if the "align(A)" is present
947 AstNode *align_expr;
852};948};
853949
854struct AstNodeStringLiteral {950struct AstNodeStringLiteral {
...@@ -944,6 +1040,7 @@ struct AstNodeEnumLiteral {...@@ -944,6 +1040,7 @@ struct AstNodeEnumLiteral {
9441040
945struct AstNode {1041struct AstNode {
946 enum NodeType type;1042 enum NodeType type;
1043 bool already_traced_this_node;
947 size_t line;1044 size_t line;
948 size_t column;1045 size_t column;
949 ZigType *owner;1046 ZigType *owner;
...@@ -1039,12 +1136,6 @@ struct FnTypeId {...@@ -1039,12 +1136,6 @@ struct FnTypeId {
1039uint32_t fn_type_id_hash(FnTypeId*);1136uint32_t fn_type_id_hash(FnTypeId*);
1040bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);1137bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
10411138
1042enum PtrLen {
1043 PtrLenUnknown,
1044 PtrLenSingle,
1045 PtrLenC,
1046};
1047
1048struct ZigTypePointer {1139struct ZigTypePointer {
1049 ZigType *child_type;1140 ZigType *child_type;
1050 ZigType *slice_parent;1141 ZigType *slice_parent;
...@@ -1055,6 +1146,7 @@ struct ZigTypePointer {...@@ -1055,6 +1146,7 @@ struct ZigTypePointer {
1055 bool is_const;1146 bool is_const;
1056 bool is_volatile;1147 bool is_volatile;
1057 bool allow_zero;1148 bool allow_zero;
1149 bool resolve_loop_flag_zero_bits;
1058};1150};
10591151
1060struct ZigTypeInt {1152struct ZigTypeInt {
...@@ -1073,7 +1165,8 @@ struct ZigTypeArray {...@@ -1073,7 +1165,8 @@ struct ZigTypeArray {
10731165
1074struct TypeStructField {1166struct TypeStructField {
1075 Buf *name;1167 Buf *name;
1076 ZigType *type_entry;1168 ZigType *type_entry; // available after ResolveStatusSizeKnown
1169 ConstExprValue *type_val; // available after ResolveStatusZeroBitsKnown
1077 size_t src_index;1170 size_t src_index;
1078 size_t gen_index;1171 size_t gen_index;
1079 size_t offset; // byte offset from beginning of struct1172 size_t offset; // byte offset from beginning of struct
...@@ -1129,15 +1222,16 @@ struct ZigTypeStruct {...@@ -1129,15 +1222,16 @@ struct ZigTypeStruct {
1129 ResolveStatus resolve_status;1222 ResolveStatus resolve_status;
11301223
1131 bool is_slice;1224 bool is_slice;
1132 bool resolve_loop_flag; // set this flag temporarily to detect infinite loops
1133 bool reported_infinite_err;
1134 // whether any of the fields require comptime1225 // whether any of the fields require comptime
1135 // known after ResolveStatusZeroBitsKnown1226 // known after ResolveStatusZeroBitsKnown
1136 bool requires_comptime;1227 bool requires_comptime;
1228 bool resolve_loop_flag_zero_bits;
1229 bool resolve_loop_flag_other;
1137};1230};
11381231
1139struct ZigTypeOptional {1232struct ZigTypeOptional {
1140 ZigType *child_type;1233 ZigType *child_type;
1234 ResolveStatus resolve_status;
1141};1235};
11421236
1143struct ZigTypeErrorUnion {1237struct ZigTypeErrorUnion {
...@@ -1155,26 +1249,20 @@ struct ZigTypeErrorSet {...@@ -1155,26 +1249,20 @@ struct ZigTypeErrorSet {
11551249
1156struct ZigTypeEnum {1250struct ZigTypeEnum {
1157 AstNode *decl_node;1251 AstNode *decl_node;
1158 ContainerLayout layout;
1159 uint32_t src_field_count;
1160 TypeEnumField *fields;1252 TypeEnumField *fields;
1161 bool is_invalid; // true if any fields are invalid
1162 ZigType *tag_int_type;1253 ZigType *tag_int_type;
11631254
1164 ScopeDecls *decls_scope;1255 ScopeDecls *decls_scope;
11651256
1166 // set this flag temporarily to detect infinite loops
1167 bool embedded_in_current;
1168 bool reported_infinite_err;
1169 // whether we've finished resolving it
1170 bool complete;
1171
1172 bool zero_bits_loop_flag;
1173 bool zero_bits_known;
1174
1175 LLVMValueRef name_function;1257 LLVMValueRef name_function;
11761258
1177 HashMap<Buf *, TypeEnumField *, buf_hash, buf_eql_buf> fields_by_name;1259 HashMap<Buf *, TypeEnumField *, buf_hash, buf_eql_buf> fields_by_name;
1260 uint32_t src_field_count;
1261
1262 ContainerLayout layout;
1263 ResolveStatus resolve_status;
1264
1265 bool resolve_loop_flag;
1178};1266};
11791267
1180uint32_t type_ptr_hash(const ZigType *ptr);1268uint32_t type_ptr_hash(const ZigType *ptr);
...@@ -1187,7 +1275,7 @@ struct ZigTypeUnion {...@@ -1187,7 +1275,7 @@ struct ZigTypeUnion {
1187 HashMap<Buf *, TypeUnionField *, buf_hash, buf_eql_buf> fields_by_name;1275 HashMap<Buf *, TypeUnionField *, buf_hash, buf_eql_buf> fields_by_name;
1188 ZigType *tag_type; // always an enum or null1276 ZigType *tag_type; // always an enum or null
1189 LLVMTypeRef union_llvm_type;1277 LLVMTypeRef union_llvm_type;
1190 ZigType *most_aligned_union_member;1278 TypeUnionField *most_aligned_union_member;
1191 size_t gen_union_index;1279 size_t gen_union_index;
1192 size_t gen_tag_index;1280 size_t gen_tag_index;
1193 size_t union_abi_size;1281 size_t union_abi_size;
...@@ -1199,11 +1287,11 @@ struct ZigTypeUnion {...@@ -1199,11 +1287,11 @@ struct ZigTypeUnion {
1199 ResolveStatus resolve_status;1287 ResolveStatus resolve_status;
12001288
1201 bool have_explicit_tag_type;1289 bool have_explicit_tag_type;
1202 bool resolve_loop_flag; // set this flag temporarily to detect infinite loops
1203 bool reported_infinite_err;
1204 // whether any of the fields require comptime1290 // whether any of the fields require comptime
1205 // the value is not valid until zero_bits_known == true1291 // the value is not valid until zero_bits_known == true
1206 bool requires_comptime;1292 bool requires_comptime;
1293 bool resolve_loop_flag_zero_bits;
1294 bool resolve_loop_flag_other;
1207};1295};
12081296
1209struct FnGenParamInfo {1297struct FnGenParamInfo {
...@@ -1715,6 +1803,7 @@ struct CodeGen {...@@ -1715,6 +1803,7 @@ struct CodeGen {
1715 //////////////////////////// Runtime State1803 //////////////////////////// Runtime State
1716 LLVMModuleRef module;1804 LLVMModuleRef module;
1717 ZigList<ErrorMsg*> errors;1805 ZigList<ErrorMsg*> errors;
1806 ErrorMsg *trace_err;
1718 LLVMBuilderRef builder;1807 LLVMBuilderRef builder;
1719 ZigLLVMDIBuilder *dbuilder;1808 ZigLLVMDIBuilder *dbuilder;
1720 ZigLLVMDICompileUnit *compile_unit;1809 ZigLLVMDICompileUnit *compile_unit;
...@@ -1767,7 +1856,6 @@ struct CodeGen {...@@ -1767,7 +1856,6 @@ struct CodeGen {
1767 ZigList<Tld *> resolve_queue;1856 ZigList<Tld *> resolve_queue;
1768 size_t resolve_queue_index;1857 size_t resolve_queue_index;
1769 ZigList<TimeEvent> timing_events;1858 ZigList<TimeEvent> timing_events;
1770 ZigList<AstNode *> tld_ref_source_node_stack;
1771 ZigList<ZigFn *> inline_fns;1859 ZigList<ZigFn *> inline_fns;
1772 ZigList<ZigFn *> test_fns;1860 ZigList<ZigFn *> test_fns;
1773 ZigList<ErrorTableEntry *> errors_by_index;1861 ZigList<ErrorTableEntry *> errors_by_index;
...@@ -1852,7 +1940,6 @@ struct CodeGen {...@@ -1852,7 +1940,6 @@ struct CodeGen {
1852 ZigFn *main_fn;1940 ZigFn *main_fn;
1853 ZigFn *panic_fn;1941 ZigFn *panic_fn;
1854 TldFn *panic_tld_fn;1942 TldFn *panic_tld_fn;
1855 AstNode *root_export_decl;
18561943
1857 WantPIC want_pic;1944 WantPIC want_pic;
1858 WantStackCheck want_stack_check;1945 WantStackCheck want_stack_check;
...@@ -1940,7 +2027,7 @@ struct CodeGen {...@@ -1940,7 +2027,7 @@ struct CodeGen {
1940 Buf *zig_lib_dir;2027 Buf *zig_lib_dir;
1941 Buf *zig_std_dir;2028 Buf *zig_std_dir;
1942 Buf *dynamic_linker_path;2029 Buf *dynamic_linker_path;
1943 Buf *version_script_path; 2030 Buf *version_script_path;
19442031
1945 const char **llvm_argv;2032 const char **llvm_argv;
1946 size_t llvm_argv_len;2033 size_t llvm_argv_len;
...@@ -3657,13 +3744,13 @@ enum ResultLocId {...@@ -3657,13 +3744,13 @@ enum ResultLocId {
3657 ResultLocIdBitCast,3744 ResultLocIdBitCast,
3658};3745};
36593746
3660// Additions to this struct may need to be handled in 3747// Additions to this struct may need to be handled in
3661// ir_reset_result3748// ir_reset_result
3662struct ResultLoc {3749struct ResultLoc {
3663 ResultLocId id;3750 ResultLocId id;
3664 bool written;3751 bool written;
3665 bool allow_write_through_const;3752 bool allow_write_through_const;
3666 IrInstruction *resolved_loc; // result ptr 3753 IrInstruction *resolved_loc; // result ptr
3667 IrInstruction *source_instruction;3754 IrInstruction *source_instruction;
3668 IrInstruction *gen_instruction; // value to store to the result loc3755 IrInstruction *gen_instruction; // value to store to the result loc
3669 ZigType *implicit_elem_type;3756 ZigType *implicit_elem_type;
src/analyze.cpp+853-479
...@@ -20,7 +20,7 @@...@@ -20,7 +20,7 @@
2020
21static const size_t default_backward_branch_quota = 1000;21static const size_t default_backward_branch_quota = 1000;
2222
23static Error resolve_struct_type(CodeGen *g, ZigType *struct_type);23static Error ATTRIBUTE_MUST_USE resolve_struct_type(CodeGen *g, ZigType *struct_type);
2424
25static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type);25static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type);
26static Error ATTRIBUTE_MUST_USE resolve_struct_alignment(CodeGen *g, ZigType *struct_type);26static Error ATTRIBUTE_MUST_USE resolve_struct_alignment(CodeGen *g, ZigType *struct_type);
...@@ -59,13 +59,15 @@ ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) {...@@ -59,13 +59,15 @@ ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) {
59 root_struct->source_code, root_struct->line_offsets, msg);59 root_struct->source_code, root_struct->line_offsets, msg);
6060
61 g->errors.append(err);61 g->errors.append(err);
62 g->trace_err = err;
62 return err;63 return err;
63}64}
6465
65ErrorMsg *add_node_error(CodeGen *g, const AstNode *node, Buf *msg) {66ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
66 Token fake_token;67 Token fake_token;
67 fake_token.start_line = node->line;68 fake_token.start_line = node->line;
68 fake_token.start_column = node->column;69 fake_token.start_column = node->column;
70 node->already_traced_this_node = true;
69 return add_token_error(g, node->owner, &fake_token, msg);71 return add_token_error(g, node->owner, &fake_token, msg);
70}72}
7173
...@@ -271,6 +273,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {...@@ -271,6 +273,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
271 return type_entry->data.structure.resolve_status >= status;273 return type_entry->data.structure.resolve_status >= status;
272 case ZigTypeIdUnion:274 case ZigTypeIdUnion:
273 return type_entry->data.unionation.resolve_status >= status;275 return type_entry->data.unionation.resolve_status >= status;
276 case ZigTypeIdEnum:
277 return type_entry->data.enumeration.resolve_status >= status;
274 case ZigTypeIdFnFrame:278 case ZigTypeIdFnFrame:
275 switch (status) {279 switch (status) {
276 case ResolveStatusInvalid:280 case ResolveStatusInvalid:
...@@ -285,32 +289,28 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {...@@ -285,32 +289,28 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
285 case ResolveStatusLLVMFull:289 case ResolveStatusLLVMFull:
286 return type_entry->llvm_type != nullptr;290 return type_entry->llvm_type != nullptr;
287 }291 }
288 case ZigTypeIdEnum:292 case ZigTypeIdOpaque:
293 return status < ResolveStatusSizeKnown;
294 case ZigTypeIdPointer:
289 switch (status) {295 switch (status) {
290 case ResolveStatusUnstarted:
291 return true;
292 case ResolveStatusInvalid:296 case ResolveStatusInvalid:
293 zig_unreachable();297 zig_unreachable();
298 case ResolveStatusUnstarted:
299 return true;
294 case ResolveStatusZeroBitsKnown:300 case ResolveStatusZeroBitsKnown:
295 return type_entry->data.enumeration.zero_bits_known;
296 case ResolveStatusAlignmentKnown:301 case ResolveStatusAlignmentKnown:
297 return type_entry->data.enumeration.zero_bits_known;
298 case ResolveStatusSizeKnown:302 case ResolveStatusSizeKnown:
299 return type_entry->data.enumeration.complete;303 return type_entry->abi_size != SIZE_MAX;
300 case ResolveStatusLLVMFwdDecl:304 case ResolveStatusLLVMFwdDecl:
301 case ResolveStatusLLVMFull:305 case ResolveStatusLLVMFull:
302 return type_entry->llvm_di_type != nullptr;306 return type_entry->llvm_type != nullptr;
303 }307 }
304 zig_unreachable();
305 case ZigTypeIdOpaque:
306 return status < ResolveStatusSizeKnown;
307 case ZigTypeIdMetaType:308 case ZigTypeIdMetaType:
308 case ZigTypeIdVoid:309 case ZigTypeIdVoid:
309 case ZigTypeIdBool:310 case ZigTypeIdBool:
310 case ZigTypeIdUnreachable:311 case ZigTypeIdUnreachable:
311 case ZigTypeIdInt:312 case ZigTypeIdInt:
312 case ZigTypeIdFloat:313 case ZigTypeIdFloat:
313 case ZigTypeIdPointer:
314 case ZigTypeIdArray:314 case ZigTypeIdArray:
315 case ZigTypeIdComptimeFloat:315 case ZigTypeIdComptimeFloat:
316 case ZigTypeIdComptimeInt:316 case ZigTypeIdComptimeInt:
...@@ -460,8 +460,6 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -460,8 +460,6 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
460 }460 }
461 }461 }
462462
463 assert(type_is_resolved(child_type, ResolveStatusZeroBitsKnown));
464
465 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);463 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
466464
467 const char *star_str = ptr_len_to_star_str(ptr_len);465 const char *star_str = ptr_len_to_star_str(ptr_len);
...@@ -491,17 +489,21 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -491,17 +489,21 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
491 buf_ptr(&child_type->name));489 buf_ptr(&child_type->name));
492 }490 }
493491
494 assert(child_type->id != ZigTypeIdInvalid);492 if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
495493 if (type_has_bits(child_type)) {
496 if (type_has_bits(child_type)) {494 entry->abi_size = g->builtin_types.entry_usize->abi_size;
497 entry->abi_size = g->builtin_types.entry_usize->abi_size;495 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
498 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;496 entry->abi_align = g->builtin_types.entry_usize->abi_align;
499 entry->abi_align = g->builtin_types.entry_usize->abi_align;497 } else {
498 assert(byte_alignment == 0);
499 entry->abi_size = 0;
500 entry->size_in_bits = 0;
501 entry->abi_align = 0;
502 }
500 } else {503 } else {
501 assert(byte_alignment == 0);504 entry->abi_size = SIZE_MAX;
502 entry->abi_size = 0;505 entry->size_in_bits = SIZE_MAX;
503 entry->size_in_bits = 0;506 entry->abi_align = UINT32_MAX;
504 entry->abi_align = 0;
505 }507 }
506508
507 entry->data.pointer.ptr_len = ptr_len;509 entry->data.pointer.ptr_len = ptr_len;
...@@ -564,6 +566,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {...@@ -564,6 +566,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
564 }566 }
565567
566 entry->data.maybe.child_type = child_type;568 entry->data.maybe.child_type = child_type;
569 entry->data.maybe.resolve_status = ResolveStatusSizeKnown;
567570
568 child_type->optional_parent = entry;571 child_type->optional_parent = entry;
569 return entry;572 return entry;
...@@ -865,7 +868,7 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -865,7 +868,7 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
865 return table_entry->value;868 return table_entry->value;
866 }869 }
867 if (fn_type_id->return_type != nullptr) {870 if (fn_type_id->return_type != nullptr) {
868 if ((err = ensure_complete_type(g, fn_type_id->return_type)))871 if ((err = type_resolve(g, fn_type_id->return_type, ResolveStatusSizeKnown)))
869 return g->builtin_types.entry_invalid;872 return g->builtin_types.entry_invalid;
870 assert(fn_type_id->return_type->id != ZigTypeIdOpaque);873 assert(fn_type_id->return_type->id != ZigTypeIdOpaque);
871 } else {874 } else {
...@@ -960,31 +963,276 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind...@@ -960,31 +963,276 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
960 return entry;963 return entry;
961}964}
962965
963ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {966ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
967 Buf *type_name, UndefAllowed undef)
968{
964 size_t backward_branch_count = 0;969 size_t backward_branch_count = 0;
965 size_t backward_branch_quota = default_backward_branch_quota;970 size_t backward_branch_quota = default_backward_branch_quota;
966 return ir_eval_const_value(g, scope, node, type_entry,971 return ir_eval_const_value(g, scope, node, type_entry,
967 &backward_branch_count, &backward_branch_quota,972 &backward_branch_count, &backward_branch_quota,
968 nullptr, nullptr, node, type_name, nullptr, nullptr);973 nullptr, nullptr, node, type_name, nullptr, nullptr, undef);
969}974}
970975
971ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {976static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type,
972 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);977 ConstExprValue *parent_type_val, bool *is_zero_bits)
973 if (type_is_invalid(result->type))978{
974 return g->builtin_types.entry_invalid;979 Error err;
980 if (type_val->special != ConstValSpecialLazy) {
981 assert(type_val->special == ConstValSpecialStatic);
982 if ((type_val->data.x_type->id == ZigTypeIdStruct &&
983 type_val->data.x_type->data.structure.resolve_loop_flag_zero_bits) ||
984 (type_val->data.x_type->id == ZigTypeIdUnion &&
985 type_val->data.x_type->data.unionation.resolve_loop_flag_zero_bits) ||
986 type_val->data.x_type->id == ZigTypeIdPointer)
987 {
988 // Does a struct/union which contains a pointer field to itself have bits? Yes.
989 *is_zero_bits = false;
990 return ErrorNone;
991 }
992 if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusZeroBitsKnown)))
993 return err;
994 *is_zero_bits = (type_val->data.x_type->abi_size == 0);
995 return ErrorNone;
996 }
997 switch (type_val->data.x_lazy->id) {
998 case LazyValueIdInvalid:
999 case LazyValueIdAlignOf:
1000 zig_unreachable();
1001 case LazyValueIdPtrType: {
1002 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
9751003
976 assert(result->special != ConstValSpecialRuntime);1004 if (parent_type_val == &lazy_ptr_type->elem_type->value) {
977 // Reject undefined as valid `type` type even though the specification1005 // Does a struct which contains a pointer field to itself have bits? Yes.
978 // allows it to be casted to anything.1006 *is_zero_bits = false;
979 // See also ir_resolve_type()1007 return ErrorNone;
980 if (result->special == ConstValSpecialUndef) {1008 } else {
981 add_node_error(g, node,1009 if (parent_type_val == nullptr) {
982 buf_sprintf("expected type 'type', found '%s'",1010 parent_type_val = type_val;
983 buf_ptr(&g->builtin_types.entry_undef->name)));1011 }
984 return g->builtin_types.entry_invalid;1012 return type_val_resolve_zero_bits(g, &lazy_ptr_type->elem_type->value, parent_type,
1013 parent_type_val, is_zero_bits);
1014 }
1015 }
1016 case LazyValueIdOptType:
1017 case LazyValueIdSliceType:
1018 case LazyValueIdErrUnionType:
1019 *is_zero_bits = false;
1020 return ErrorNone;
1021 case LazyValueIdFnType: {
1022 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
1023 *is_zero_bits = lazy_fn_type->is_generic;
1024 return ErrorNone;
1025 }
1026 }
1027 zig_unreachable();
1028}
1029
1030Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {
1031 if (type_val->special != ConstValSpecialLazy) {
1032 assert(type_val->special == ConstValSpecialStatic);
1033 *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);
1034 return ErrorNone;
1035 }
1036 switch (type_val->data.x_lazy->id) {
1037 case LazyValueIdInvalid:
1038 case LazyValueIdAlignOf:
1039 zig_unreachable();
1040 case LazyValueIdSliceType:
1041 case LazyValueIdPtrType:
1042 case LazyValueIdFnType:
1043 case LazyValueIdOptType:
1044 case LazyValueIdErrUnionType:
1045 *is_opaque_type = false;
1046 return ErrorNone;
1047 }
1048 zig_unreachable();
1049}
1050
1051static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue *type_val) {
1052 if (type_val->special != ConstValSpecialLazy) {
1053 return type_requires_comptime(g, type_val->data.x_type);
1054 }
1055 switch (type_val->data.x_lazy->id) {
1056 case LazyValueIdInvalid:
1057 case LazyValueIdAlignOf:
1058 zig_unreachable();
1059 case LazyValueIdSliceType: {
1060 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
1061 return type_val_resolve_requires_comptime(g, &lazy_slice_type->elem_type->value);
1062 }
1063 case LazyValueIdPtrType: {
1064 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
1065 return type_val_resolve_requires_comptime(g, &lazy_ptr_type->elem_type->value);
1066 }
1067 case LazyValueIdOptType: {
1068 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
1069 return type_val_resolve_requires_comptime(g, &lazy_opt_type->payload_type->value);
1070 }
1071 case LazyValueIdFnType: {
1072 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
1073 if (lazy_fn_type->is_generic)
1074 return ReqCompTimeYes;
1075 switch (type_val_resolve_requires_comptime(g, &lazy_fn_type->return_type->value)) {
1076 case ReqCompTimeInvalid:
1077 return ReqCompTimeInvalid;
1078 case ReqCompTimeYes:
1079 return ReqCompTimeYes;
1080 case ReqCompTimeNo:
1081 break;
1082 }
1083 size_t param_count = lazy_fn_type->proto_node->data.fn_proto.params.length;
1084 for (size_t i = 0; i < param_count; i += 1) {
1085 AstNode *param_node = lazy_fn_type->proto_node->data.fn_proto.params.at(i);
1086 bool param_is_var_args = param_node->data.param_decl.is_var_args;
1087 if (param_is_var_args) break;
1088 switch (type_val_resolve_requires_comptime(g, &lazy_fn_type->param_types[i]->value)) {
1089 case ReqCompTimeInvalid:
1090 return ReqCompTimeInvalid;
1091 case ReqCompTimeYes:
1092 return ReqCompTimeYes;
1093 case ReqCompTimeNo:
1094 break;
1095 }
1096 }
1097 return ReqCompTimeNo;
1098 }
1099 case LazyValueIdErrUnionType: {
1100 LazyValueErrUnionType *lazy_err_union_type =
1101 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
1102 return type_val_resolve_requires_comptime(g, &lazy_err_union_type->payload_type->value);
1103 }
1104 }
1105 zig_unreachable();
1106}
1107
1108static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstExprValue *type_val,
1109 size_t *abi_size, size_t *size_in_bits)
1110{
1111 Error err;
1112
1113start_over:
1114 if (type_val->special != ConstValSpecialLazy) {
1115 assert(type_val->special == ConstValSpecialStatic);
1116 ZigType *ty = type_val->data.x_type;
1117 if ((err = type_resolve(g, ty, ResolveStatusSizeKnown)))
1118 return err;
1119 *abi_size = ty->abi_size;
1120 *size_in_bits = ty->size_in_bits;
1121 return ErrorNone;
1122 }
1123 switch (type_val->data.x_lazy->id) {
1124 case LazyValueIdInvalid:
1125 case LazyValueIdAlignOf:
1126 zig_unreachable();
1127 case LazyValueIdSliceType:
1128 *abi_size = g->builtin_types.entry_usize->abi_size * 2;
1129 *size_in_bits = g->builtin_types.entry_usize->size_in_bits * 2;
1130 return ErrorNone;
1131 case LazyValueIdPtrType:
1132 case LazyValueIdFnType:
1133 *abi_size = g->builtin_types.entry_usize->abi_size;
1134 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1135 return ErrorNone;
1136 case LazyValueIdOptType:
1137 case LazyValueIdErrUnionType:
1138 if ((err = ir_resolve_lazy(g, source_node, type_val)))
1139 return err;
1140 goto start_over;
1141 }
1142 zig_unreachable();
1143}
1144
1145Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t *abi_align) {
1146 Error err;
1147 if (type_val->special != ConstValSpecialLazy) {
1148 assert(type_val->special == ConstValSpecialStatic);
1149 ZigType *ty = type_val->data.x_type;
1150 if (ty->id == ZigTypeIdPointer) {
1151 *abi_align = g->builtin_types.entry_usize->abi_align;
1152 return ErrorNone;
1153 }
1154 if ((err = type_resolve(g, ty, ResolveStatusAlignmentKnown)))
1155 return err;
1156 *abi_align = ty->abi_align;
1157 return ErrorNone;
1158 }
1159 switch (type_val->data.x_lazy->id) {
1160 case LazyValueIdInvalid:
1161 case LazyValueIdAlignOf:
1162 zig_unreachable();
1163 case LazyValueIdSliceType:
1164 case LazyValueIdPtrType:
1165 case LazyValueIdFnType:
1166 *abi_align = g->builtin_types.entry_usize->abi_align;
1167 return ErrorNone;
1168 case LazyValueIdOptType: {
1169 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
1170 return type_val_resolve_abi_align(g, &lazy_opt_type->payload_type->value, abi_align);
1171 }
1172 case LazyValueIdErrUnionType: {
1173 LazyValueErrUnionType *lazy_err_union_type =
1174 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
1175 uint32_t payload_abi_align;
1176 if ((err = type_val_resolve_abi_align(g, &lazy_err_union_type->payload_type->value,
1177 &payload_abi_align)))
1178 {
1179 return err;
1180 }
1181 *abi_align = (payload_abi_align > g->err_tag_type->abi_align) ?
1182 payload_abi_align : g->err_tag_type->abi_align;
1183 return ErrorNone;
1184 }
985 }1185 }
1186 zig_unreachable();
1187}
9861188
987 assert(result->data.x_type != nullptr);1189static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ConstExprValue *type_val) {
1190 if (type_val->special != ConstValSpecialLazy) {
1191 return type_has_one_possible_value(g, type_val->data.x_type);
1192 }
1193 switch (type_val->data.x_lazy->id) {
1194 case LazyValueIdInvalid:
1195 case LazyValueIdAlignOf:
1196 zig_unreachable();
1197 case LazyValueIdSliceType: // it has the len field
1198 case LazyValueIdOptType: // it has the optional bit
1199 case LazyValueIdFnType:
1200 return OnePossibleValueNo;
1201 case LazyValueIdPtrType: {
1202 Error err;
1203 bool zero_bits;
1204 if ((err = type_val_resolve_zero_bits(g, type_val, nullptr, nullptr, &zero_bits))) {
1205 return OnePossibleValueInvalid;
1206 }
1207 if (zero_bits) {
1208 return OnePossibleValueYes;
1209 } else {
1210 return OnePossibleValueNo;
1211 }
1212 }
1213 case LazyValueIdErrUnionType: {
1214 LazyValueErrUnionType *lazy_err_union_type =
1215 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
1216 switch (type_val_resolve_has_one_possible_value(g, &lazy_err_union_type->err_set_type->value)) {
1217 case OnePossibleValueInvalid:
1218 return OnePossibleValueInvalid;
1219 case OnePossibleValueNo:
1220 return OnePossibleValueNo;
1221 case OnePossibleValueYes:
1222 return type_val_resolve_has_one_possible_value(g, &lazy_err_union_type->payload_type->value);
1223 }
1224 }
1225 }
1226 zig_unreachable();
1227}
1228
1229ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
1230 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type,
1231 nullptr, UndefBad);
1232 if (type_is_invalid(result->type))
1233 return g->builtin_types.entry_invalid;
1234 src_assert(result->special == ConstValSpecialStatic, node);
1235 src_assert(result->data.x_type != nullptr, node);
988 return result->data.x_type;1236 return result->data.x_type;
989}1237}
9901238
...@@ -1032,11 +1280,12 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou...@@ -1032,11 +1280,12 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
1032}1280}
10331281
1034static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {1282static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
1035 ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);1283 ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g),
1284 nullptr, UndefBad);
1036 if (type_is_invalid(align_result->type))1285 if (type_is_invalid(align_result->type))
1037 return false;1286 return false;
10381287
1039 uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint);1288 uint32_t align_bytes = bigint_as_u32(&align_result->data.x_bigint);
1040 if (align_bytes == 0) {1289 if (align_bytes == 0) {
1041 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));1290 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
1042 return false;1291 return false;
...@@ -1054,7 +1303,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **...@@ -1054,7 +1303,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
1054 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,1303 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1055 PtrLenUnknown, 0, 0, 0, false);1304 PtrLenUnknown, 0, 0, 0, false);
1056 ZigType *str_type = get_slice_type(g, ptr_type);1305 ZigType *str_type = get_slice_type(g, ptr_type);
1057 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);1306 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr, UndefBad);
1058 if (type_is_invalid(result_val->type))1307 if (type_is_invalid(result_val->type))
1059 return false;1308 return false;
10601309
...@@ -1068,7 +1317,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **...@@ -1068,7 +1317,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
1068 return true;1317 return true;
1069 }1318 }
1070 expand_undef_array(g, array_val);1319 expand_undef_array(g, array_val);
1071 size_t len = bigint_as_unsigned(&len_field->data.x_bigint);1320 size_t len = bigint_as_usize(&len_field->data.x_bigint);
1072 Buf *result = buf_alloc();1321 Buf *result = buf_alloc();
1073 buf_resize(result, len);1322 buf_resize(result, len);
1074 for (size_t i = 0; i < len; i += 1) {1323 for (size_t i = 0; i < len; i += 1) {
...@@ -1078,7 +1327,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **...@@ -1078,7 +1327,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
1078 add_node_error(g, node, buf_sprintf("use of undefined value"));1327 add_node_error(g, node, buf_sprintf("use of undefined value"));
1079 return false;1328 return false;
1080 }1329 }
1081 uint64_t big_c = bigint_as_unsigned(&char_val->data.x_bigint);1330 uint64_t big_c = bigint_as_u64(&char_val->data.x_bigint);
1082 assert(big_c <= UINT8_MAX);1331 assert(big_c <= UINT8_MAX);
1083 uint8_t c = (uint8_t)big_c;1332 uint8_t c = (uint8_t)big_c;
1084 buf_ptr(result)[i] = c;1333 buf_ptr(result)[i] = c;
...@@ -1404,7 +1653,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1404,7 +1653,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1404 add_node_error(g, proto_node,1653 add_node_error(g, proto_node,
1405 buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447"));1654 buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447"));
1406 return g->builtin_types.entry_invalid;1655 return g->builtin_types.entry_invalid;
1407 //return get_generic_fn_type(g, &fn_type_id);
1408 }1656 }
14091657
1410 ZigType *specified_return_type = analyze_type_expr(g, child_scope, fn_proto->return_type);1658 ZigType *specified_return_type = analyze_type_expr(g, child_scope, fn_proto->return_type);
...@@ -1423,14 +1671,17 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1423,14 +1671,17 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1423 }1671 }
14241672
1425 if (!calling_convention_allows_zig_types(fn_type_id.cc) &&1673 if (!calling_convention_allows_zig_types(fn_type_id.cc) &&
1426 fn_type_id.return_type->id != ZigTypeIdVoid &&1674 fn_type_id.return_type->id != ZigTypeIdVoid)
1427 !type_allowed_in_extern(g, fn_type_id.return_type))
1428 {1675 {
1429 add_node_error(g, fn_proto->return_type,1676 if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown)))
1430 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",1677 return g->builtin_types.entry_invalid;
1431 buf_ptr(&fn_type_id.return_type->name),1678 if (!type_allowed_in_extern(g, fn_type_id.return_type)) {
1432 calling_convention_name(fn_type_id.cc)));1679 add_node_error(g, fn_proto->return_type,
1433 return g->builtin_types.entry_invalid;1680 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
1681 buf_ptr(&fn_type_id.return_type->name),
1682 calling_convention_name(fn_type_id.cc)));
1683 return g->builtin_types.entry_invalid;
1684 }
1434 }1685 }
14351686
1436 switch (fn_type_id.return_type->id) {1687 switch (fn_type_id.return_type->id) {
...@@ -1490,7 +1741,7 @@ bool type_is_invalid(ZigType *type_entry) {...@@ -1490,7 +1741,7 @@ bool type_is_invalid(ZigType *type_entry) {
1490 case ZigTypeIdUnion:1741 case ZigTypeIdUnion:
1491 return type_entry->data.unionation.resolve_status == ResolveStatusInvalid;1742 return type_entry->data.unionation.resolve_status == ResolveStatusInvalid;
1492 case ZigTypeIdEnum:1743 case ZigTypeIdEnum:
1493 return type_entry->data.enumeration.is_invalid;1744 return type_entry->data.enumeration.resolve_status == ResolveStatusInvalid;
1494 default:1745 default:
1495 return false;1746 return false;
1496 }1747 }
...@@ -1584,6 +1835,17 @@ static size_t get_abi_size_bytes(size_t size_in_bits, size_t pointer_size_bytes)...@@ -1584,6 +1835,17 @@ static size_t get_abi_size_bytes(size_t size_in_bits, size_t pointer_size_bytes)
1584 return align_forward(store_size_bytes, abi_align);1835 return align_forward(store_size_bytes, abi_align);
1585}1836}
15861837
1838ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field) {
1839 Error err;
1840 if (struct_field->type_entry == nullptr) {
1841 if ((err = ir_resolve_lazy(g, struct_field->decl_node, struct_field->type_val))) {
1842 return nullptr;
1843 }
1844 struct_field->type_entry = struct_field->type_val->data.x_type;
1845 }
1846 return struct_field->type_entry;
1847}
1848
1587static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {1849static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1588 assert(struct_type->id == ZigTypeIdStruct);1850 assert(struct_type->id == ZigTypeIdStruct);
15891851
...@@ -1599,12 +1861,11 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -1599,12 +1861,11 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
15991861
1600 AstNode *decl_node = struct_type->data.structure.decl_node;1862 AstNode *decl_node = struct_type->data.structure.decl_node;
16011863
1602 if (struct_type->data.structure.resolve_loop_flag) {1864 if (struct_type->data.structure.resolve_loop_flag_other) {
1603 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {1865 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
1604 struct_type->data.structure.resolve_status = ResolveStatusInvalid;1866 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1605 ErrorMsg *msg = add_node_error(g, decl_node,1867 add_node_error(g, decl_node,
1606 buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));1868 buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name)));
1607 emit_error_notes_for_ref_stack(g, msg);
1608 }1869 }
1609 return ErrorSemanticAnalyzeFail;1870 return ErrorSemanticAnalyzeFail;
1610 }1871 }
...@@ -1615,20 +1876,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -1615,20 +1876,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1615 size_t field_count = struct_type->data.structure.src_field_count;1876 size_t field_count = struct_type->data.structure.src_field_count;
16161877
1617 bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);1878 bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
1618 struct_type->data.structure.resolve_loop_flag = true;1879 struct_type->data.structure.resolve_loop_flag_other = true;
16191880
1620 uint32_t *host_int_bytes = packed ? allocate<uint32_t>(struct_type->data.structure.gen_field_count) : nullptr;1881 uint32_t *host_int_bytes = packed ? allocate<uint32_t>(struct_type->data.structure.gen_field_count) : nullptr;
16211882
1622 // Resolve sizes of all the field types. Done before the offset loop because the offset
1623 // loop has to look ahead.
1624 for (size_t i = 0; i < field_count; i += 1) {
1625 TypeStructField *field = &struct_type->data.structure.fields[i];
1626 if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) {
1627 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1628 return ErrorSemanticAnalyzeFail;
1629 }
1630 }
1631
1632 size_t packed_bits_offset = 0;1883 size_t packed_bits_offset = 0;
1633 size_t next_offset = 0;1884 size_t next_offset = 0;
1634 size_t first_packed_bits_offset_misalign = SIZE_MAX;1885 size_t first_packed_bits_offset_misalign = SIZE_MAX;
...@@ -1641,13 +1892,25 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -1641,13 +1892,25 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1641 TypeStructField *field = &struct_type->data.structure.fields[i];1892 TypeStructField *field = &struct_type->data.structure.fields[i];
1642 if (field->gen_index == SIZE_MAX)1893 if (field->gen_index == SIZE_MAX)
1643 continue;1894 continue;
1644 ZigType *field_type = field->type_entry;
1645 assert(field_type != nullptr);
16461895
1647 field->gen_index = gen_field_index;1896 field->gen_index = gen_field_index;
1648 field->offset = next_offset;1897 field->offset = next_offset;
16491898
1650 if (packed) {1899 if (packed) {
1900 ZigType *field_type = resolve_struct_field_type(g, field);
1901 if (field_type == nullptr) {
1902 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1903 return err;
1904 }
1905 if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) {
1906 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1907 return err;
1908 }
1909 if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field->type_entry, field->decl_node))) {
1910 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1911 return err;
1912 }
1913
1651 size_t field_size_in_bits = type_size_bits(g, field_type);1914 size_t field_size_in_bits = type_size_bits(g, field_type);
1652 size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits;1915 size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits;
16531916
...@@ -1683,6 +1946,15 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -1683,6 +1946,15 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1683 }1946 }
1684 packed_bits_offset = next_packed_bits_offset;1947 packed_bits_offset = next_packed_bits_offset;
1685 } else {1948 } else {
1949 size_t field_abi_size;
1950 size_t field_size_in_bits;
1951 if ((err = type_val_resolve_abi_size(g, field->decl_node, field->type_val,
1952 &field_abi_size, &field_size_in_bits)))
1953 {
1954 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1955 return err;
1956 }
1957
1686 gen_field_index += 1;1958 gen_field_index += 1;
1687 size_t next_src_field_index = i + 1;1959 size_t next_src_field_index = i + 1;
1688 for (; next_src_field_index < field_count; next_src_field_index += 1) {1960 for (; next_src_field_index < field_count; next_src_field_index += 1) {
...@@ -1690,9 +1962,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -1690,9 +1962,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1690 break;1962 break;
1691 }1963 }
1692 }1964 }
1693 size_t next_abi_align = (next_src_field_index == field_count) ?1965 size_t next_align = (next_src_field_index == field_count) ?
1694 abi_align : struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align;1966 abi_align : struct_type->data.structure.fields[next_src_field_index].align;
1695 next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, next_abi_align);1967 next_offset = next_field_offset(next_offset, abi_align, field_abi_size, next_align);
1696 size_in_bits = next_offset * 8;1968 size_in_bits = next_offset * 8;
1697 }1969 }
1698 }1970 }
...@@ -1708,9 +1980,39 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -1708,9 +1980,39 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1708 struct_type->size_in_bits = size_in_bits;1980 struct_type->size_in_bits = size_in_bits;
1709 struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;1981 struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
1710 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;1982 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
1711 struct_type->data.structure.resolve_loop_flag = false;1983 struct_type->data.structure.resolve_loop_flag_other = false;
1712 struct_type->data.structure.host_int_bytes = host_int_bytes;1984 struct_type->data.structure.host_int_bytes = host_int_bytes;
17131985
1986
1987 // Resolve types for fields
1988 if (!packed) {
1989 for (size_t i = 0; i < field_count; i += 1) {
1990 TypeStructField *field = &struct_type->data.structure.fields[i];
1991 ZigType *field_type = resolve_struct_field_type(g, field);
1992 if (field_type == nullptr) {
1993 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1994 return err;
1995 }
1996
1997 if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {
1998 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1999 return err;
2000 }
2001
2002 if (struct_type->data.structure.layout == ContainerLayoutExtern &&
2003 !type_allowed_in_extern(g, field_type))
2004 {
2005 add_node_error(g, field->decl_node,
2006 buf_sprintf("extern structs cannot contain fields of type '%s'",
2007 buf_ptr(&field_type->name)));
2008 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2009 return ErrorSemanticAnalyzeFail;
2010 }
2011
2012 }
2013 }
2014
2015
1714 return ErrorNone;2016 return ErrorNone;
1715}2017}
17162018
...@@ -1728,22 +2030,21 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {...@@ -1728,22 +2030,21 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
1728 if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown)2030 if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown)
1729 return ErrorNone;2031 return ErrorNone;
17302032
1731 if (union_type->data.unionation.resolve_loop_flag) {2033 AstNode *decl_node = union_type->data.structure.decl_node;
1732 if (!union_type->data.unionation.reported_infinite_err) {2034
1733 AstNode *decl_node = union_type->data.unionation.decl_node;2035 if (union_type->data.unionation.resolve_loop_flag_other) {
1734 union_type->data.unionation.reported_infinite_err = true;2036 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
1735 union_type->data.unionation.resolve_status = ResolveStatusInvalid;2037 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
1736 ErrorMsg *msg = add_node_error(g, decl_node,2038 add_node_error(g, decl_node,
1737 buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name)));2039 buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name)));
1738 emit_error_notes_for_ref_stack(g, msg);
1739 }2040 }
1740 return ErrorSemanticAnalyzeFail;2041 return ErrorSemanticAnalyzeFail;
1741 }2042 }
17422043
1743 // set temporary flag2044 // set temporary flag
1744 union_type->data.unionation.resolve_loop_flag = true;2045 union_type->data.unionation.resolve_loop_flag_other = true;
17452046
1746 ZigType *most_aligned_union_member = nullptr;2047 TypeUnionField *most_aligned_union_member = nullptr;
1747 uint32_t field_count = union_type->data.unionation.src_field_count;2048 uint32_t field_count = union_type->data.unionation.src_field_count;
1748 bool packed = union_type->data.unionation.layout == ContainerLayoutPacked;2049 bool packed = union_type->data.unionation.layout == ContainerLayoutPacked;
17492050
...@@ -1752,34 +2053,44 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {...@@ -1752,34 +2053,44 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
1752 if (field->gen_index == UINT32_MAX)2053 if (field->gen_index == UINT32_MAX)
1753 continue;2054 continue;
17542055
1755 size_t this_field_align;2056 AstNode *align_expr = field->decl_node->data.struct_field.align_expr;
1756 if (packed) {2057 if (align_expr != nullptr) {
1757 // TODO: https://github.com/ziglang/zig/issues/15122058 if (!analyze_const_align(g, &union_type->data.unionation.decls_scope->base, align_expr,
1758 this_field_align = 1;2059 &field->align))
1759 // This is the same hack as resolve_struct_alignment. See the comment there.2060 {
1760 } else if (field->type_entry == nullptr) {2061 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
1761 this_field_align = g->builtin_types.entry_usize->abi_align;2062 return err;
1762 } else {2063 }
2064 add_node_error(g, field->decl_node,
2065 buf_create_from_str("TODO implement field alignment syntax for unions. https://github.com/ziglang/zig/issues/3125"));
2066 } else if (packed) {
2067 field->align = 1;
2068 } else if (field->type_entry != nullptr) {
1763 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {2069 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
1764 union_type->data.unionation.resolve_status = ResolveStatusInvalid;2070 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
1765 return ErrorSemanticAnalyzeFail;2071 return err;
2072 }
2073 field->align = field->type_entry->abi_align;
2074 } else {
2075 if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) {
2076 if (g->trace_err != nullptr) {
2077 g->trace_err = add_error_note(g, g->trace_err, field->decl_node,
2078 buf_create_from_str("while checking this field"));
2079 }
2080 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2081 return err;
1766 }2082 }
1767
1768 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)2083 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
1769 return ErrorSemanticAnalyzeFail;2084 return ErrorSemanticAnalyzeFail;
1770
1771 this_field_align = field->type_entry->abi_align;
1772 }2085 }
17732086
1774 if (most_aligned_union_member == nullptr ||2087 if (most_aligned_union_member == nullptr || field->align > most_aligned_union_member->align) {
1775 this_field_align > most_aligned_union_member->abi_align)2088 most_aligned_union_member = field;
1776 {
1777 most_aligned_union_member = field->type_entry;
1778 }2089 }
1779 }2090 }
17802091
1781 // unset temporary flag2092 // unset temporary flag
1782 union_type->data.unionation.resolve_loop_flag = false;2093 union_type->data.unionation.resolve_loop_flag_other = false;
1783 union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown;2094 union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown;
1784 union_type->data.unionation.most_aligned_union_member = most_aligned_union_member;2095 union_type->data.unionation.most_aligned_union_member = most_aligned_union_member;
17852096
...@@ -1793,18 +2104,18 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {...@@ -1793,18 +2104,18 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
1793 union_type->abi_align = tag_type->abi_align;2104 union_type->abi_align = tag_type->abi_align;
1794 union_type->data.unionation.gen_tag_index = SIZE_MAX;2105 union_type->data.unionation.gen_tag_index = SIZE_MAX;
1795 union_type->data.unionation.gen_union_index = SIZE_MAX;2106 union_type->data.unionation.gen_union_index = SIZE_MAX;
1796 } else if (tag_type->abi_align > most_aligned_union_member->abi_align) {2107 } else if (tag_type->abi_align > most_aligned_union_member->align) {
1797 union_type->abi_align = tag_type->abi_align;2108 union_type->abi_align = tag_type->abi_align;
1798 union_type->data.unionation.gen_tag_index = 0;2109 union_type->data.unionation.gen_tag_index = 0;
1799 union_type->data.unionation.gen_union_index = 1;2110 union_type->data.unionation.gen_union_index = 1;
1800 } else {2111 } else {
1801 union_type->abi_align = most_aligned_union_member->abi_align;2112 union_type->abi_align = most_aligned_union_member->align;
1802 union_type->data.unionation.gen_union_index = 0;2113 union_type->data.unionation.gen_union_index = 0;
1803 union_type->data.unionation.gen_tag_index = 1;2114 union_type->data.unionation.gen_tag_index = 1;
1804 }2115 }
1805 } else {2116 } else {
1806 assert(most_aligned_union_member != nullptr);2117 assert(most_aligned_union_member != nullptr);
1807 union_type->abi_align = most_aligned_union_member->abi_align;2118 union_type->abi_align = most_aligned_union_member->align;
1808 union_type->data.unionation.gen_union_index = SIZE_MAX;2119 union_type->data.unionation.gen_union_index = SIZE_MAX;
1809 union_type->data.unionation.gen_tag_index = SIZE_MAX;2120 union_type->data.unionation.gen_tag_index = SIZE_MAX;
1810 }2121 }
...@@ -1812,6 +2123,17 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {...@@ -1812,6 +2123,17 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
1812 return ErrorNone;2123 return ErrorNone;
1813}2124}
18142125
2126ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field) {
2127 Error err;
2128 if (union_field->type_entry == nullptr) {
2129 if ((err = ir_resolve_lazy(g, union_field->decl_node, union_field->type_val))) {
2130 return nullptr;
2131 }
2132 union_field->type_entry = union_field->type_val->data.x_type;
2133 }
2134 return union_field->type_entry;
2135}
2136
1815static Error resolve_union_type(CodeGen *g, ZigType *union_type) {2137static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
1816 assert(union_type->id == ZigTypeIdUnion);2138 assert(union_type->id == ZigTypeIdUnion);
18172139
...@@ -1831,30 +2153,32 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {...@@ -1831,30 +2153,32 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
1831 assert(decl_node->type == NodeTypeContainerDecl);2153 assert(decl_node->type == NodeTypeContainerDecl);
18322154
1833 uint32_t field_count = union_type->data.unionation.src_field_count;2155 uint32_t field_count = union_type->data.unionation.src_field_count;
1834 ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;2156 TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
18352157
1836 assert(union_type->data.unionation.fields);2158 assert(union_type->data.unionation.fields);
18372159
1838 size_t union_abi_size = 0;2160 size_t union_abi_size = 0;
1839 size_t union_size_in_bits = 0;2161 size_t union_size_in_bits = 0;
18402162
1841 if (union_type->data.unionation.resolve_loop_flag) {2163 if (union_type->data.unionation.resolve_loop_flag_other) {
1842 if (!union_type->data.unionation.reported_infinite_err) {2164 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
1843 union_type->data.unionation.reported_infinite_err = true;
1844 union_type->data.unionation.resolve_status = ResolveStatusInvalid;2165 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
1845 ErrorMsg *msg = add_node_error(g, decl_node,2166 add_node_error(g, decl_node,
1846 buf_sprintf("union '%s' depends on its own size", buf_ptr(&union_type->name)));2167 buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name)));
1847 emit_error_notes_for_ref_stack(g, msg);
1848 }2168 }
1849 return ErrorSemanticAnalyzeFail;2169 return ErrorSemanticAnalyzeFail;
1850 }2170 }
18512171
1852 // set temporary flag2172 // set temporary flag
1853 union_type->data.unionation.resolve_loop_flag = true;2173 union_type->data.unionation.resolve_loop_flag_other = true;
18542174
1855 for (uint32_t i = 0; i < field_count; i += 1) {2175 for (uint32_t i = 0; i < field_count; i += 1) {
1856 TypeUnionField *union_field = &union_type->data.unionation.fields[i];2176 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
1857 ZigType *field_type = union_field->type_entry;2177 ZigType *field_type = resolve_union_field_type(g, union_field);
2178 if (field_type == nullptr) {
2179 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2180 return ErrorSemanticAnalyzeFail;
2181 }
18582182
1859 if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {2183 if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {
1860 union_type->data.unionation.resolve_status = ResolveStatusInvalid;2184 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
...@@ -1874,11 +2198,11 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {...@@ -1874,11 +2198,11 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
1874 // The union itself for now has to be treated as being independently aligned.2198 // The union itself for now has to be treated as being independently aligned.
1875 // See https://github.com/ziglang/zig/issues/2166.2199 // See https://github.com/ziglang/zig/issues/2166.
1876 if (most_aligned_union_member != nullptr) {2200 if (most_aligned_union_member != nullptr) {
1877 union_abi_size = align_forward(union_abi_size, most_aligned_union_member->abi_align);2201 union_abi_size = align_forward(union_abi_size, most_aligned_union_member->align);
1878 }2202 }
18792203
1880 // unset temporary flag2204 // unset temporary flag
1881 union_type->data.unionation.resolve_loop_flag = false;2205 union_type->data.unionation.resolve_loop_flag_other = false;
1882 union_type->data.unionation.resolve_status = ResolveStatusSizeKnown;2206 union_type->data.unionation.resolve_status = ResolveStatusSizeKnown;
1883 union_type->data.unionation.union_abi_size = union_abi_size;2207 union_type->data.unionation.union_abi_size = union_abi_size;
18842208
...@@ -1897,7 +2221,7 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {...@@ -1897,7 +2221,7 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
1897 field_sizes[union_type->data.unionation.gen_tag_index] = tag_type->abi_size;2221 field_sizes[union_type->data.unionation.gen_tag_index] = tag_type->abi_size;
1898 field_aligns[union_type->data.unionation.gen_tag_index] = tag_type->abi_align;2222 field_aligns[union_type->data.unionation.gen_tag_index] = tag_type->abi_align;
1899 field_sizes[union_type->data.unionation.gen_union_index] = union_abi_size;2223 field_sizes[union_type->data.unionation.gen_union_index] = union_abi_size;
1900 field_aligns[union_type->data.unionation.gen_union_index] = most_aligned_union_member->abi_align;2224 field_aligns[union_type->data.unionation.gen_union_index] = most_aligned_union_member->align;
1901 size_t field2_offset = next_field_offset(0, union_type->abi_align, field_sizes[0], field_aligns[1]);2225 size_t field2_offset = next_field_offset(0, union_type->abi_align, field_sizes[0], field_aligns[1]);
1902 union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], union_type->abi_align);2226 union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], union_type->abi_align);
1903 union_type->size_in_bits = union_type->abi_size * 8;2227 union_type->size_in_bits = union_type->abi_size * 8;
...@@ -1925,24 +2249,25 @@ static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) {...@@ -1925,24 +2249,25 @@ static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) {
1925static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {2249static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
1926 assert(enum_type->id == ZigTypeIdEnum);2250 assert(enum_type->id == ZigTypeIdEnum);
19272251
1928 if (enum_type->data.enumeration.is_invalid)2252 if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
1929 return ErrorSemanticAnalyzeFail;2253 return ErrorSemanticAnalyzeFail;
19302254 if (enum_type->data.enumeration.resolve_status >= ResolveStatusZeroBitsKnown)
1931 if (enum_type->data.enumeration.zero_bits_known)
1932 return ErrorNone;2255 return ErrorNone;
19332256
1934 if (enum_type->data.enumeration.zero_bits_loop_flag) {2257 AstNode *decl_node = enum_type->data.enumeration.decl_node;
1935 ErrorMsg *msg = add_node_error(g, enum_type->data.enumeration.decl_node,2258 assert(decl_node->type == NodeTypeContainerDecl);
1936 buf_sprintf("'%s' depends on itself", buf_ptr(&enum_type->name)));2259
1937 emit_error_notes_for_ref_stack(g, msg);2260 if (enum_type->data.enumeration.resolve_loop_flag) {
1938 enum_type->data.enumeration.is_invalid = true;2261 if (enum_type->data.enumeration.resolve_status != ResolveStatusInvalid) {
2262 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2263 add_node_error(g, decl_node,
2264 buf_sprintf("enum '%s' depends on itself",
2265 buf_ptr(&enum_type->name)));
2266 }
1939 return ErrorSemanticAnalyzeFail;2267 return ErrorSemanticAnalyzeFail;
1940 }2268 }
19412269
1942 enum_type->data.enumeration.zero_bits_loop_flag = true;2270 enum_type->data.enumeration.resolve_loop_flag = true;
1943
1944 AstNode *decl_node = enum_type->data.enumeration.decl_node;
1945 assert(decl_node->type == NodeTypeContainerDecl);
19462271
1947 assert(!enum_type->data.enumeration.fields);2272 assert(!enum_type->data.enumeration.fields);
1948 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;2273 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
...@@ -1951,9 +2276,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -1951,9 +2276,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
19512276
1952 enum_type->data.enumeration.src_field_count = field_count;2277 enum_type->data.enumeration.src_field_count = field_count;
1953 enum_type->data.enumeration.fields = nullptr;2278 enum_type->data.enumeration.fields = nullptr;
1954 enum_type->data.enumeration.is_invalid = true;2279 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
1955 enum_type->data.enumeration.zero_bits_loop_flag = false;
1956 enum_type->data.enumeration.zero_bits_known = true;
1957 return ErrorSemanticAnalyzeFail;2280 return ErrorSemanticAnalyzeFail;
1958 }2281 }
19592282
...@@ -1982,14 +2305,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -1982,14 +2305,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
1982 if (decl_node->data.container_decl.init_arg_expr != nullptr) {2305 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
1983 ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);2306 ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
1984 if (type_is_invalid(wanted_tag_int_type)) {2307 if (type_is_invalid(wanted_tag_int_type)) {
1985 enum_type->data.enumeration.is_invalid = true;2308 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
1986 } else if (wanted_tag_int_type->id != ZigTypeIdInt) {2309 } else if (wanted_tag_int_type->id != ZigTypeIdInt) {
1987 enum_type->data.enumeration.is_invalid = true;2310 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
1988 add_node_error(g, decl_node->data.container_decl.init_arg_expr,2311 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
1989 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));2312 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
1990 } else if (enum_type->data.enumeration.layout == ContainerLayoutExtern &&2313 } else if (enum_type->data.enumeration.layout == ContainerLayoutExtern &&
1991 !type_is_valid_extern_enum_tag(g, wanted_tag_int_type)) {2314 !type_is_valid_extern_enum_tag(g, wanted_tag_int_type)) {
1992 enum_type->data.enumeration.is_invalid = true;2315 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
1993 ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr,2316 ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr,
1994 buf_sprintf("'%s' is not a valid tag type for an extern enum",2317 buf_sprintf("'%s' is not a valid tag type for an extern enum",
1995 buf_ptr(&wanted_tag_int_type->name)));2318 buf_ptr(&wanted_tag_int_type->name)));
...@@ -2022,6 +2345,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2022,6 +2345,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2022 buf_sprintf("structs and unions, not enums, support field types"));2345 buf_sprintf("structs and unions, not enums, support field types"));
2023 add_error_note(g, msg, decl_node,2346 add_error_note(g, msg, decl_node,
2024 buf_sprintf("consider 'union(enum)' here"));2347 buf_sprintf("consider 'union(enum)' here"));
2348 } else if (field_node->data.struct_field.align_expr != nullptr) {
2349 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.align_expr,
2350 buf_sprintf("structs and unions, not enums, support field alignment"));
2351 add_error_note(g, msg, decl_node,
2352 buf_sprintf("consider 'union(enum)' here"));
2025 }2353 }
20262354
2027 auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);2355 auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);
...@@ -2029,7 +2357,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2029,7 +2357,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2029 ErrorMsg *msg = add_node_error(g, field_node,2357 ErrorMsg *msg = add_node_error(g, field_node,
2030 buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));2358 buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));
2031 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));2359 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
2032 enum_type->data.enumeration.is_invalid = true;2360 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2033 continue;2361 continue;
2034 }2362 }
20352363
...@@ -2037,9 +2365,10 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2037,9 +2365,10 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
20372365
2038 if (tag_value != nullptr) {2366 if (tag_value != nullptr) {
2039 // A user-specified value is available2367 // A user-specified value is available
2040 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);2368 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
2369 nullptr, UndefBad);
2041 if (type_is_invalid(result->type)) {2370 if (type_is_invalid(result->type)) {
2042 enum_type->data.enumeration.is_invalid = true;2371 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2043 continue;2372 continue;
2044 }2373 }
20452374
...@@ -2060,7 +2389,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2060,7 +2389,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2060 if (!bigint_fits_in_bits(&type_enum_field->value,2389 if (!bigint_fits_in_bits(&type_enum_field->value,
2061 tag_int_type->size_in_bits,2390 tag_int_type->size_in_bits,
2062 tag_int_type->data.integral.is_signed)) {2391 tag_int_type->data.integral.is_signed)) {
2063 enum_type->data.enumeration.is_invalid = true;2392 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
20642393
2065 Buf *val_buf = buf_alloc();2394 Buf *val_buf = buf_alloc();
2066 bigint_append_buf(val_buf, &type_enum_field->value, 10);2395 bigint_append_buf(val_buf, &type_enum_field->value, 10);
...@@ -2075,7 +2404,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2075,7 +2404,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2075 // Make sure the value is unique2404 // Make sure the value is unique
2076 auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);2405 auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
2077 if (entry != nullptr) {2406 if (entry != nullptr) {
2078 enum_type->data.enumeration.is_invalid = true;2407 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
20792408
2080 Buf *val_buf = buf_alloc();2409 Buf *val_buf = buf_alloc();
2081 bigint_append_buf(val_buf, &type_enum_field->value, 10);2410 bigint_append_buf(val_buf, &type_enum_field->value, 10);
...@@ -2089,13 +2418,12 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2089,13 +2418,12 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2089 last_enum_field = type_enum_field;2418 last_enum_field = type_enum_field;
2090 }2419 }
20912420
2092 enum_type->data.enumeration.zero_bits_loop_flag = false;2421 if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
2093 enum_type->data.enumeration.zero_bits_known = true;
2094 enum_type->data.enumeration.complete = true;
2095
2096 if (enum_type->data.enumeration.is_invalid)
2097 return ErrorSemanticAnalyzeFail;2422 return ErrorSemanticAnalyzeFail;
20982423
2424 enum_type->data.enumeration.resolve_loop_flag = false;
2425 enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
2426
2099 return ErrorNone;2427 return ErrorNone;
2100}2428}
21012429
...@@ -2112,16 +2440,17 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2112,16 +2440,17 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2112 AstNode *decl_node = struct_type->data.structure.decl_node;2440 AstNode *decl_node = struct_type->data.structure.decl_node;
2113 assert(decl_node->type == NodeTypeContainerDecl);2441 assert(decl_node->type == NodeTypeContainerDecl);
21142442
2115 if (struct_type->data.structure.resolve_loop_flag) {2443 if (struct_type->data.structure.resolve_loop_flag_zero_bits) {
2116 // TODO This is a problem. I believe it can be solved with lazy values.2444 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
2117 struct_type->size_in_bits = SIZE_MAX;2445 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2118 struct_type->abi_size = SIZE_MAX;2446 add_node_error(g, decl_node,
2119 struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown;2447 buf_sprintf("struct '%s' depends on itself",
2120 struct_type->data.structure.resolve_loop_flag = false;2448 buf_ptr(&struct_type->name)));
2121 return ErrorNone;2449 }
2450 return ErrorSemanticAnalyzeFail;
2122 }2451 }
21232452
2124 struct_type->data.structure.resolve_loop_flag = true;2453 struct_type->data.structure.resolve_loop_flag_zero_bits = true;
21252454
2126 assert(!struct_type->data.structure.fields);2455 assert(!struct_type->data.structure.fields);
2127 size_t field_count = decl_node->data.container_decl.fields.length;2456 size_t field_count = decl_node->data.container_decl.fields.length;
...@@ -2153,58 +2482,60 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2153,58 +2482,60 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2153 return ErrorSemanticAnalyzeFail;2482 return ErrorSemanticAnalyzeFail;
2154 }2483 }
21552484
2156 ZigType *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);2485 ConstExprValue *field_type_val = analyze_const_value(g, scope,
2157 type_struct_field->type_entry = field_type;2486 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
2158 if (type_is_invalid(field_type)) {2487 if (type_is_invalid(field_type_val->type)) {
2159 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2488 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2160 return ErrorSemanticAnalyzeFail;2489 return ErrorSemanticAnalyzeFail;
2161 }2490 }
2491 assert(field_type_val->special != ConstValSpecialRuntime);
2492 type_struct_field->type_val = field_type_val;
2162 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)2493 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2163 return ErrorSemanticAnalyzeFail;2494 return ErrorSemanticAnalyzeFail;
21642495
2165 if (struct_type->data.structure.layout == ContainerLayoutExtern &&2496 bool field_is_opaque_type;
2166 !type_allowed_in_extern(g, field_type))2497 if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
2167 {
2168 add_node_error(g, field_node,
2169 buf_sprintf("extern structs cannot contain fields of type '%s'",
2170 buf_ptr(&field_type->name)));
2171 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2498 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2172 return ErrorSemanticAnalyzeFail;2499 return ErrorSemanticAnalyzeFail;
2173 } else if (struct_type->data.structure.layout == ContainerLayoutPacked) {
2174 if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_node))) {
2175 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2176 return ErrorSemanticAnalyzeFail;
2177 }
2178 }2500 }
21792501 if (field_is_opaque_type) {
2180 type_struct_field->src_index = i;
2181 type_struct_field->gen_index = SIZE_MAX;
2182
2183 if (field_type->id == ZigTypeIdOpaque) {
2184 add_node_error(g, field_node->data.struct_field.type,2502 add_node_error(g, field_node->data.struct_field.type,
2185 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));2503 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
2186 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2504 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2187 return ErrorSemanticAnalyzeFail;2505 return ErrorSemanticAnalyzeFail;
2188 }2506 }
2189 switch (type_requires_comptime(g, field_type)) {2507
2508 type_struct_field->src_index = i;
2509 type_struct_field->gen_index = SIZE_MAX;
2510
2511 switch (type_val_resolve_requires_comptime(g, field_type_val)) {
2190 case ReqCompTimeYes:2512 case ReqCompTimeYes:
2191 struct_type->data.structure.requires_comptime = true;2513 struct_type->data.structure.requires_comptime = true;
2192 break;2514 break;
2193 case ReqCompTimeInvalid:2515 case ReqCompTimeInvalid:
2516 if (g->trace_err != nullptr) {
2517 g->trace_err = add_error_note(g, g->trace_err, field_node,
2518 buf_create_from_str("while checking this field"));
2519 }
2194 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2520 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2195 return ErrorSemanticAnalyzeFail;2521 return ErrorSemanticAnalyzeFail;
2196 case ReqCompTimeNo:2522 case ReqCompTimeNo:
2197 break;2523 break;
2198 }2524 }
21992525
2200 if (!type_has_bits(field_type))2526 bool field_is_zero_bits;
2527 if ((err = type_val_resolve_zero_bits(g, field_type_val, struct_type, nullptr, &field_is_zero_bits))) {
2528 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2529 return ErrorSemanticAnalyzeFail;
2530 }
2531 if (field_is_zero_bits)
2201 continue;2532 continue;
22022533
2203 type_struct_field->gen_index = gen_field_index;2534 type_struct_field->gen_index = gen_field_index;
2204 gen_field_index += 1;2535 gen_field_index += 1;
2205 }2536 }
22062537
2207 struct_type->data.structure.resolve_loop_flag = false;2538 struct_type->data.structure.resolve_loop_flag_zero_bits = false;
2208 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;2539 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
2209 if (gen_field_index != 0) {2540 if (gen_field_index != 0) {
2210 struct_type->abi_size = SIZE_MAX;2541 struct_type->abi_size = SIZE_MAX;
...@@ -2234,17 +2565,16 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {...@@ -2234,17 +2565,16 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
22342565
2235 AstNode *decl_node = struct_type->data.structure.decl_node;2566 AstNode *decl_node = struct_type->data.structure.decl_node;
22362567
2237 if (struct_type->data.structure.resolve_loop_flag) {2568 if (struct_type->data.structure.resolve_loop_flag_other) {
2238 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {2569 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
2239 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2570 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2240 ErrorMsg *msg = add_node_error(g, decl_node,2571 add_node_error(g, decl_node,
2241 buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));2572 buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name)));
2242 emit_error_notes_for_ref_stack(g, msg);
2243 }2573 }
2244 return ErrorSemanticAnalyzeFail;2574 return ErrorSemanticAnalyzeFail;
2245 }2575 }
22462576
2247 struct_type->data.structure.resolve_loop_flag = true;2577 struct_type->data.structure.resolve_loop_flag_other = true;
2248 assert(decl_node->type == NodeTypeContainerDecl);2578 assert(decl_node->type == NodeTypeContainerDecl);
22492579
2250 size_t field_count = struct_type->data.structure.src_field_count;2580 size_t field_count = struct_type->data.structure.src_field_count;
...@@ -2255,35 +2585,35 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {...@@ -2255,35 +2585,35 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
2255 if (field->gen_index == SIZE_MAX)2585 if (field->gen_index == SIZE_MAX)
2256 continue;2586 continue;
22572587
2258 size_t this_field_align;2588 AstNode *align_expr = field->decl_node->data.struct_field.align_expr;
2259 if (packed) {2589 if (align_expr != nullptr) {
2260 // TODO: https://github.com/ziglang/zig/issues/15122590 if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr,
2261 this_field_align = 1;2591 &field->align))
2262 // TODO If we have no type_entry for the field, we've already failed to2592 {
2263 // compile the program correctly. This stage1 compiler needs a deeper2593 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2264 // reworking to make this correct, or we can ignore the problem2594 return err;
2265 // and make sure it is fixed in stage2. This workaround is for when2595 }
2266 // there is a false positive of a dependency loop, of alignment depending2596 } else if (packed) {
2267 // on itself. When this false positive happens we assume a pointer-aligned2597 field->align = 1;
2268 // field, which is usually fine but could be incorrectly over-aligned or
2269 // even under-aligned. See https://github.com/ziglang/zig/issues/1512
2270 } else if (field->type_entry == nullptr) {
2271 this_field_align = g->builtin_types.entry_usize->abi_align;
2272 } else {2598 } else {
2273 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {2599 if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) {
2600 if (g->trace_err != nullptr) {
2601 g->trace_err = add_error_note(g, g->trace_err, field->decl_node,
2602 buf_create_from_str("while checking this field"));
2603 }
2274 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2604 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2275 return ErrorSemanticAnalyzeFail;2605 return err;
2276 }2606 }
2277 this_field_align = field->type_entry->abi_align;2607 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2608 return ErrorSemanticAnalyzeFail;
2278 }2609 }
22792610
2280 // TODO: https://github.com/ziglang/zig/issues/15122611 if (field->align > struct_type->abi_align) {
2281 if (this_field_align > struct_type->abi_align) {2612 struct_type->abi_align = field->align;
2282 struct_type->abi_align = this_field_align;
2283 }2613 }
2284 }2614 }
22852615
2286 struct_type->data.structure.resolve_loop_flag = false;2616 struct_type->data.structure.resolve_loop_flag_other = false;
22872617
2288 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {2618 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {
2289 return ErrorSemanticAnalyzeFail;2619 return ErrorSemanticAnalyzeFail;
...@@ -2304,23 +2634,21 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2304,23 +2634,21 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2304 if (union_type->data.unionation.resolve_status >= ResolveStatusZeroBitsKnown)2634 if (union_type->data.unionation.resolve_status >= ResolveStatusZeroBitsKnown)
2305 return ErrorNone;2635 return ErrorNone;
23062636
2307 if (union_type->data.unionation.resolve_loop_flag) {
2308 // If we get here it's due to recursion. From this we conclude that the struct is
2309 // not zero bits.
2310 // TODO actually it could still be zero bits. Here we should continue analyzing
2311 // the union from the next field index.
2312 union_type->data.unionation.resolve_status = ResolveStatusZeroBitsKnown;
2313 union_type->data.unionation.resolve_loop_flag = false;
2314 union_type->abi_size = SIZE_MAX;
2315 union_type->size_in_bits = SIZE_MAX;
2316 return ErrorNone;
2317 }
2318
2319 union_type->data.unionation.resolve_loop_flag = true;
2320
2321 AstNode *decl_node = union_type->data.unionation.decl_node;2637 AstNode *decl_node = union_type->data.unionation.decl_node;
2322 assert(decl_node->type == NodeTypeContainerDecl);2638 assert(decl_node->type == NodeTypeContainerDecl);
23232639
2640 if (union_type->data.unionation.resolve_loop_flag_zero_bits) {
2641 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
2642 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2643 add_node_error(g, decl_node,
2644 buf_sprintf("union '%s' depends on itself",
2645 buf_ptr(&union_type->name)));
2646 }
2647 return ErrorSemanticAnalyzeFail;
2648 }
2649
2650 union_type->data.unionation.resolve_loop_flag_zero_bits = true;
2651
2324 assert(union_type->data.unionation.fields == nullptr);2652 assert(union_type->data.unionation.fields == nullptr);
2325 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;2653 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
2326 if (field_count == 0) {2654 if (field_count == 0) {
...@@ -2380,14 +2708,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2380,14 +2708,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2380 tag_type->size_in_bits = tag_int_type->size_in_bits;2708 tag_type->size_in_bits = tag_int_type->size_in_bits;
23812709
2382 tag_type->data.enumeration.tag_int_type = tag_int_type;2710 tag_type->data.enumeration.tag_int_type = tag_int_type;
2383 tag_type->data.enumeration.zero_bits_known = true;2711 tag_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
2384 tag_type->data.enumeration.decl_node = decl_node;2712 tag_type->data.enumeration.decl_node = decl_node;
2385 tag_type->data.enumeration.layout = ContainerLayoutAuto;2713 tag_type->data.enumeration.layout = ContainerLayoutAuto;
2386 tag_type->data.enumeration.src_field_count = field_count;2714 tag_type->data.enumeration.src_field_count = field_count;
2387 tag_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);2715 tag_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
2388 tag_type->data.enumeration.fields_by_name.init(field_count);2716 tag_type->data.enumeration.fields_by_name.init(field_count);
2389 tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope;2717 tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope;
2390 tag_type->data.enumeration.complete = true;
2391 } else if (enum_type_node != nullptr) {2718 } else if (enum_type_node != nullptr) {
2392 ZigType *enum_type = analyze_type_expr(g, scope, enum_type_node);2719 ZigType *enum_type = analyze_type_expr(g, scope, enum_type_node);
2393 if (type_is_invalid(enum_type)) {2720 if (type_is_invalid(enum_type)) {
...@@ -2429,49 +2756,68 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2429,49 +2756,68 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2429 return ErrorSemanticAnalyzeFail;2756 return ErrorSemanticAnalyzeFail;
2430 }2757 }
24312758
2432 ZigType *field_type;2759 bool field_is_zero_bits;
2433 if (field_node->data.struct_field.type == nullptr) {2760 if (field_node->data.struct_field.type == nullptr) {
2434 if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) {2761 if (decl_node->data.container_decl.auto_enum ||
2435 field_type = g->builtin_types.entry_void;2762 decl_node->data.container_decl.init_arg_expr != nullptr)
2763 {
2764 union_field->type_entry = g->builtin_types.entry_void;
2765 field_is_zero_bits = true;
2436 } else {2766 } else {
2437 add_node_error(g, field_node, buf_sprintf("union field missing type"));2767 add_node_error(g, field_node, buf_sprintf("union field missing type"));
2438 union_type->data.unionation.resolve_status = ResolveStatusInvalid;2768 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2439 return ErrorSemanticAnalyzeFail;2769 return ErrorSemanticAnalyzeFail;
2440 }2770 }
2441 } else {2771 } else {
2442 field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);2772 ConstExprValue *field_type_val = analyze_const_value(g, scope,
2443 if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) {2773 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
2774 if (type_is_invalid(field_type_val->type)) {
2444 union_type->data.unionation.resolve_status = ResolveStatusInvalid;2775 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2445 return ErrorSemanticAnalyzeFail;2776 return ErrorSemanticAnalyzeFail;
2446 }2777 }
2778 assert(field_type_val->special != ConstValSpecialRuntime);
2779 union_field->type_val = field_type_val;
2447 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)2780 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
2448 return ErrorSemanticAnalyzeFail;2781 return ErrorSemanticAnalyzeFail;
2449 }
2450 union_field->type_entry = field_type;
24512782
2452 if (field_type->id == ZigTypeIdOpaque) {2783 bool field_is_opaque_type;
2453 add_node_error(g, field_node->data.struct_field.type,2784 if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
2454 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions"));2785 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2455 union_type->data.unionation.resolve_status = ResolveStatusInvalid;2786 return ErrorSemanticAnalyzeFail;
2456 return ErrorSemanticAnalyzeFail;2787 }
2457 }2788 if (field_is_opaque_type) {
2789 add_node_error(g, field_node->data.struct_field.type,
2790 buf_create_from_str(
2791 "opaque types have unknown size and therefore cannot be directly embedded in unions"));
2792 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2793 return ErrorSemanticAnalyzeFail;
2794 }
24582795
2459 switch (type_requires_comptime(g, field_type)) {2796 switch (type_val_resolve_requires_comptime(g, field_type_val)) {
2460 case ReqCompTimeInvalid:2797 case ReqCompTimeInvalid:
2798 if (g->trace_err != nullptr) {
2799 g->trace_err = add_error_note(g, g->trace_err, field_node,
2800 buf_create_from_str("while checking this field"));
2801 }
2802 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2803 return ErrorSemanticAnalyzeFail;
2804 case ReqCompTimeYes:
2805 union_type->data.unionation.requires_comptime = true;
2806 break;
2807 case ReqCompTimeNo:
2808 break;
2809 }
2810
2811 if ((err = type_val_resolve_zero_bits(g, field_type_val, union_type, nullptr, &field_is_zero_bits))) {
2461 union_type->data.unionation.resolve_status = ResolveStatusInvalid;2812 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2462 return ErrorSemanticAnalyzeFail;2813 return ErrorSemanticAnalyzeFail;
2463 case ReqCompTimeYes:2814 }
2464 union_type->data.unionation.requires_comptime = true;
2465 break;
2466 case ReqCompTimeNo:
2467 break;
2468 }2815 }
24692816
2470 if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {2817 if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {
2471 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,2818 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
2472 buf_sprintf("non-enum union field assignment"));2819 buf_create_from_str("untagged union field assignment"));
2473 add_error_note(g, msg, decl_node,2820 add_error_note(g, msg, decl_node, buf_create_from_str("consider 'union(enum)' here"));
2474 buf_sprintf("consider 'union(enum)' here"));
2475 }2821 }
24762822
2477 if (create_enum_type) {2823 if (create_enum_type) {
...@@ -2489,7 +2835,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2489,7 +2835,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2489 // In a second pass we will fill in the unspecified ones.2835 // In a second pass we will fill in the unspecified ones.
2490 if (tag_value != nullptr) {2836 if (tag_value != nullptr) {
2491 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;2837 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
2492 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);2838 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
2839 nullptr, UndefBad);
2493 if (type_is_invalid(result->type)) {2840 if (type_is_invalid(result->type)) {
2494 union_type->data.unionation.resolve_status = ResolveStatusInvalid;2841 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
2495 return ErrorSemanticAnalyzeFail;2842 return ErrorSemanticAnalyzeFail;
...@@ -2530,7 +2877,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2530,7 +2877,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2530 }2877 }
2531 assert(union_field->enum_field != nullptr);2878 assert(union_field->enum_field != nullptr);
25322879
2533 if (!type_has_bits(field_type))2880 if (field_is_zero_bits)
2534 continue;2881 continue;
25352882
2536 union_field->gen_index = gen_field_index;2883 union_field->gen_index = gen_field_index;
...@@ -2607,7 +2954,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2607,7 +2954,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2607 return ErrorSemanticAnalyzeFail;2954 return ErrorSemanticAnalyzeFail;
2608 }2955 }
26092956
2610 union_type->data.unionation.resolve_loop_flag = false;2957 union_type->data.unionation.resolve_loop_flag_zero_bits = false;
26112958
2612 union_type->data.unionation.gen_field_count = gen_field_index;2959 union_type->data.unionation.gen_field_count = gen_field_index;
2613 bool zero_bits = gen_field_index == 0 && (field_count < 2 || !src_have_tag);2960 bool zero_bits = gen_field_index == 0 && (field_count < 2 || !src_have_tag);
...@@ -2664,6 +3011,8 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) {...@@ -2664,6 +3011,8 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) {
2664 fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :3011 fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
2665 proto_node->data.fn_proto.fn_def_node->data.fn_def.body;3012 proto_node->data.fn_proto.fn_def_node->data.fn_def.body;
26663013
3014 fn_entry->analyzed_executable.source_node = fn_entry->body_node;
3015
2667 return fn_entry;3016 return fn_entry;
2668}3017}
26693018
...@@ -2690,7 +3039,7 @@ void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {...@@ -2690,7 +3039,7 @@ void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
2690 fake_decl->data.symbol_expr.symbol = tld_fn->base.name;3039 fake_decl->data.symbol_expr.symbol = tld_fn->base.name;
26913040
2692 // call this for the side effects of casting to panic_fn_type3041 // call this for the side effects of casting to panic_fn_type
2693 analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);3042 analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr, UndefBad);
2694}3043}
26953044
2696ZigType *get_test_fn_type(CodeGen *g) {3045ZigType *get_test_fn_type(CodeGen *g) {
...@@ -2836,7 +3185,8 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -2836,7 +3185,8 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
2836static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {3185static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {
2837 assert(tld_comptime->base.source_node->type == NodeTypeCompTime);3186 assert(tld_comptime->base.source_node->type == NodeTypeCompTime);
2838 AstNode *expr_node = tld_comptime->base.source_node->data.comptime_expr.expr;3187 AstNode *expr_node = tld_comptime->base.source_node->data.comptime_expr.expr;
2839 analyze_const_value(g, tld_comptime->base.parent_scope, expr_node, g->builtin_types.entry_void, nullptr);3188 analyze_const_value(g, tld_comptime->base.parent_scope, expr_node, g->builtin_types.entry_void,
3189 nullptr, UndefBad);
2840}3190}
28413191
2842static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {3192static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
...@@ -2931,7 +3281,7 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source...@@ -2931,7 +3281,7 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source
29313281
2932void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {3282void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
2933 Tld *tld = get_container_scope(g->compile_var_import)->decl_table.get(name);3283 Tld *tld = get_container_scope(g->compile_var_import)->decl_table.get(name);
2934 resolve_top_level_decl(g, tld, tld->source_node);3284 resolve_top_level_decl(g, tld, tld->source_node, false);
2935 assert(tld->id == TldIdVar);3285 assert(tld->id == TldIdVar);
2936 TldVar *tld_var = (TldVar *)tld;3286 TldVar *tld_var = (TldVar *)tld;
2937 tld_var->var->const_value = value;3287 tld_var->var->const_value = value;
...@@ -3173,7 +3523,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf...@@ -3173,7 +3523,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
3173 return variable_entry;3523 return variable_entry;
3174}3524}
31753525
3176static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {3526static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
3177 AstNode *source_node = tld_var->base.source_node;3527 AstNode *source_node = tld_var->base.source_node;
3178 AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration;3528 AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration;
31793529
...@@ -3185,9 +3535,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3185,9 +3535,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3185 ZigType *explicit_type = nullptr;3535 ZigType *explicit_type = nullptr;
3186 if (var_decl->type) {3536 if (var_decl->type) {
3187 if (tld_var->analyzing_type) {3537 if (tld_var->analyzing_type) {
3188 ErrorMsg *msg = add_node_error(g, var_decl->type,3538 add_node_error(g, var_decl->type,
3189 buf_sprintf("type of '%s' depends on itself", buf_ptr(tld_var->base.name)));3539 buf_sprintf("type of '%s' depends on itself", buf_ptr(tld_var->base.name)));
3190 emit_error_notes_for_ref_stack(g, msg);
3191 explicit_type = g->builtin_types.entry_invalid;3540 explicit_type = g->builtin_types.entry_invalid;
3192 } else {3541 } else {
3193 tld_var->analyzing_type = true;3542 tld_var->analyzing_type = true;
...@@ -3205,7 +3554,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3205,7 +3554,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3205 if (explicit_type && explicit_type->id == ZigTypeIdInvalid) {3554 if (explicit_type && explicit_type->id == ZigTypeIdInvalid) {
3206 implicit_type = explicit_type;3555 implicit_type = explicit_type;
3207 } else if (var_decl->expr) {3556 } else if (var_decl->expr) {
3208 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);3557 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type,
3558 var_decl->symbol, allow_lazy ? LazyOk : UndefOk);
3209 assert(init_value);3559 assert(init_value);
3210 implicit_type = init_value->type;3560 implicit_type = init_value->type;
32113561
...@@ -3360,7 +3710,8 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco...@@ -3360,7 +3710,8 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
3360 using_namespace->base.resolution = TldResolutionResolving;3710 using_namespace->base.resolution = TldResolutionResolving;
3361 assert(using_namespace->base.source_node->type == NodeTypeUsingNamespace);3711 assert(using_namespace->base.source_node->type == NodeTypeUsingNamespace);
3362 ConstExprValue *result = analyze_const_value(g, &dest_decls_scope->base,3712 ConstExprValue *result = analyze_const_value(g, &dest_decls_scope->base,
3363 using_namespace->base.source_node->data.using_namespace.expr, g->builtin_types.entry_type, nullptr);3713 using_namespace->base.source_node->data.using_namespace.expr, g->builtin_types.entry_type,
3714 nullptr, UndefBad);
3364 using_namespace->using_namespace_value = result;3715 using_namespace->using_namespace_value = result;
33653716
3366 if (type_is_invalid(result->type)) {3717 if (type_is_invalid(result->type)) {
...@@ -3380,51 +3731,61 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco...@@ -3380,51 +3731,61 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
3380 }3731 }
3381}3732}
33823733
3383void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) {3734void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy) {
3384 if (tld->resolution != TldResolutionUnresolved)3735 bool want_resolve_lazy = tld->resolution == TldResolutionOkLazy && !allow_lazy;
3736 if (tld->resolution != TldResolutionUnresolved && !want_resolve_lazy)
3385 return;3737 return;
33863738
3387 assert(tld->resolution != TldResolutionResolving);
3388 tld->resolution = TldResolutionResolving;3739 tld->resolution = TldResolutionResolving;
3389 g->tld_ref_source_node_stack.append(source_node);
33903740
3391 switch (tld->id) {3741 switch (tld->id) {
3392 case TldIdVar:3742 case TldIdVar: {
3393 {3743 TldVar *tld_var = (TldVar *)tld;
3394 TldVar *tld_var = (TldVar *)tld;3744 if (want_resolve_lazy) {
3395 resolve_decl_var(g, tld_var);3745 ir_resolve_lazy(g, source_node, tld_var->var->const_value);
3396 break;3746 } else {
3397 }3747 resolve_decl_var(g, tld_var, allow_lazy);
3398 case TldIdFn:
3399 {
3400 TldFn *tld_fn = (TldFn *)tld;
3401 resolve_decl_fn(g, tld_fn);
3402 break;
3403 }
3404 case TldIdContainer:
3405 {
3406 TldContainer *tld_container = (TldContainer *)tld;
3407 resolve_decl_container(g, tld_container);
3408 break;
3409 }
3410 case TldIdCompTime:
3411 {
3412 TldCompTime *tld_comptime = (TldCompTime *)tld;
3413 resolve_decl_comptime(g, tld_comptime);
3414 break;
3415 }3748 }
3749 tld->resolution = allow_lazy ? TldResolutionOkLazy : TldResolutionOk;
3750 break;
3751 }
3752 case TldIdFn: {
3753 TldFn *tld_fn = (TldFn *)tld;
3754 resolve_decl_fn(g, tld_fn);
3755
3756 tld->resolution = TldResolutionOk;
3757 break;
3758 }
3759 case TldIdContainer: {
3760 TldContainer *tld_container = (TldContainer *)tld;
3761 resolve_decl_container(g, tld_container);
3762
3763 tld->resolution = TldResolutionOk;
3764 break;
3765 }
3766 case TldIdCompTime: {
3767 TldCompTime *tld_comptime = (TldCompTime *)tld;
3768 resolve_decl_comptime(g, tld_comptime);
3769
3770 tld->resolution = TldResolutionOk;
3771 break;
3772 }
3416 case TldIdUsingNamespace: {3773 case TldIdUsingNamespace: {
3417 TldUsingNamespace *tld_using_namespace = (TldUsingNamespace *)tld;3774 TldUsingNamespace *tld_using_namespace = (TldUsingNamespace *)tld;
3418 assert(tld_using_namespace->base.parent_scope->id == ScopeIdDecls);3775 assert(tld_using_namespace->base.parent_scope->id == ScopeIdDecls);
3419 ScopeDecls *dest_decls_scope = (ScopeDecls *)tld_using_namespace->base.parent_scope;3776 ScopeDecls *dest_decls_scope = (ScopeDecls *)tld_using_namespace->base.parent_scope;
3420 preview_use_decl(g, tld_using_namespace, dest_decls_scope);3777 preview_use_decl(g, tld_using_namespace, dest_decls_scope);
3421 resolve_use_decl(g, tld_using_namespace, dest_decls_scope);3778 resolve_use_decl(g, tld_using_namespace, dest_decls_scope);
3779
3780 tld->resolution = TldResolutionOk;
3422 break;3781 break;
3423 }3782 }
3424 }3783 }
34253784
3426 tld->resolution = TldResolutionOk;3785 if (g->trace_err != nullptr && source_node != nullptr && !source_node->already_traced_this_node) {
3427 g->tld_ref_source_node_stack.pop();3786 g->trace_err = add_error_note(g, g->trace_err, source_node, buf_create_from_str("referenced here"));
3787 source_node->already_traced_this_node = true;
3788 }
3428}3789}
34293790
3430Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name) {3791Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name) {
...@@ -3550,7 +3911,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag)...@@ -3550,7 +3911,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag)
3550}3911}
35513912
3552TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag) {3913TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag) {
3553 assert(enum_type->data.enumeration.zero_bits_known);3914 assert(type_is_resolved(enum_type, ResolveStatusZeroBitsKnown));
3554 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {3915 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
3555 TypeEnumField *field = &enum_type->data.enumeration.fields[i];3916 TypeEnumField *field = &enum_type->data.enumeration.fields[i];
3556 if (bigint_cmp(&field->value, tag) == CmpEQ) {3917 if (bigint_cmp(&field->value, tag) == CmpEQ) {
...@@ -3619,43 +3980,6 @@ ZigType *container_ref_type(ZigType *type_entry) {...@@ -3619,43 +3980,6 @@ ZigType *container_ref_type(ZigType *type_entry) {
3619 type_entry->data.pointer.child_type : type_entry;3980 type_entry->data.pointer.child_type : type_entry;
3620}3981}
36213982
3622Error resolve_container_type(CodeGen *g, ZigType *type_entry) {
3623 switch (type_entry->id) {
3624 case ZigTypeIdStruct:
3625 return resolve_struct_type(g, type_entry);
3626 case ZigTypeIdEnum:
3627 return resolve_enum_zero_bits(g, type_entry);
3628 case ZigTypeIdUnion:
3629 return resolve_union_type(g, type_entry);
3630 case ZigTypeIdPointer:
3631 case ZigTypeIdMetaType:
3632 case ZigTypeIdVoid:
3633 case ZigTypeIdBool:
3634 case ZigTypeIdUnreachable:
3635 case ZigTypeIdInt:
3636 case ZigTypeIdFloat:
3637 case ZigTypeIdArray:
3638 case ZigTypeIdComptimeFloat:
3639 case ZigTypeIdComptimeInt:
3640 case ZigTypeIdEnumLiteral:
3641 case ZigTypeIdUndefined:
3642 case ZigTypeIdNull:
3643 case ZigTypeIdOptional:
3644 case ZigTypeIdErrorUnion:
3645 case ZigTypeIdErrorSet:
3646 case ZigTypeIdFn:
3647 case ZigTypeIdBoundFn:
3648 case ZigTypeIdInvalid:
3649 case ZigTypeIdArgTuple:
3650 case ZigTypeIdOpaque:
3651 case ZigTypeIdVector:
3652 case ZigTypeIdFnFrame:
3653 case ZigTypeIdAnyFrame:
3654 zig_unreachable();
3655 }
3656 zig_unreachable();
3657}
3658
3659ZigType *get_src_ptr_type(ZigType *type) {3983ZigType *get_src_ptr_type(ZigType *type) {
3660 if (type->id == ZigTypeIdPointer) return type;3984 if (type->id == ZigTypeIdPointer) return type;
3661 if (type->id == ZigTypeIdFn) return type;3985 if (type->id == ZigTypeIdFn) return type;
...@@ -3791,6 +4115,13 @@ static void resolve_async_fn_frame(CodeGen *g, ZigFn *fn) {...@@ -3791,6 +4115,13 @@ static void resolve_async_fn_frame(CodeGen *g, ZigFn *fn) {
3791 ZigType *frame_type = get_fn_frame_type(g, fn);4115 ZigType *frame_type = get_fn_frame_type(g, fn);
3792 Error err;4116 Error err;
3793 if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown))) {4117 if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown))) {
4118 if (g->trace_err != nullptr && frame_type->data.frame.resolve_loop_src_node != nullptr &&
4119 !frame_type->data.frame.reported_loop_err)
4120 {
4121 frame_type->data.frame.reported_loop_err = true;
4122 g->trace_err = add_error_note(g, g->trace_err, frame_type->data.frame.resolve_loop_src_node,
4123 buf_sprintf("when analyzing type '%s' here", buf_ptr(&frame_type->name)));
4124 }
3794 fn->anal_state = FnAnalStateInvalid;4125 fn->anal_state = FnAnalStateInvalid;
3795 return;4126 return;
3796 }4127 }
...@@ -3906,7 +4237,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {...@@ -3906,7 +4237,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
3906 &fn->analyzed_executable, fn_type_id->return_type, return_type_node);4237 &fn->analyzed_executable, fn_type_id->return_type, return_type_node);
3907 fn->src_implicit_return_type = block_return_type;4238 fn->src_implicit_return_type = block_return_type;
39084239
3909 if (type_is_invalid(block_return_type) || fn->analyzed_executable.invalid) {4240 if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) {
3910 assert(g->errors.length > 0);4241 assert(g->errors.length > 0);
3911 fn->anal_state = FnAnalStateInvalid;4242 fn->anal_state = FnAnalStateInvalid;
3912 return;4243 return;
...@@ -3990,7 +4321,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {...@@ -3990,7 +4321,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
3990 assert(!fn_type->data.fn.is_generic);4321 assert(!fn_type->data.fn.is_generic);
39914322
3992 ir_gen_fn(g, fn_table_entry);4323 ir_gen_fn(g, fn_table_entry);
3993 if (fn_table_entry->ir_executable.invalid) {4324 if (fn_table_entry->ir_executable.first_err_trace_msg != nullptr) {
3994 fn_table_entry->anal_state = FnAnalStateInvalid;4325 fn_table_entry->anal_state = FnAnalStateInvalid;
3995 return;4326 return;
3996 }4327 }
...@@ -4128,12 +4459,14 @@ void semantic_analyze(CodeGen *g) {...@@ -4128,12 +4459,14 @@ void semantic_analyze(CodeGen *g) {
4128 {4459 {
4129 for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) {4460 for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) {
4130 Tld *tld = g->resolve_queue.at(g->resolve_queue_index);4461 Tld *tld = g->resolve_queue.at(g->resolve_queue_index);
4462 g->trace_err = nullptr;
4131 AstNode *source_node = nullptr;4463 AstNode *source_node = nullptr;
4132 resolve_top_level_decl(g, tld, source_node);4464 resolve_top_level_decl(g, tld, source_node, false);
4133 }4465 }
41344466
4135 for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {4467 for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
4136 ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index);4468 ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index);
4469 g->trace_err = nullptr;
4137 analyze_fn_body(g, fn_entry);4470 analyze_fn_body(g, fn_entry);
4138 }4471 }
4139 }4472 }
...@@ -4145,6 +4478,7 @@ void semantic_analyze(CodeGen *g) {...@@ -4145,6 +4478,7 @@ void semantic_analyze(CodeGen *g) {
4145 // second pass over functions for detecting async4478 // second pass over functions for detecting async
4146 for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {4479 for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
4147 ZigFn *fn = g->fn_defs.at(g->fn_defs_index);4480 ZigFn *fn = g->fn_defs.at(g->fn_defs_index);
4481 g->trace_err = nullptr;
4148 analyze_fn_async(g, fn, true);4482 analyze_fn_async(g, fn, true);
4149 if (fn_is_async(fn) && fn->non_async_node != nullptr) {4483 if (fn_is_async(fn) && fn->non_async_node != nullptr) {
4150 ErrorMsg *msg = add_node_error(g, fn->proto_node,4484 ErrorMsg *msg = add_node_error(g, fn->proto_node,
...@@ -4790,7 +5124,10 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -4790,7 +5124,10 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
4790 case ZigTypeIdStruct:5124 case ZigTypeIdStruct:
4791 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {5125 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
4792 TypeStructField *field = &type_entry->data.structure.fields[i];5126 TypeStructField *field = &type_entry->data.structure.fields[i];
4793 switch (type_has_one_possible_value(g, field->type_entry)) {5127 OnePossibleValue opv = (field->type_entry != nullptr) ?
5128 type_has_one_possible_value(g, field->type_entry) :
5129 type_val_resolve_has_one_possible_value(g, field->type_val);
5130 switch (opv) {
4794 case OnePossibleValueInvalid:5131 case OnePossibleValueInvalid:
4795 return OnePossibleValueInvalid;5132 return OnePossibleValueInvalid;
4796 case OnePossibleValueNo:5133 case OnePossibleValueNo:
...@@ -4816,18 +5153,19 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -4816,18 +5153,19 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
4816 case ZigTypeIdUnion:5153 case ZigTypeIdUnion:
4817 if (type_entry->data.unionation.src_field_count > 1)5154 if (type_entry->data.unionation.src_field_count > 1)
4818 return OnePossibleValueNo;5155 return OnePossibleValueNo;
4819 return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry);5156 TypeUnionField *only_field = &type_entry->data.unionation.fields[0];
5157 if (only_field->type_entry != nullptr) {
5158 return type_has_one_possible_value(g, only_field->type_entry);
5159 }
5160 return type_val_resolve_has_one_possible_value(g, only_field->type_val);
4820 }5161 }
4821 zig_unreachable();5162 zig_unreachable();
4822}5163}
48235164
4824ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {5165ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
4825 Error err;5166 Error err;
4826 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))5167 switch (ty->id) {
4827 return ReqCompTimeInvalid;
4828 switch (type_entry->id) {
4829 case ZigTypeIdInvalid:5168 case ZigTypeIdInvalid:
4830 case ZigTypeIdOpaque:
4831 zig_unreachable();5169 zig_unreachable();
4832 case ZigTypeIdComptimeFloat:5170 case ZigTypeIdComptimeFloat:
4833 case ZigTypeIdComptimeInt:5171 case ZigTypeIdComptimeInt:
...@@ -4839,23 +5177,36 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {...@@ -4839,23 +5177,36 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
4839 case ZigTypeIdArgTuple:5177 case ZigTypeIdArgTuple:
4840 return ReqCompTimeYes;5178 return ReqCompTimeYes;
4841 case ZigTypeIdArray:5179 case ZigTypeIdArray:
4842 return type_requires_comptime(g, type_entry->data.array.child_type);5180 return type_requires_comptime(g, ty->data.array.child_type);
4843 case ZigTypeIdStruct:5181 case ZigTypeIdStruct:
4844 return type_entry->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;5182 if (ty->data.structure.resolve_loop_flag_zero_bits) {
5183 // Does a struct which contains a pointer field to itself require comptime? No.
5184 return ReqCompTimeNo;
5185 }
5186 if ((err = type_resolve(g, ty, ResolveStatusZeroBitsKnown)))
5187 return ReqCompTimeInvalid;
5188 return ty->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
4845 case ZigTypeIdUnion:5189 case ZigTypeIdUnion:
4846 return type_entry->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;5190 if (ty->data.unionation.resolve_loop_flag_zero_bits) {
5191 // Does a union which contains a pointer field to itself require comptime? No.
5192 return ReqCompTimeNo;
5193 }
5194 if ((err = type_resolve(g, ty, ResolveStatusZeroBitsKnown)))
5195 return ReqCompTimeInvalid;
5196 return ty->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
4847 case ZigTypeIdOptional:5197 case ZigTypeIdOptional:
4848 return type_requires_comptime(g, type_entry->data.maybe.child_type);5198 return type_requires_comptime(g, ty->data.maybe.child_type);
4849 case ZigTypeIdErrorUnion:5199 case ZigTypeIdErrorUnion:
4850 return type_requires_comptime(g, type_entry->data.error_union.payload_type);5200 return type_requires_comptime(g, ty->data.error_union.payload_type);
4851 case ZigTypeIdPointer:5201 case ZigTypeIdPointer:
4852 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {5202 if (ty->data.pointer.child_type->id == ZigTypeIdOpaque) {
4853 return ReqCompTimeNo;5203 return ReqCompTimeNo;
4854 } else {5204 } else {
4855 return type_requires_comptime(g, type_entry->data.pointer.child_type);5205 return type_requires_comptime(g, ty->data.pointer.child_type);
4856 }5206 }
4857 case ZigTypeIdFn:5207 case ZigTypeIdFn:
4858 return type_entry->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo;5208 return ty->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo;
5209 case ZigTypeIdOpaque:
4859 case ZigTypeIdEnum:5210 case ZigTypeIdEnum:
4860 case ZigTypeIdErrorSet:5211 case ZigTypeIdErrorSet:
4861 case ZigTypeIdBool:5212 case ZigTypeIdBool:
...@@ -5143,34 +5494,6 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_...@@ -5143,34 +5494,6 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
5143}5494}
51445495
51455496
5146void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
5147 Error err;
5148 ZigType *wanted_type = const_val->type;
5149 if (wanted_type->id == ZigTypeIdArray) {
5150 const_val->special = ConstValSpecialStatic;
5151 const_val->data.x_array.special = ConstArraySpecialUndef;
5152 } else if (wanted_type->id == ZigTypeIdStruct) {
5153 if ((err = ensure_complete_type(g, wanted_type))) {
5154 return;
5155 }
5156
5157 const_val->special = ConstValSpecialStatic;
5158 size_t field_count = wanted_type->data.structure.src_field_count;
5159 const_val->data.x_struct.fields = create_const_vals(field_count);
5160 for (size_t i = 0; i < field_count; i += 1) {
5161 ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
5162 field_val->type = wanted_type->data.structure.fields[i].type_entry;
5163 assert(field_val->type);
5164 init_const_undefined(g, field_val);
5165 field_val->parent.id = ConstParentIdStruct;
5166 field_val->parent.data.p_struct.struct_val = const_val;
5167 field_val->parent.data.p_struct.field_index = i;
5168 }
5169 } else {
5170 const_val->special = ConstValSpecialUndef;
5171 }
5172}
5173
5174ConstExprValue *create_const_vals(size_t count) {5497ConstExprValue *create_const_vals(size_t count) {
5175 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(count);5498 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(count);
5176 ConstExprValue *vals = allocate<ConstExprValue>(count);5499 ConstExprValue *vals = allocate<ConstExprValue>(count);
...@@ -5180,10 +5503,6 @@ ConstExprValue *create_const_vals(size_t count) {...@@ -5180,10 +5503,6 @@ ConstExprValue *create_const_vals(size_t count) {
5180 return vals;5503 return vals;
5181}5504}
51825505
5183Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {
5184 return type_resolve(g, type_entry, ResolveStatusSizeKnown);
5185}
5186
5187static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {5506static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
5188 if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync)5507 if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync)
5189 return orig_fn_type;5508 return orig_fn_type;
...@@ -5197,27 +5516,6 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {...@@ -5197,27 +5516,6 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
5197 return fn_type;5516 return fn_type;
5198}5517}
51995518
5200static void emit_error_notes_for_type_loop(CodeGen *g, ErrorMsg *msg, ZigType *stop_type,
5201 ZigType *ty, AstNode *src_node)
5202{
5203 ErrorMsg *note = add_error_note(g, msg, src_node,
5204 buf_sprintf("when analyzing type '%s' here", buf_ptr(&ty->name)));
5205 if (ty == stop_type)
5206 return;
5207 switch (ty->id) {
5208 case ZigTypeIdFnFrame: {
5209 ty->data.frame.reported_loop_err = true;
5210 ZigType *depending_type = ty->data.frame.resolve_loop_type;
5211 if (depending_type == nullptr)
5212 return;
5213 emit_error_notes_for_type_loop(g, note, stop_type,
5214 depending_type, ty->data.frame.resolve_loop_src_node);
5215 }
5216 default:
5217 return;
5218 }
5219}
5220
5221static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {5519static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5222 Error err;5520 Error err;
52235521
...@@ -5229,14 +5527,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5229,14 +5527,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
52295527
5230 if (frame_type->data.frame.resolve_loop_type != nullptr) {5528 if (frame_type->data.frame.resolve_loop_type != nullptr) {
5231 if (!frame_type->data.frame.reported_loop_err) {5529 if (!frame_type->data.frame.reported_loop_err) {
5232 frame_type->data.frame.reported_loop_err = true;5530 add_node_error(g, fn->proto_node,
5233 ErrorMsg *msg = add_node_error(g, fn->proto_node,
5234 buf_sprintf("'%s' depends on itself", buf_ptr(&frame_type->name)));5531 buf_sprintf("'%s' depends on itself", buf_ptr(&frame_type->name)));
5235 emit_error_notes_for_type_loop(g, msg,
5236 frame_type,
5237 frame_type->data.frame.resolve_loop_type,
5238 frame_type->data.frame.resolve_loop_src_node);
5239 emit_error_notes_for_ref_stack(g, msg);
5240 }5532 }
5241 return ErrorSemanticAnalyzeFail;5533 return ErrorSemanticAnalyzeFail;
5242 }5534 }
...@@ -5252,11 +5544,9 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5252,11 +5544,9 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5252 return ErrorSemanticAnalyzeFail;5544 return ErrorSemanticAnalyzeFail;
5253 break;5545 break;
5254 case FnAnalStateProbing: {5546 case FnAnalStateProbing: {
5255 ErrorMsg *msg = add_node_error(g, fn->proto_node,5547 add_node_error(g, fn->proto_node,
5256 buf_sprintf("cannot resolve '%s': function not fully analyzed yet",5548 buf_sprintf("cannot resolve '%s': function not fully analyzed yet",
5257 buf_ptr(&frame_type->name)));5549 buf_ptr(&frame_type->name)));
5258 ir_add_analysis_trace(fn->ir_executable.analysis, msg,
5259 buf_sprintf("depends on its own frame here"));
5260 return ErrorSemanticAnalyzeFail;5550 return ErrorSemanticAnalyzeFail;
5261 }5551 }
5262 }5552 }
...@@ -5327,10 +5617,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5327,10 +5617,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5327 if (callee->anal_state == FnAnalStateProbing) {5617 if (callee->anal_state == FnAnalStateProbing) {
5328 ErrorMsg *msg = add_node_error(g, fn->proto_node,5618 ErrorMsg *msg = add_node_error(g, fn->proto_node,
5329 buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name)));5619 buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name)));
5330 ErrorMsg *note = add_error_note(g, msg, call->base.source_node,5620 g->trace_err = add_error_note(g, msg, call->base.source_node,
5331 buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name)));5621 buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name)));
5332 ir_add_analysis_trace(callee->ir_executable.analysis, note,
5333 buf_sprintf("depends on the frame here"));
5334 return ErrorSemanticAnalyzeFail;5622 return ErrorSemanticAnalyzeFail;
5335 }5623 }
53365624
...@@ -5442,6 +5730,37 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5442,6 +5730,37 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5442 return ErrorNone;5730 return ErrorNone;
5443}5731}
54445732
5733static Error resolve_pointer_zero_bits(CodeGen *g, ZigType *ty) {
5734 Error err;
5735
5736 if (ty->abi_size != SIZE_MAX)
5737 return ErrorNone;
5738
5739 if (ty->data.pointer.resolve_loop_flag_zero_bits) {
5740 ty->abi_size = g->builtin_types.entry_usize->abi_size;
5741 ty->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
5742 ty->abi_align = g->builtin_types.entry_usize->abi_align;
5743 return ErrorNone;
5744 }
5745 ty->data.pointer.resolve_loop_flag_zero_bits = true;
5746
5747 ZigType *elem_type = ty->data.pointer.child_type;
5748
5749 if ((err = type_resolve(g, elem_type, ResolveStatusZeroBitsKnown)))
5750 return err;
5751
5752 if (type_has_bits(elem_type)) {
5753 ty->abi_size = g->builtin_types.entry_usize->abi_size;
5754 ty->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
5755 ty->abi_align = g->builtin_types.entry_usize->abi_align;
5756 } else {
5757 ty->abi_size = 0;
5758 ty->size_in_bits = 0;
5759 ty->abi_align = 0;
5760 }
5761 return ErrorNone;
5762}
5763
5445Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {5764Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
5446 if (type_is_invalid(ty))5765 if (type_is_invalid(ty))
5447 return ErrorSemanticAnalyzeFail;5766 return ErrorSemanticAnalyzeFail;
...@@ -5451,36 +5770,48 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {...@@ -5451,36 +5770,48 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
5451 case ResolveStatusInvalid:5770 case ResolveStatusInvalid:
5452 zig_unreachable();5771 zig_unreachable();
5453 case ResolveStatusZeroBitsKnown:5772 case ResolveStatusZeroBitsKnown:
5454 if (ty->id == ZigTypeIdStruct) {5773 switch (ty->id) {
5455 return resolve_struct_zero_bits(g, ty);5774 case ZigTypeIdStruct:
5456 } else if (ty->id == ZigTypeIdEnum) {5775 return resolve_struct_zero_bits(g, ty);
5457 return resolve_enum_zero_bits(g, ty);5776 case ZigTypeIdEnum:
5458 } else if (ty->id == ZigTypeIdUnion) {5777 return resolve_enum_zero_bits(g, ty);
5459 return resolve_union_zero_bits(g, ty);5778 case ZigTypeIdUnion:
5779 return resolve_union_zero_bits(g, ty);
5780 case ZigTypeIdPointer:
5781 return resolve_pointer_zero_bits(g, ty);
5782 default:
5783 return ErrorNone;
5460 }5784 }
5461 return ErrorNone;
5462 case ResolveStatusAlignmentKnown:5785 case ResolveStatusAlignmentKnown:
5463 if (ty->id == ZigTypeIdStruct) {5786 switch (ty->id) {
5464 return resolve_struct_alignment(g, ty);5787 case ZigTypeIdStruct:
5465 } else if (ty->id == ZigTypeIdEnum) {5788 return resolve_struct_alignment(g, ty);
5466 return resolve_enum_zero_bits(g, ty);5789 case ZigTypeIdEnum:
5467 } else if (ty->id == ZigTypeIdUnion) {5790 return resolve_enum_zero_bits(g, ty);
5468 return resolve_union_alignment(g, ty);5791 case ZigTypeIdUnion:
5469 } else if (ty->id == ZigTypeIdFnFrame) {5792 return resolve_union_alignment(g, ty);
5470 return resolve_async_frame(g, ty);5793 case ZigTypeIdFnFrame:
5794 return resolve_async_frame(g, ty);
5795 case ZigTypeIdPointer:
5796 return resolve_pointer_zero_bits(g, ty);
5797 default:
5798 return ErrorNone;
5471 }5799 }
5472 return ErrorNone;
5473 case ResolveStatusSizeKnown:5800 case ResolveStatusSizeKnown:
5474 if (ty->id == ZigTypeIdStruct) {5801 switch (ty->id) {
5475 return resolve_struct_type(g, ty);5802 case ZigTypeIdStruct:
5476 } else if (ty->id == ZigTypeIdEnum) {5803 return resolve_struct_type(g, ty);
5477 return resolve_enum_zero_bits(g, ty);5804 case ZigTypeIdEnum:
5478 } else if (ty->id == ZigTypeIdUnion) {5805 return resolve_enum_zero_bits(g, ty);
5479 return resolve_union_type(g, ty);5806 case ZigTypeIdUnion:
5480 } else if (ty->id == ZigTypeIdFnFrame) {5807 return resolve_union_type(g, ty);
5481 return resolve_async_frame(g, ty);5808 case ZigTypeIdFnFrame:
5809 return resolve_async_frame(g, ty);
5810 case ZigTypeIdPointer:
5811 return resolve_pointer_zero_bits(g, ty);
5812 default:
5813 return ErrorNone;
5482 }5814 }
5483 return ErrorNone;
5484 case ResolveStatusLLVMFwdDecl:5815 case ResolveStatusLLVMFwdDecl:
5485 case ResolveStatusLLVMFull:5816 case ResolveStatusLLVMFull:
5486 resolve_llvm_types(g, ty, status);5817 resolve_llvm_types(g, ty, status);
...@@ -5855,6 +6186,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5855,6 +6186,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5855 case ConstValSpecialRuntime:6186 case ConstValSpecialRuntime:
5856 buf_appendf(buf, "(runtime value)");6187 buf_appendf(buf, "(runtime value)");
5857 return;6188 return;
6189 case ConstValSpecialLazy:
6190 buf_appendf(buf, "(lazy value)");
6191 return;
5858 case ConstValSpecialUndef:6192 case ConstValSpecialUndef:
5859 buf_appendf(buf, "undefined");6193 buf_appendf(buf, "undefined");
5860 return;6194 return;
...@@ -5976,7 +6310,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5976,7 +6310,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5976 {6310 {
5977 if (is_slice(type_entry)) {6311 if (is_slice(type_entry)) {
5978 ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index];6312 ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index];
5979 size_t len = bigint_as_unsigned(&len_val->data.x_bigint);6313 size_t len = bigint_as_usize(&len_val->data.x_bigint);
59806314
5981 ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index];6315 ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index];
5982 if (ptr_val->special == ConstValSpecialUndef) {6316 if (ptr_val->special == ConstValSpecialUndef) {
...@@ -6051,12 +6385,12 @@ ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {...@@ -6051,12 +6385,12 @@ ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
6051 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type);6385 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type);
6052 entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type);6386 entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type);
60536387
6054 if (size_in_bits >= 128) {6388 if (size_in_bits >= 128 && entry->abi_align < 16) {
6055 // Override the incorrect alignment reported by LLVM. Clang does this as well.6389 // Override the incorrect alignment reported by LLVM. Clang does this as well.
6056 // On x86_64 there are some instructions like CMPXCHG16B which require this.6390 // On x86_64 there are some instructions like CMPXCHG16B which require this.
6057 // On all targets, integers 128 bits and above have ABI alignment of 16.6391 // On all targets, integers 128 bits and above have ABI alignment of 16.
6392 // However for some targets, LLVM incorrectly reports this as 8.
6058 // See: https://github.com/ziglang/zig/issues/29876393 // See: https://github.com/ziglang/zig/issues/2987
6059 assert(entry->abi_align == 8); // if this trips we can remove the workaround
6060 entry->abi_align = 16;6394 entry->abi_align = 16;
6061 }6395 }
6062 }6396 }
...@@ -6229,6 +6563,40 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {...@@ -6229,6 +6563,40 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
6229 zig_unreachable();6563 zig_unreachable();
6230}6564}
62316565
6566static void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
6567 Error err;
6568 ZigType *wanted_type = const_val->type;
6569 if (wanted_type->id == ZigTypeIdArray) {
6570 const_val->special = ConstValSpecialStatic;
6571 const_val->data.x_array.special = ConstArraySpecialUndef;
6572 } else if (wanted_type->id == ZigTypeIdStruct) {
6573 if ((err = type_resolve(g, wanted_type, ResolveStatusZeroBitsKnown))) {
6574 return;
6575 }
6576
6577 const_val->special = ConstValSpecialStatic;
6578 size_t field_count = wanted_type->data.structure.src_field_count;
6579 const_val->data.x_struct.fields = create_const_vals(field_count);
6580 for (size_t i = 0; i < field_count; i += 1) {
6581 ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
6582 field_val->type = wanted_type->data.structure.fields[i].type_entry;
6583 assert(field_val->type);
6584 init_const_undefined(g, field_val);
6585 field_val->parent.id = ConstParentIdStruct;
6586 field_val->parent.data.p_struct.struct_val = const_val;
6587 field_val->parent.data.p_struct.field_index = i;
6588 }
6589 } else {
6590 const_val->special = ConstValSpecialUndef;
6591 }
6592}
6593
6594void expand_undef_struct(CodeGen *g, ConstExprValue *const_val) {
6595 if (const_val->special == ConstValSpecialUndef) {
6596 init_const_undefined(g, const_val);
6597 }
6598}
6599
6232// Canonicalize the array value as ConstArraySpecialNone6600// Canonicalize the array value as ConstArraySpecialNone
6233void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {6601void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6234 size_t elem_count;6602 size_t elem_count;
...@@ -6492,7 +6860,7 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b) {...@@ -6492,7 +6860,7 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b) {
64926860
6493ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {6861ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
6494 Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name));6862 Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name));
6495 resolve_top_level_decl(codegen, tld, nullptr);6863 resolve_top_level_decl(codegen, tld, nullptr, false);
6496 assert(tld->id == TldIdVar);6864 assert(tld->id == TldIdVar);
6497 TldVar *tld_var = (TldVar *)tld;6865 TldVar *tld_var = (TldVar *)tld;
6498 ConstExprValue *var_value = tld_var->var->const_value;6866 ConstExprValue *var_value = tld_var->var->const_value;
...@@ -6707,19 +7075,6 @@ bool ptr_allows_addr_zero(ZigType *ptr_type) {...@@ -6707,19 +7075,6 @@ bool ptr_allows_addr_zero(ZigType *ptr_type) {
6707 return false;7075 return false;
6708}7076}
67097077
6710void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg) {
6711 size_t i = g->tld_ref_source_node_stack.length;
6712 for (;;) {
6713 if (i == 0)
6714 break;
6715 i -= 1;
6716 AstNode *source_node = g->tld_ref_source_node_stack.at(i);
6717 if (source_node) {
6718 msg = add_error_note(g, msg, source_node, buf_sprintf("referenced here"));
6719 }
6720 }
6721}
6722
6723Buf *type_bare_name(ZigType *type_entry) {7078Buf *type_bare_name(ZigType *type_entry) {
6724 if (is_slice(type_entry)) {7079 if (is_slice(type_entry)) {
6725 return &type_entry->name;7080 return &type_entry->name;
...@@ -7122,10 +7477,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -7122,10 +7477,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
7122 struct_type->data.structure.resolve_status = ResolveStatusLLVMFull;7477 struct_type->data.structure.resolve_status = ResolveStatusLLVMFull;
7123}7478}
71247479
7125static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {7480static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatus wanted_resolve_status) {
7126 assert(!enum_type->data.enumeration.is_invalid);7481 assert(enum_type->data.enumeration.resolve_status >= ResolveStatusSizeKnown);
7127 assert(enum_type->data.enumeration.complete);7482 if (enum_type->data.enumeration.resolve_status >= wanted_resolve_status) return;
7128 if (enum_type->llvm_di_type != nullptr) return;
71297483
7130 Scope *scope = &enum_type->data.enumeration.decls_scope->base;7484 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
7131 ZigType *import = get_scope_import(scope);7485 ZigType *import = get_scope_import(scope);
...@@ -7146,6 +7500,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {...@@ -7146,6 +7500,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {
7146 debug_align_in_bits,7500 debug_align_in_bits,
7147 ZigLLVM_DIFlags_Zero,7501 ZigLLVM_DIFlags_Zero,
7148 nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");7502 nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");
7503 enum_type->data.enumeration.resolve_status = ResolveStatusLLVMFull;
7149 return;7504 return;
7150 }7505 }
71517506
...@@ -7178,14 +7533,16 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {...@@ -7178,14 +7533,16 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {
7178 get_llvm_di_type(g, tag_int_type), "");7533 get_llvm_di_type(g, tag_int_type), "");
71797534
7180 enum_type->llvm_di_type = tag_di_type;7535 enum_type->llvm_di_type = tag_di_type;
7536 enum_type->data.enumeration.resolve_status = ResolveStatusLLVMFull;
7181}7537}
71827538
7183static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) {7539static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) {
7184 if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return;7540 if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return;
71857541
7186 ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;7542 TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
7187 ZigType *tag_type = union_type->data.unionation.tag_type;7543 ZigType *tag_type = union_type->data.unionation.tag_type;
7188 if (most_aligned_union_member == nullptr) {7544 uint32_t gen_field_count = union_type->data.unionation.gen_field_count;
7545 if (gen_field_count == 0) {
7189 union_type->llvm_type = get_llvm_type(g, tag_type);7546 union_type->llvm_type = get_llvm_type(g, tag_type);
7190 union_type->llvm_di_type = get_llvm_di_type(g, tag_type);7547 union_type->llvm_di_type = get_llvm_di_type(g, tag_type);
7191 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;7548 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
...@@ -7209,7 +7566,6 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -7209,7 +7566,6 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
7209 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;7566 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;
7210 }7567 }
72117568
7212 uint32_t gen_field_count = union_type->data.unionation.gen_field_count;
7213 ZigLLVMDIType **union_inner_di_types = allocate<ZigLLVMDIType*>(gen_field_count);7569 ZigLLVMDIType **union_inner_di_types = allocate<ZigLLVMDIType*>(gen_field_count);
7214 uint32_t field_count = union_type->data.unionation.src_field_count;7570 uint32_t field_count = union_type->data.unionation.src_field_count;
7215 for (uint32_t i = 0; i < field_count; i += 1) {7571 for (uint32_t i = 0; i < field_count; i += 1) {
...@@ -7236,17 +7592,17 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -7236,17 +7592,17 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
7236 if (tag_type == nullptr || !type_has_bits(tag_type)) {7592 if (tag_type == nullptr || !type_has_bits(tag_type)) {
7237 assert(most_aligned_union_member != nullptr);7593 assert(most_aligned_union_member != nullptr);
72387594
7239 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->abi_size;7595 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
7240 if (padding_bytes > 0) {7596 if (padding_bytes > 0) {
7241 ZigType *u8_type = get_int_type(g, false, 8);7597 ZigType *u8_type = get_int_type(g, false, 8);
7242 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);7598 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
7243 LLVMTypeRef union_element_types[] = {7599 LLVMTypeRef union_element_types[] = {
7244 most_aligned_union_member->llvm_type,7600 most_aligned_union_member->type_entry->llvm_type,
7245 get_llvm_type(g, padding_array),7601 get_llvm_type(g, padding_array),
7246 };7602 };
7247 LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, false);7603 LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, false);
7248 } else {7604 } else {
7249 LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->llvm_type, 1, false);7605 LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->type_entry->llvm_type, 1, false);
7250 }7606 }
7251 union_type->data.unionation.union_llvm_type = union_type->llvm_type;7607 union_type->data.unionation.union_llvm_type = union_type->llvm_type;
7252 union_type->data.unionation.gen_tag_index = SIZE_MAX;7608 union_type->data.unionation.gen_tag_index = SIZE_MAX;
...@@ -7257,7 +7613,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -7257,7 +7613,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
7257 ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name),7613 ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name),
7258 import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),7614 import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
7259 union_type->data.unionation.union_abi_size * 8,7615 union_type->data.unionation.union_abi_size * 8,
7260 most_aligned_union_member->abi_align * 8,7616 most_aligned_union_member->align * 8,
7261 ZigLLVM_DIFlags_Zero, union_inner_di_types,7617 ZigLLVM_DIFlags_Zero, union_inner_di_types,
7262 gen_field_count, 0, "");7618 gen_field_count, 0, "");
72637619
...@@ -7268,14 +7624,14 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -7268,14 +7624,14 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
7268 }7624 }
72697625
7270 LLVMTypeRef union_type_ref;7626 LLVMTypeRef union_type_ref;
7271 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->abi_size;7627 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
7272 if (padding_bytes == 0) {7628 if (padding_bytes == 0) {
7273 union_type_ref = get_llvm_type(g, most_aligned_union_member);7629 union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);
7274 } else {7630 } else {
7275 ZigType *u8_type = get_int_type(g, false, 8);7631 ZigType *u8_type = get_int_type(g, false, 8);
7276 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);7632 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
7277 LLVMTypeRef union_element_types[] = {7633 LLVMTypeRef union_element_types[] = {
7278 get_llvm_type(g, most_aligned_union_member),7634 get_llvm_type(g, most_aligned_union_member->type_entry),
7279 get_llvm_type(g, padding_array),7635 get_llvm_type(g, padding_array),
7280 };7636 };
7281 union_type_ref = LLVMStructType(union_element_types, 2, false);7637 union_type_ref = LLVMStructType(union_element_types, 2, false);
...@@ -7291,7 +7647,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -7291,7 +7647,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
7291 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,7647 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
7292 ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion",7648 ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion",
7293 import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),7649 import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
7294 most_aligned_union_member->size_in_bits, 8*most_aligned_union_member->abi_align,7650 most_aligned_union_member->type_entry->size_in_bits, 8*most_aligned_union_member->align,
7295 ZigLLVM_DIFlags_Zero, union_inner_di_types, gen_field_count, 0, "");7651 ZigLLVM_DIFlags_Zero, union_inner_di_types, gen_field_count, 0, "");
72967652
7297 uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->llvm_type,7653 uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->llvm_type,
...@@ -7302,8 +7658,8 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -7302,8 +7658,8 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
7302 ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,7658 ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
7303 ZigLLVMTypeToScope(union_type->llvm_di_type), "payload",7659 ZigLLVMTypeToScope(union_type->llvm_di_type), "payload",
7304 import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),7660 import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
7305 most_aligned_union_member->size_in_bits,7661 most_aligned_union_member->type_entry->size_in_bits,
7306 8*most_aligned_union_member->abi_align,7662 8*most_aligned_union_member->align,
7307 union_offset_in_bits,7663 union_offset_in_bits,
7308 ZigLLVM_DIFlags_Zero, union_di_type);7664 ZigLLVM_DIFlags_Zero, union_di_type);
73097665
...@@ -7340,6 +7696,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -7340,6 +7696,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
7340static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {7696static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
7341 if (type->llvm_di_type != nullptr) return;7697 if (type->llvm_di_type != nullptr) return;
73427698
7699 if (resolve_pointer_zero_bits(g, type) != ErrorNone)
7700 zig_unreachable();
7701
7343 if (!type_has_bits(type)) {7702 if (!type_has_bits(type)) {
7344 type->llvm_type = g->builtin_types.entry_void->llvm_type;7703 type->llvm_type = g->builtin_types.entry_void->llvm_type;
7345 type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;7704 type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
...@@ -7406,8 +7765,11 @@ static void resolve_llvm_types_integer(CodeGen *g, ZigType *type) {...@@ -7406,8 +7765,11 @@ static void resolve_llvm_types_integer(CodeGen *g, ZigType *type) {
7406 type->llvm_type = LLVMIntType(type->size_in_bits);7765 type->llvm_type = LLVMIntType(type->size_in_bits);
7407}7766}
74087767
7409static void resolve_llvm_types_optional(CodeGen *g, ZigType *type) {7768static void resolve_llvm_types_optional(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
7410 if (type->llvm_di_type != nullptr) return;7769 assert(type->id == ZigTypeIdOptional);
7770 assert(type->data.maybe.resolve_status != ResolveStatusInvalid);
7771 assert(type->data.maybe.resolve_status >= ResolveStatusSizeKnown);
7772 if (type->data.maybe.resolve_status >= wanted_resolve_status) return;
74117773
7412 LLVMTypeRef bool_llvm_type = get_llvm_type(g, g->builtin_types.entry_bool);7774 LLVMTypeRef bool_llvm_type = get_llvm_type(g, g->builtin_types.entry_bool);
7413 ZigLLVMDIType *bool_llvm_di_type = get_llvm_di_type(g, g->builtin_types.entry_bool);7775 ZigLLVMDIType *bool_llvm_di_type = get_llvm_di_type(g, g->builtin_types.entry_bool);
...@@ -7416,30 +7778,41 @@ static void resolve_llvm_types_optional(CodeGen *g, ZigType *type) {...@@ -7416,30 +7778,41 @@ static void resolve_llvm_types_optional(CodeGen *g, ZigType *type) {
7416 if (!type_has_bits(child_type)) {7778 if (!type_has_bits(child_type)) {
7417 type->llvm_type = bool_llvm_type;7779 type->llvm_type = bool_llvm_type;
7418 type->llvm_di_type = bool_llvm_di_type;7780 type->llvm_di_type = bool_llvm_di_type;
7781 type->data.maybe.resolve_status = ResolveStatusLLVMFull;
7419 return;7782 return;
7420 }7783 }
74217784
7422 LLVMTypeRef child_llvm_type = get_llvm_type(g, child_type);
7423 ZigLLVMDIType *child_llvm_di_type = get_llvm_di_type(g, child_type);
7424
7425 if (type_is_nonnull_ptr(child_type) || child_type->id == ZigTypeIdErrorSet) {7785 if (type_is_nonnull_ptr(child_type) || child_type->id == ZigTypeIdErrorSet) {
7426 type->llvm_type = child_llvm_type;7786 type->llvm_type = get_llvm_type(g, child_type);
7427 type->llvm_di_type = child_llvm_di_type;7787 type->llvm_di_type = get_llvm_di_type(g, child_type);
7788 type->data.maybe.resolve_status = ResolveStatusLLVMFull;
7428 return;7789 return;
7429 }7790 }
74307791
7792 ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
7793 ZigLLVMDIFile *di_file = nullptr;
7794 unsigned line = 0;
7795
7796 if (type->data.maybe.resolve_status < ResolveStatusLLVMFwdDecl) {
7797 type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&type->name));
7798 unsigned dwarf_kind = ZigLLVMTag_DW_structure_type();
7799 type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
7800 dwarf_kind, buf_ptr(&type->name),
7801 compile_unit_scope, di_file, line);
7802
7803 type->data.maybe.resolve_status = ResolveStatusLLVMFwdDecl;
7804 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;
7805 }
7806
7807 LLVMTypeRef child_llvm_type = get_llvm_type(g, child_type);
7808 ZigLLVMDIType *child_llvm_di_type = get_llvm_di_type(g, child_type);
7809 if (type->data.maybe.resolve_status >= wanted_resolve_status) return;
7810
7431 LLVMTypeRef elem_types[] = {7811 LLVMTypeRef elem_types[] = {
7432 get_llvm_type(g, child_type),7812 get_llvm_type(g, child_type),
7433 LLVMInt1Type(),7813 LLVMInt1Type(),
7434 };7814 };
7435 type->llvm_type = LLVMStructType(elem_types, 2, false);7815 LLVMStructSetBody(type->llvm_type, elem_types, 2, false);
7436
7437 ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
7438 ZigLLVMDIFile *di_file = nullptr;
7439 unsigned line = 0;
7440 type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
7441 ZigLLVMTag_DW_structure_type(), buf_ptr(&type->name),
7442 compile_unit_scope, di_file, line);
74437816
7444 uint64_t val_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, child_llvm_type);7817 uint64_t val_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, child_llvm_type);
7445 uint64_t val_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, child_llvm_type);7818 uint64_t val_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, child_llvm_type);
...@@ -7474,6 +7847,7 @@ static void resolve_llvm_types_optional(CodeGen *g, ZigType *type) {...@@ -7474,6 +7847,7 @@ static void resolve_llvm_types_optional(CodeGen *g, ZigType *type) {
74747847
7475 ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);7848 ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
7476 type->llvm_di_type = replacement_di_type;7849 type->llvm_di_type = replacement_di_type;
7850 type->data.maybe.resolve_status = ResolveStatusLLVMFull;
7477}7851}
74787852
7479static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) {7853static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) {
...@@ -7909,7 +8283,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r...@@ -7909,7 +8283,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
7909 else8283 else
7910 return resolve_llvm_types_struct(g, type, wanted_resolve_status, nullptr);8284 return resolve_llvm_types_struct(g, type, wanted_resolve_status, nullptr);
7911 case ZigTypeIdEnum:8285 case ZigTypeIdEnum:
7912 return resolve_llvm_types_enum(g, type);8286 return resolve_llvm_types_enum(g, type, wanted_resolve_status);
7913 case ZigTypeIdUnion:8287 case ZigTypeIdUnion:
7914 return resolve_llvm_types_union(g, type, wanted_resolve_status);8288 return resolve_llvm_types_union(g, type, wanted_resolve_status);
7915 case ZigTypeIdPointer:8289 case ZigTypeIdPointer:
...@@ -7917,7 +8291,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r...@@ -7917,7 +8291,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
7917 case ZigTypeIdInt:8291 case ZigTypeIdInt:
7918 return resolve_llvm_types_integer(g, type);8292 return resolve_llvm_types_integer(g, type);
7919 case ZigTypeIdOptional:8293 case ZigTypeIdOptional:
7920 return resolve_llvm_types_optional(g, type);8294 return resolve_llvm_types_optional(g, type, wanted_resolve_status);
7921 case ZigTypeIdErrorUnion:8295 case ZigTypeIdErrorUnion:
7922 return resolve_llvm_types_error_union(g, type);8296 return resolve_llvm_types_error_union(g, type);
7923 case ZigTypeIdArray:8297 case ZigTypeIdArray:
src/analyze.hpp+9-8
...@@ -11,10 +11,9 @@...@@ -11,10 +11,9 @@
11#include "all_types.hpp"11#include "all_types.hpp"
1212
13void semantic_analyze(CodeGen *g);13void semantic_analyze(CodeGen *g);
14ErrorMsg *add_node_error(CodeGen *g, const AstNode *node, Buf *msg);14ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
15ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg);15ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg);
16ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg);16ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg);
17void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg);
18ZigType *new_type_table_entry(ZigTypeId id);17ZigType *new_type_table_entry(ZigTypeId id);
19ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn);18ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn);
20ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);19ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
...@@ -59,7 +58,7 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Bu...@@ -59,7 +58,7 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Bu
59ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope);58ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope);
60Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);59Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
61Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name);60Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name);
62void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node);61void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy);
6362
64ZigType *get_src_ptr_type(ZigType *type);63ZigType *get_src_ptr_type(ZigType *type);
65ZigType *get_codegen_ptr_type(ZigType *type);64ZigType *get_codegen_ptr_type(ZigType *type);
...@@ -71,7 +70,6 @@ bool type_is_complete(ZigType *type_entry);...@@ -71,7 +70,6 @@ bool type_is_complete(ZigType *type_entry);
71bool type_is_resolved(ZigType *type_entry, ResolveStatus status);70bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
72bool type_is_invalid(ZigType *type_entry);71bool type_is_invalid(ZigType *type_entry);
73bool type_is_global_error_set(ZigType *err_set_type);72bool type_is_global_error_set(ZigType *err_set_type);
74Error resolve_container_type(CodeGen *g, ZigType *type_entry);
75ScopeDecls *get_container_scope(ZigType *type_entry);73ScopeDecls *get_container_scope(ZigType *type_entry);
76TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);74TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
77TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name);75TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name);
...@@ -95,7 +93,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node);...@@ -95,7 +93,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
95ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);93ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
96void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);94void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
97AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);95AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
98Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
99Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);96Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
100void complete_enum(CodeGen *g, ZigType *enum_type);97void complete_enum(CodeGen *g, ZigType *enum_type);
101bool ir_get_var_is_comptime(ZigVar *var);98bool ir_get_var_is_comptime(ZigVar *var);
...@@ -169,12 +166,11 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t...@@ -169,12 +166,11 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
169void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end);166void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end);
170ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end);167ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end);
171168
172void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
173
174ConstExprValue *create_const_vals(size_t count);169ConstExprValue *create_const_vals(size_t count);
175170
176ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);171ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
177void expand_undef_array(CodeGen *g, ConstExprValue *const_val);172void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
173void expand_undef_struct(CodeGen *g, ConstExprValue *const_val);
178void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);174void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
179175
180const char *type_id_name(ZigTypeId id);176const char *type_id_name(ZigTypeId id);
...@@ -244,9 +240,14 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa...@@ -244,9 +240,14 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
244240
245void src_assert(bool ok, AstNode *source_node);241void src_assert(bool ok, AstNode *source_node);
246bool is_container(ZigType *type_entry);242bool is_container(ZigType *type_entry);
247ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);243ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
244 Buf *type_name, UndefAllowed undef);
248245
249void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);246void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
250bool fn_is_async(ZigFn *fn);247bool fn_is_async(ZigFn *fn);
251248
249Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t *abi_align);
250ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field);
251ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);
252
252#endif253#endif
src/bigint.cpp+22-1
...@@ -15,6 +15,8 @@...@@ -15,6 +15,8 @@
15#include <limits>15#include <limits>
16#include <algorithm>16#include <algorithm>
1717
18static uint64_t bigint_as_unsigned(const BigInt *bigint);
19
18static void bigint_normalize(BigInt *dest) {20static void bigint_normalize(BigInt *dest) {
19 const uint64_t *digits = bigint_ptr(dest);21 const uint64_t *digits = bigint_ptr(dest);
2022
...@@ -1660,7 +1662,7 @@ size_t bigint_clz(const BigInt *bi, size_t bit_count) {...@@ -1660,7 +1662,7 @@ size_t bigint_clz(const BigInt *bi, size_t bit_count) {
1660 return count;1662 return count;
1661}1663}
16621664
1663uint64_t bigint_as_unsigned(const BigInt *bigint) {1665static uint64_t bigint_as_unsigned(const BigInt *bigint) {
1664 assert(!bigint->is_negative);1666 assert(!bigint->is_negative);
1665 if (bigint->digit_count == 0) {1667 if (bigint->digit_count == 0) {
1666 return 0;1668 return 0;
...@@ -1671,6 +1673,25 @@ uint64_t bigint_as_unsigned(const BigInt *bigint) {...@@ -1671,6 +1673,25 @@ uint64_t bigint_as_unsigned(const BigInt *bigint) {
1671 }1673 }
1672}1674}
16731675
1676uint64_t bigint_as_u64(const BigInt *bigint)
1677{
1678 return bigint_as_unsigned(bigint);
1679}
1680
1681uint32_t bigint_as_u32(const BigInt *bigint) {
1682 uint64_t value64 = bigint_as_unsigned(bigint);
1683 uint32_t value32 = (uint32_t)value64;
1684 assert (value64 == value32);
1685 return value32;
1686}
1687
1688size_t bigint_as_usize(const BigInt *bigint) {
1689 uint64_t value64 = bigint_as_unsigned(bigint);
1690 size_t valueUsize = (size_t)value64;
1691 assert (value64 == valueUsize);
1692 return valueUsize;
1693}
1694
1674int64_t bigint_as_signed(const BigInt *bigint) {1695int64_t bigint_as_signed(const BigInt *bigint) {
1675 if (bigint->digit_count == 0) {1696 if (bigint->digit_count == 0) {
1676 return 0;1697 return 0;
src/bigint.hpp+4-1
...@@ -36,7 +36,10 @@ void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);...@@ -36,7 +36,10 @@ void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);
36void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative);36void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative);
3737
38// panics if number won't fit38// panics if number won't fit
39uint64_t bigint_as_unsigned(const BigInt *bigint);39uint64_t bigint_as_u64(const BigInt *bigint);
40uint32_t bigint_as_u32(const BigInt *bigint);
41size_t bigint_as_usize(const BigInt *bigint);
42
40int64_t bigint_as_signed(const BigInt *bigint);43int64_t bigint_as_signed(const BigInt *bigint);
4144
42static inline const uint64_t *bigint_ptr(const BigInt *bigint) {45static inline const uint64_t *bigint_ptr(const BigInt *bigint) {
src/codegen.cpp+28-13
...@@ -2872,7 +2872,7 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in...@@ -2872,7 +2872,7 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in
2872 eval_min_max_value_int(g, int_type, &biggest_possible_err_val, true);2872 eval_min_max_value_int(g, int_type, &biggest_possible_err_val, true);
28732873
2874 if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) &&2874 if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) &&
2875 bigint_as_unsigned(&biggest_possible_err_val) < g->errors_by_index.length)2875 bigint_as_usize(&biggest_possible_err_val) < g->errors_by_index.length)
2876 {2876 {
2877 ok_bit = neq_zero_bit;2877 ok_bit = neq_zero_bit;
2878 } else {2878 } else {
...@@ -3052,8 +3052,10 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex...@@ -3052,8 +3052,10 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex
3052 IrInstructionPtrOfArrayToSlice *instruction)3052 IrInstructionPtrOfArrayToSlice *instruction)
3053{3053{
3054 ZigType *actual_type = instruction->operand->value.type;3054 ZigType *actual_type = instruction->operand->value.type;
3055 LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);3055 ZigType *slice_type = instruction->base.value.type;
3056 assert(expr_val);3056 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry;
3057 size_t ptr_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
3058 size_t len_index = slice_type->data.structure.fields[slice_len_index].gen_index;
30573059
3058 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);3060 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
30593061
...@@ -3061,15 +3063,21 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex...@@ -3061,15 +3063,21 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex
3061 ZigType *array_type = actual_type->data.pointer.child_type;3063 ZigType *array_type = actual_type->data.pointer.child_type;
3062 assert(array_type->id == ZigTypeIdArray);3064 assert(array_type->id == ZigTypeIdArray);
30633065
3064 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_ptr_index, "");3066 if (type_has_bits(actual_type)) {
3065 LLVMValueRef indices[] = {3067 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, "");
3066 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),3068 LLVMValueRef indices[] = {
3067 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),3069 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
3068 };3070 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
3069 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");3071 };
3070 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);3072 LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
3073 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");
3074 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
3075 } else if (ir_want_runtime_safety(g, &instruction->base)) {
3076 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, "");
3077 gen_undef_init(g, slice_ptr_type->abi_align, slice_ptr_type, ptr_field_ptr);
3078 }
30713079
3072 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_len_index, "");3080 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, len_index, "");
3073 LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,3081 LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
3074 array_type->data.array.len, false);3082 array_type->data.array.len, false);
3075 gen_store_untyped(g, len_value, len_field_ptr, 0, false);3083 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
...@@ -3386,6 +3394,8 @@ static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {...@@ -3386,6 +3394,8 @@ static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
33863394
3387static bool value_is_all_undef(ConstExprValue *const_val) {3395static bool value_is_all_undef(ConstExprValue *const_val) {
3388 switch (const_val->special) {3396 switch (const_val->special) {
3397 case ConstValSpecialLazy:
3398 zig_unreachable();
3389 case ConstValSpecialRuntime:3399 case ConstValSpecialRuntime:
3390 return false;3400 return false;
3391 case ConstValSpecialUndef:3401 case ConstValSpecialUndef:
...@@ -3525,6 +3535,8 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir...@@ -3525,6 +3535,8 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
3525}3535}
35263536
3527static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {3537static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
3538 if (instruction->base.value.special != ConstValSpecialRuntime)
3539 return ir_llvm_value(g, &instruction->base);
3528 ZigVar *var = instruction->var;3540 ZigVar *var = instruction->var;
3529 if (type_has_bits(var->var_type)) {3541 if (type_has_bits(var->var_type)) {
3530 assert(var->value_ref);3542 assert(var->value_ref);
...@@ -6041,6 +6053,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un...@@ -6041,6 +6053,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un
60416053
6042static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) {6054static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) {
6043 switch (const_val->special) {6055 switch (const_val->special) {
6056 case ConstValSpecialLazy:
6044 case ConstValSpecialRuntime:6057 case ConstValSpecialRuntime:
6045 zig_unreachable();6058 zig_unreachable();
6046 case ConstValSpecialUndef:6059 case ConstValSpecialUndef:
...@@ -6300,6 +6313,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -6300,6 +6313,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
6300 assert(type_has_bits(type_entry));6313 assert(type_has_bits(type_entry));
63016314
6302 switch (const_val->special) {6315 switch (const_val->special) {
6316 case ConstValSpecialLazy:
6317 zig_unreachable();
6303 case ConstValSpecialRuntime:6318 case ConstValSpecialRuntime:
6304 zig_unreachable();6319 zig_unreachable();
6305 case ConstValSpecialUndef:6320 case ConstValSpecialUndef:
...@@ -6563,7 +6578,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -6563,7 +6578,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
6563 uint64_t pad_bytes = type_entry->data.unionation.union_abi_size - field_type_bytes;6578 uint64_t pad_bytes = type_entry->data.unionation.union_abi_size - field_type_bytes;
6564 LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value, "");6579 LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value, "");
6565 make_unnamed_struct = is_llvm_value_unnamed_type(g, payload_value->type, correctly_typed_value) ||6580 make_unnamed_struct = is_llvm_value_unnamed_type(g, payload_value->type, correctly_typed_value) ||
6566 payload_value->type != type_entry->data.unionation.most_aligned_union_member;6581 payload_value->type != type_entry->data.unionation.most_aligned_union_member->type_entry;
65676582
6568 {6583 {
6569 if (pad_bytes == 0) {6584 if (pad_bytes == 0) {
...@@ -8905,7 +8920,7 @@ static void gen_root_source(CodeGen *g) {...@@ -8905,7 +8920,7 @@ static void gen_root_source(CodeGen *g) {
8905 }8920 }
8906 Tld *panic_tld = find_decl(g, &get_container_scope(import_with_panic)->base, buf_create_from_str("panic"));8921 Tld *panic_tld = find_decl(g, &get_container_scope(import_with_panic)->base, buf_create_from_str("panic"));
8907 assert(panic_tld != nullptr);8922 assert(panic_tld != nullptr);
8908 resolve_top_level_decl(g, panic_tld, nullptr);8923 resolve_top_level_decl(g, panic_tld, nullptr, false);
8909 }8924 }
89108925
89118926
src/ir.cpp+966-580
...@@ -152,11 +152,6 @@ struct ConstCastBadAllowsZero {...@@ -152,11 +152,6 @@ struct ConstCastBadAllowsZero {
152};152};
153153
154154
155enum UndefAllowed {
156 UndefOk,
157 UndefBad,
158};
159
160static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);155static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
161static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,156static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
162 ResultLoc *result_loc);157 ResultLoc *result_loc);
...@@ -234,6 +229,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -234,6 +229,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
234 }229 }
235 case ConstPtrSpecialBaseStruct: {230 case ConstPtrSpecialBaseStruct: {
236 ConstExprValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;231 ConstExprValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
232 expand_undef_struct(g, struct_val);
237 result = &struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index];233 result = &struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index];
238 break;234 break;
239 }235 }
...@@ -402,7 +398,7 @@ static void ir_ref_var(ZigVar *var) {...@@ -402,7 +398,7 @@ static void ir_ref_var(ZigVar *var) {
402ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) {398ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) {
403 ConstExprValue *result = ir_eval_const_value(ira->codegen, scope, node, ira->codegen->builtin_types.entry_type,399 ConstExprValue *result = ir_eval_const_value(ira->codegen, scope, node, ira->codegen->builtin_types.entry_type,
404 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, nullptr,400 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, nullptr,
405 node, nullptr, ira->new_irb.exec, nullptr);401 node, nullptr, ira->new_irb.exec, nullptr, UndefBad);
406402
407 if (type_is_invalid(result->type))403 if (type_is_invalid(result->type))
408 return ira->codegen->builtin_types.entry_invalid;404 return ira->codegen->builtin_types.entry_invalid;
...@@ -5766,7 +5762,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -5766,7 +5762,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
5766 buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf)));5762 buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf)));
5767 return irb->codegen->invalid_instruction;5763 return irb->codegen->invalid_instruction;
5768 }5764 }
5769 bit_offset_start = bigint_as_unsigned(node->data.pointer_type.bit_offset_start);5765 bit_offset_start = bigint_as_u32(node->data.pointer_type.bit_offset_start);
5770 }5766 }
57715767
5772 uint32_t host_int_bytes = 0;5768 uint32_t host_int_bytes = 0;
...@@ -5778,7 +5774,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -5778,7 +5774,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
5778 buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf)));5774 buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf)));
5779 return irb->codegen->invalid_instruction;5775 return irb->codegen->invalid_instruction;
5780 }5776 }
5781 host_int_bytes = bigint_as_unsigned(node->data.pointer_type.host_int_bytes);5777 host_int_bytes = bigint_as_u32(node->data.pointer_type.host_int_bytes);
5782 }5778 }
57835779
5784 if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) {5780 if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) {
...@@ -6858,7 +6854,7 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -6858,7 +6854,7 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
6858 uint32_t len = asm_token.end - asm_token.start - 2;6854 uint32_t len = asm_token.end - asm_token.start - 2;
68596855
6860 add_node_error(irb->codegen, node,6856 add_node_error(irb->codegen, node,
6861 buf_sprintf("could not find '%.*s' in the inputs or outputs.",6857 buf_sprintf("could not find '%.*s' in the inputs or outputs",
6862 len, ptr));6858 len, ptr));
6863 return irb->codegen->invalid_instruction;6859 return irb->codegen->invalid_instruction;
6864 }6860 }
...@@ -8111,7 +8107,12 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc...@@ -8111,7 +8107,12 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc
8111 ir_build_reset_result(irb, scope, node, result_loc);8107 ir_build_reset_result(irb, scope, node, result_loc);
8112 }8108 }
8113 IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval, result_loc);8109 IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval, result_loc);
8114 irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction);8110 if (result == irb->codegen->invalid_instruction) {
8111 if (irb->exec->first_err_trace_msg == nullptr) {
8112 irb->exec->first_err_trace_msg = irb->codegen->trace_err;
8113 }
8114 src_assert(irb->exec->first_err_trace_msg != nullptr, node);
8115 }
8115 return result;8116 return result;
8116}8117}
81178118
...@@ -8119,21 +8120,20 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) {...@@ -8119,21 +8120,20 @@ static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) {
8119 return ir_gen_node_extra(irb, node, scope, LValNone, nullptr);8120 return ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
8120}8121}
81218122
8122static void invalidate_exec(IrExecutable *exec) {8123static void invalidate_exec(IrExecutable *exec, ErrorMsg *msg) {
8123 if (exec->invalid)8124 if (exec->first_err_trace_msg != nullptr)
8124 return;8125 return;
81258126
8126 exec->invalid = true;8127 exec->first_err_trace_msg = msg;
81278128
8128 for (size_t i = 0; i < exec->tld_list.length; i += 1) {8129 for (size_t i = 0; i < exec->tld_list.length; i += 1) {
8129 exec->tld_list.items[i]->resolution = TldResolutionInvalid;8130 exec->tld_list.items[i]->resolution = TldResolutionInvalid;
8130 }8131 }
81318132
8132 if (exec->source_exec != nullptr)8133 if (exec->source_exec != nullptr)
8133 invalidate_exec(exec->source_exec);8134 invalidate_exec(exec->source_exec, msg);
8134}8135}
81358136
8136
8137bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_executable) {8137bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_executable) {
8138 assert(node->owner);8138 assert(node->owner);
81398139
...@@ -8151,8 +8151,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -8151,8 +8151,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
81518151
8152 IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr);8152 IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr);
8153 assert(result);8153 assert(result);
8154 if (irb->exec->invalid)8154 if (irb->exec->first_err_trace_msg != nullptr) {
8155 codegen->trace_err = irb->exec->first_err_trace_msg;
8155 return false;8156 return false;
8157 }
81568158
8157 if (!instr_is_unreachable(result)) {8159 if (!instr_is_unreachable(result)) {
8158 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result));8160 ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result));
...@@ -8181,15 +8183,9 @@ static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, Error...@@ -8181,15 +8183,9 @@ static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, Error
8181 ir_add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1);8183 ir_add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1);
8182}8184}
81838185
8184void ir_add_analysis_trace(IrAnalyze *ira, ErrorMsg *err_msg, Buf *text) {
8185 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
8186 add_error_note(ira->codegen, err_msg, old_instruction->source_node, text);
8187 ir_add_call_stack_errors(ira->codegen, ira->new_irb.exec, err_msg, 10);
8188}
8189
8190static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg) {8186static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg) {
8191 invalidate_exec(exec);
8192 ErrorMsg *err_msg = add_node_error(codegen, source_node, msg);8187 ErrorMsg *err_msg = add_node_error(codegen, source_node, msg);
8188 invalidate_exec(exec, err_msg);
8193 if (exec->parent_exec) {8189 if (exec->parent_exec) {
8194 ir_add_call_stack_errors(codegen, exec, err_msg, 10);8190 ir_add_call_stack_errors(codegen, exec, err_msg, 10);
8195 }8191 }
...@@ -8223,6 +8219,7 @@ static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, Ast...@@ -8223,6 +8219,7 @@ static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, Ast
8223{8219{
8224 Error err;8220 Error err;
8225 assert(ptr_val->type->id == ZigTypeIdPointer);8221 assert(ptr_val->type->id == ZigTypeIdPointer);
8222 assert(ptr_val->special == ConstValSpecialStatic);
8226 ConstExprValue tmp = {};8223 ConstExprValue tmp = {};
8227 tmp.special = ConstValSpecialStatic;8224 tmp.special = ConstValSpecialStatic;
8228 tmp.type = ptr_val->type->data.pointer.child_type;8225 tmp.type = ptr_val->type->data.pointer.child_type;
...@@ -9016,7 +9013,8 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -9016,7 +9013,8 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
9016 }9013 }
90179014
9018 ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad);9015 ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad);
9019 assert(const_val != nullptr);9016 if (const_val == nullptr)
9017 return false;
90209018
9021 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);9019 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
9022 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);9020 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);
...@@ -9376,6 +9374,14 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9376,6 +9374,14 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9376 result.id = ConstCastResultIdInvalid;9374 result.id = ConstCastResultIdInvalid;
9377 return result;9375 return result;
9378 }9376 }
9377 if ((err = type_resolve(g, wanted_type, ResolveStatusZeroBitsKnown))) {
9378 result.id = ConstCastResultIdInvalid;
9379 return result;
9380 }
9381 if ((err = type_resolve(g, actual_type, ResolveStatusZeroBitsKnown))) {
9382 result.id = ConstCastResultIdInvalid;
9383 return result;
9384 }
9379 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;9385 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
9380 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&9386 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
9381 type_has_bits(wanted_type) == type_has_bits(actual_type) &&9387 type_has_bits(wanted_type) == type_has_bits(actual_type) &&
...@@ -10634,7 +10640,7 @@ static void ir_finish_bb(IrAnalyze *ira) {...@@ -10634,7 +10640,7 @@ static void ir_finish_bb(IrAnalyze *ira) {
1063410640
10635static IrInstruction *ir_unreach_error(IrAnalyze *ira) {10641static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
10636 ira->old_bb_index = SIZE_MAX;10642 ira->old_bb_index = SIZE_MAX;
10637 ira->new_irb.exec->invalid = true;10643 assert(ira->new_irb.exec->first_err_trace_msg != nullptr);
10638 return ira->codegen->unreach_instruction;10644 return ira->codegen->unreach_instruction;
10639}10645}
1064010646
...@@ -10722,32 +10728,57 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio...@@ -10722,32 +10728,57 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
10722 return const_instr;10728 return const_instr;
10723}10729}
1072410730
10731static Error ir_resolve_const_val(CodeGen *codegen, IrExecutable *exec, AstNode *source_node,
10732 ConstExprValue *val, UndefAllowed undef_allowed)
10733{
10734 Error err;
10735 for (;;) {
10736 switch (val->special) {
10737 case ConstValSpecialStatic:
10738 return ErrorNone;
10739 case ConstValSpecialRuntime:
10740 if (!type_has_bits(val->type))
10741 return ErrorNone;
10742
10743 exec_add_error_node(codegen, exec, source_node,
10744 buf_sprintf("unable to evaluate constant expression"));
10745 return ErrorSemanticAnalyzeFail;
10746 case ConstValSpecialUndef:
10747 if (undef_allowed == UndefOk || undef_allowed == LazyOk)
10748 return ErrorNone;
10749
10750 exec_add_error_node(codegen, exec, source_node,
10751 buf_sprintf("use of undefined value here causes undefined behavior"));
10752 return ErrorSemanticAnalyzeFail;
10753 case ConstValSpecialLazy:
10754 if (undef_allowed == LazyOk || undef_allowed == LazyOkNoUndef)
10755 return ErrorNone;
10756
10757 if ((err = ir_resolve_lazy(codegen, source_node, val)))
10758 return err;
10759
10760 continue;
10761 }
10762 }
10763}
10764
10725static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {10765static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {
10726 switch (value->value.special) {10766 Error err;
10727 case ConstValSpecialStatic:10767 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, value->source_node,
10728 return &value->value;10768 &value->value, undef_allowed)))
10729 case ConstValSpecialRuntime:10769 {
10730 if (!type_has_bits(value->value.type)) {10770 return nullptr;
10731 return &value->value;
10732 }
10733 ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression"));
10734 return nullptr;
10735 case ConstValSpecialUndef:
10736 if (undef_allowed == UndefOk) {
10737 return &value->value;
10738 } else {
10739 ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior"));
10740 return nullptr;
10741 }
10742 }10771 }
10743 zig_unreachable();10772 return &value->value;
10744}10773}
1074510774
10746ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,10775ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
10747 ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,10776 ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
10748 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,10777 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
10749 IrExecutable *parent_exec, AstNode *expected_type_source_node)10778 IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed)
10750{10779{
10780 Error err;
10781
10751 if (expected_type != nullptr && type_is_invalid(expected_type))10782 if (expected_type != nullptr && type_is_invalid(expected_type))
10752 return &codegen->invalid_instruction->value;10783 return &codegen->invalid_instruction->value;
1075310784
...@@ -10761,8 +10792,10 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod...@@ -10761,8 +10792,10 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
10761 ir_executable->begin_scope = scope;10792 ir_executable->begin_scope = scope;
10762 ir_gen(codegen, node, scope, ir_executable);10793 ir_gen(codegen, node, scope, ir_executable);
1076310794
10764 if (ir_executable->invalid)10795 if (ir_executable->first_err_trace_msg != nullptr) {
10796 codegen->trace_err = ir_executable->first_err_trace_msg;
10765 return &codegen->invalid_instruction->value;10797 return &codegen->invalid_instruction->value;
10798 }
1076610799
10767 if (codegen->verbose_ir) {10800 if (codegen->verbose_ir) {
10768 fprintf(stderr, "\nSource: ");10801 fprintf(stderr, "\nSource: ");
...@@ -10783,8 +10816,9 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod...@@ -10783,8 +10816,9 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
10783 analyzed_executable->backward_branch_quota = backward_branch_quota;10816 analyzed_executable->backward_branch_quota = backward_branch_quota;
10784 analyzed_executable->begin_scope = scope;10817 analyzed_executable->begin_scope = scope;
10785 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node);10818 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node);
10786 if (type_is_invalid(result_type))10819 if (type_is_invalid(result_type)) {
10787 return &codegen->invalid_instruction->value;10820 return &codegen->invalid_instruction->value;
10821 }
1078810822
10789 if (codegen->verbose_ir) {10823 if (codegen->verbose_ir) {
10790 fprintf(stderr, "{ // (analyzed)\n");10824 fprintf(stderr, "{ // (analyzed)\n");
...@@ -10792,7 +10826,14 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod...@@ -10792,7 +10826,14 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
10792 fprintf(stderr, "}\n");10826 fprintf(stderr, "}\n");
10793 }10827 }
1079410828
10795 return ir_exec_const_result(codegen, analyzed_executable);10829 ConstExprValue *result = ir_exec_const_result(codegen, analyzed_executable);
10830 if (type_is_invalid(result->type))
10831 return &codegen->invalid_instruction->value;
10832
10833 if ((err = ir_resolve_const_val(codegen, analyzed_executable, node, result, undef_allowed)))
10834 return &codegen->invalid_instruction->value;
10835
10836 return result;
10796}10837}
1079710838
10798static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_value) {10839static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_value) {
...@@ -10813,22 +10854,43 @@ static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_valu...@@ -10813,22 +10854,43 @@ static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_valu
10813 return const_val->data.x_err_set;10854 return const_val->data.x_err_set;
10814}10855}
1081510856
10816static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {10857static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node,
10858 ConstExprValue *val)
10859{
10860 Error err;
10861 if ((err = ir_resolve_const_val(codegen, exec, source_node, val, UndefBad)))
10862 return codegen->builtin_types.entry_invalid;
10863
10864 assert(val->data.x_type != nullptr);
10865 return val->data.x_type;
10866}
10867
10868static ConstExprValue *ir_resolve_type_lazy(IrAnalyze *ira, IrInstruction *type_value) {
10817 if (type_is_invalid(type_value->value.type))10869 if (type_is_invalid(type_value->value.type))
10818 return ira->codegen->builtin_types.entry_invalid;10870 return nullptr;
1081910871
10820 if (type_value->value.type->id != ZigTypeIdMetaType) {10872 if (type_value->value.type->id != ZigTypeIdMetaType) {
10821 ir_add_error(ira, type_value,10873 ir_add_error(ira, type_value,
10822 buf_sprintf("expected type 'type', found '%s'", buf_ptr(&type_value->value.type->name)));10874 buf_sprintf("expected type 'type', found '%s'", buf_ptr(&type_value->value.type->name)));
10823 return ira->codegen->builtin_types.entry_invalid;10875 return nullptr;
10824 }10876 }
1082510877
10826 ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad);10878 Error err;
10827 if (!const_val)10879 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, type_value->source_node,
10880 &type_value->value, LazyOk)))
10881 {
10882 return nullptr;
10883 }
10884
10885 return &type_value->value;
10886}
10887
10888static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
10889 ConstExprValue *val = ir_resolve_type_lazy(ira, type_value);
10890 if (val == nullptr)
10828 return ira->codegen->builtin_types.entry_invalid;10891 return ira->codegen->builtin_types.entry_invalid;
1082910892
10830 assert(const_val->data.x_type != nullptr);10893 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val);
10831 return const_val->data.x_type;
10832}10894}
1083310895
10834static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) {10896static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) {
...@@ -11026,14 +11088,21 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou...@@ -11026,14 +11088,21 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou
11026}11088}
1102711089
11028static IrInstruction *ir_analyze_frame_ptr_to_anyframe(IrAnalyze *ira, IrInstruction *source_instr,11090static IrInstruction *ir_analyze_frame_ptr_to_anyframe(IrAnalyze *ira, IrInstruction *source_instr,
11029 IrInstruction *value, ZigType *wanted_type)11091 IrInstruction *frame_ptr, ZigType *wanted_type)
11030{11092{
11031 if (instr_is_comptime(value)) {11093 if (instr_is_comptime(frame_ptr)) {
11032 zig_panic("TODO comptime frame pointer");11094 ConstExprValue *ptr_val = ir_resolve_const(ira, frame_ptr, UndefBad);
11095 if (ptr_val == nullptr)
11096 return ira->codegen->invalid_instruction;
11097
11098 ir_assert(ptr_val->type->id == ZigTypeIdPointer, source_instr);
11099 if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
11100 zig_panic("TODO comptime frame pointer");
11101 }
11033 }11102 }
1103411103
11035 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node,11104 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node,
11036 wanted_type, value, CastOpBitCast);11105 wanted_type, frame_ptr, CastOpBitCast);
11037 result->value.type = wanted_type;11106 result->value.type = wanted_type;
11038 return result;11107 return result;
11039}11108}
...@@ -11152,6 +11221,9 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi...@@ -11152,6 +11221,9 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
11152 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,11221 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
11153 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);11222 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
1115411223
11224 if ((err = type_resolve(ira->codegen, ptr_type, ResolveStatusZeroBitsKnown)))
11225 return ira->codegen->invalid_instruction;
11226
11155 IrInstruction *result_loc;11227 IrInstruction *result_loc;
11156 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {11228 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
11157 result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true,11229 result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true,
...@@ -11322,7 +11394,7 @@ static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruc...@@ -11322,7 +11394,7 @@ static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruc
11322 IrInstruction *target, ZigType *wanted_type)11394 IrInstruction *target, ZigType *wanted_type)
11323{11395{
11324 IrInstruction *result = ir_const(ira, source_instr, wanted_type);11396 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
11325 init_const_undefined(ira->codegen, &result->value);11397 result->value.special = ConstValSpecialUndef;
11326 return result;11398 return result;
11327}11399}
1132811400
...@@ -11345,10 +11417,13 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so...@@ -11345,10 +11417,13 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
11345 return ira->codegen->invalid_instruction;11417 return ira->codegen->invalid_instruction;
11346 TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);11418 TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);
11347 assert(union_field != nullptr);11419 assert(union_field != nullptr);
11348 if ((err = type_resolve(ira->codegen, union_field->type_entry, ResolveStatusZeroBitsKnown)))11420 ZigType *field_type = resolve_union_field_type(ira->codegen, union_field);
11421 if (field_type == nullptr)
11422 return ira->codegen->invalid_instruction;
11423 if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown)))
11349 return ira->codegen->invalid_instruction;11424 return ira->codegen->invalid_instruction;
1135011425
11351 switch (type_has_one_possible_value(ira->codegen, union_field->type_entry)) {11426 switch (type_has_one_possible_value(ira->codegen, field_type)) {
11352 case OnePossibleValueInvalid:11427 case OnePossibleValueInvalid:
11353 return ira->codegen->invalid_instruction;11428 return ira->codegen->invalid_instruction;
11354 case OnePossibleValueNo: {11429 case OnePossibleValueNo: {
...@@ -11357,7 +11432,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so...@@ -11357,7 +11432,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
11357 ErrorMsg *msg = ir_add_error(ira, source_instr,11432 ErrorMsg *msg = ir_add_error(ira, source_instr,
11358 buf_sprintf("cast to union '%s' must initialize '%s' field '%s'",11433 buf_sprintf("cast to union '%s' must initialize '%s' field '%s'",
11359 buf_ptr(&wanted_type->name),11434 buf_ptr(&wanted_type->name),
11360 buf_ptr(&union_field->type_entry->name),11435 buf_ptr(&field_type->name),
11361 buf_ptr(union_field->name)));11436 buf_ptr(union_field->name)));
11362 add_error_note(ira->codegen, msg, field_node,11437 add_error_note(ira->codegen, msg, field_node,
11363 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));11438 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
...@@ -11373,7 +11448,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so...@@ -11373,7 +11448,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
11373 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);11448 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);
11374 result->value.data.x_union.payload = create_const_vals(1);11449 result->value.data.x_union.payload = create_const_vals(1);
11375 result->value.data.x_union.payload->special = ConstValSpecialStatic;11450 result->value.data.x_union.payload->special = ConstValSpecialStatic;
11376 result->value.data.x_union.payload->type = union_field->type_entry;11451 result->value.data.x_union.payload->type = field_type;
11377 return result;11452 return result;
11378 }11453 }
1137911454
...@@ -11390,12 +11465,17 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so...@@ -11390,12 +11465,17 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
11390 buf_ptr(&wanted_type->name)));11465 buf_ptr(&wanted_type->name)));
11391 for (uint32_t i = 0; i < wanted_type->data.unionation.src_field_count; i += 1) {11466 for (uint32_t i = 0; i < wanted_type->data.unionation.src_field_count; i += 1) {
11392 TypeUnionField *union_field = &wanted_type->data.unionation.fields[i];11467 TypeUnionField *union_field = &wanted_type->data.unionation.fields[i];
11393 if (type_has_bits(union_field->type_entry)) {11468 ZigType *field_type = resolve_union_field_type(ira->codegen, union_field);
11469 if (field_type == nullptr)
11470 return ira->codegen->invalid_instruction;
11471 if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown)))
11472 return ira->codegen->invalid_instruction;
11473 if (type_has_bits(field_type)) {
11394 AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(i);11474 AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(i);
11395 add_error_note(ira->codegen, msg, field_node,11475 add_error_note(ira->codegen, msg, field_node,
11396 buf_sprintf("field '%s' has type '%s'",11476 buf_sprintf("field '%s' has type '%s'",
11397 buf_ptr(union_field->name),11477 buf_ptr(union_field->name),
11398 buf_ptr(&union_field->type_entry->name)));11478 buf_ptr(&field_type->name)));
11399 }11479 }
11400 }11480 }
11401 return ira->codegen->invalid_instruction;11481 return ira->codegen->invalid_instruction;
...@@ -11461,7 +11541,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -11461,7 +11541,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
1146111541
11462 ZigType *actual_type = target->value.type;11542 ZigType *actual_type = target->value.type;
1146311543
11464 if ((err = ensure_complete_type(ira->codegen, wanted_type)))11544 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))
11465 return ira->codegen->invalid_instruction;11545 return ira->codegen->invalid_instruction;
1146611546
11467 if (actual_type != wanted_type->data.enumeration.tag_int_type) {11547 if (actual_type != wanted_type->data.enumeration.tag_int_type) {
...@@ -11550,7 +11630,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc...@@ -11550,7 +11630,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
11550 return ira->codegen->invalid_instruction;11630 return ira->codegen->invalid_instruction;
11551 }11631 }
1155211632
11553 size_t index = bigint_as_unsigned(&val->data.x_bigint);11633 size_t index = bigint_as_usize(&val->data.x_bigint);
11554 result->value.data.x_err_set = ira->codegen->errors_by_index.at(index);11634 result->value.data.x_err_set = ira->codegen->errors_by_index.at(index);
11555 return result;11635 return result;
11556 } else {11636 } else {
...@@ -12508,26 +12588,22 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -12508,26 +12588,22 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
12508 return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst);12588 return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst);
12509}12589}
1251012590
12511static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {12591static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode *source_node,
12512 if (type_is_invalid(value->value.type))12592 ConstExprValue *const_val, uint32_t *out)
12513 return false;12593{
1251412594 Error err;
12515 IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen));12595 if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad)))
12516 if (type_is_invalid(casted_value->value.type))
12517 return false;
12518
12519 ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
12520 if (!const_val)
12521 return false;12596 return false;
1252212597
12523 uint32_t align_bytes = bigint_as_unsigned(&const_val->data.x_bigint);12598 uint32_t align_bytes = bigint_as_u32(&const_val->data.x_bigint);
12524 if (align_bytes == 0) {12599 if (align_bytes == 0) {
12525 ir_add_error(ira, value, buf_sprintf("alignment must be >= 1"));12600 exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment must be >= 1"));
12526 return false;12601 return false;
12527 }12602 }
1252812603
12529 if (!is_power_of_2(align_bytes)) {12604 if (!is_power_of_2(align_bytes)) {
12530 ir_add_error(ira, value, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes));12605 exec_add_error_node(codegen, exec, source_node,
12606 buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes));
12531 return false;12607 return false;
12532 }12608 }
1253312609
...@@ -12535,6 +12611,18 @@ static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out...@@ -12535,6 +12611,18 @@ static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out
12535 return true;12611 return true;
12536}12612}
1253712613
12614static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) {
12615 if (type_is_invalid(value->value.type))
12616 return false;
12617
12618 IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen));
12619 if (type_is_invalid(casted_value->value.type))
12620 return false;
12621
12622 return ir_resolve_const_align(ira->codegen, ira->new_irb.exec, value->source_node,
12623 &casted_value->value, out);
12624}
12625
12538static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *int_type, uint64_t *out) {12626static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *int_type, uint64_t *out) {
12539 if (type_is_invalid(value->value.type))12627 if (type_is_invalid(value->value.type))
12540 return false;12628 return false;
...@@ -12547,7 +12635,7 @@ static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *i...@@ -12547,7 +12635,7 @@ static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *i
12547 if (!const_val)12635 if (!const_val)
12548 return false;12636 return false;
1254912637
12550 *out = bigint_as_unsigned(&const_val->data.x_bigint);12638 *out = bigint_as_u64(&const_val->data.x_bigint);
12551 return true;12639 return true;
12552}12640}
1255312641
...@@ -12595,7 +12683,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic...@@ -12595,7 +12683,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
12595 if (!const_val)12683 if (!const_val)
12596 return false;12684 return false;
1259712685
12598 *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum_tag);12686 *out = (AtomicOrder)bigint_as_u32(&const_val->data.x_enum_tag);
12599 return true;12687 return true;
12600}12688}
1260112689
...@@ -12615,7 +12703,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi...@@ -12615,7 +12703,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi
12615 if (!const_val)12703 if (!const_val)
12616 return false;12704 return false;
1261712705
12618 *out = (AtomicRmwOp)bigint_as_unsigned(&const_val->data.x_enum_tag);12706 *out = (AtomicRmwOp)bigint_as_u32(&const_val->data.x_enum_tag);
12619 return true;12707 return true;
12620}12708}
1262112709
...@@ -12635,7 +12723,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob...@@ -12635,7 +12723,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob
12635 if (!const_val)12723 if (!const_val)
12636 return false;12724 return false;
1263712725
12638 *out = (GlobalLinkageId)bigint_as_unsigned(&const_val->data.x_enum_tag);12726 *out = (GlobalLinkageId)bigint_as_u32(&const_val->data.x_enum_tag);
12639 return true;12727 return true;
12640}12728}
1264112729
...@@ -12655,7 +12743,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod...@@ -12655,7 +12743,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod
12655 if (!const_val)12743 if (!const_val)
12656 return false;12744 return false;
1265712745
12658 *out = (FloatMode)bigint_as_unsigned(&const_val->data.x_enum_tag);12746 *out = (FloatMode)bigint_as_u32(&const_val->data.x_enum_tag);
12659 return true;12747 return true;
12660}12748}
1266112749
...@@ -12684,7 +12772,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {...@@ -12684,7 +12772,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
12684 return array_val->data.x_array.data.s_buf;12772 return array_val->data.x_array.data.s_buf;
12685 }12773 }
12686 expand_undef_array(ira->codegen, array_val);12774 expand_undef_array(ira->codegen, array_val);
12687 size_t len = bigint_as_unsigned(&len_field->data.x_bigint);12775 size_t len = bigint_as_usize(&len_field->data.x_bigint);
12688 Buf *result = buf_alloc();12776 Buf *result = buf_alloc();
12689 buf_resize(result, len);12777 buf_resize(result, len);
12690 for (size_t i = 0; i < len; i += 1) {12778 for (size_t i = 0; i < len; i += 1) {
...@@ -12694,7 +12782,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {...@@ -12694,7 +12782,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
12694 ir_add_error(ira, casted_value, buf_sprintf("use of undefined value"));12782 ir_add_error(ira, casted_value, buf_sprintf("use of undefined value"));
12695 return nullptr;12783 return nullptr;
12696 }12784 }
12697 uint64_t big_c = bigint_as_unsigned(&char_val->data.x_bigint);12785 uint64_t big_c = bigint_as_u64(&char_val->data.x_bigint);
12698 assert(big_c <= UINT8_MAX);12786 assert(big_c <= UINT8_MAX);
12699 uint8_t c = (uint8_t)big_c;12787 uint8_t c = (uint8_t)big_c;
12700 buf_ptr(result)[i] = c;12788 buf_ptr(result)[i] = c;
...@@ -12719,7 +12807,9 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio...@@ -12719,7 +12807,9 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
12719 if (type_is_invalid(operand->value.type))12807 if (type_is_invalid(operand->value.type))
12720 return ir_unreach_error(ira);12808 return ir_unreach_error(ira);
1272112809
12722 if (!instr_is_comptime(operand) && handle_is_ptr(ira->explicit_return_type)) {12810 if (!instr_is_comptime(operand) && ira->explicit_return_type != nullptr &&
12811 handle_is_ptr(ira->explicit_return_type))
12812 {
12723 // result location mechanism took care of it.12813 // result location mechanism took care of it.
12724 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,12814 IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope,
12725 instruction->base.source_node, nullptr);12815 instruction->base.source_node, nullptr);
...@@ -13576,21 +13666,34 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -13576,21 +13666,34 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
13576 if (type_is_invalid(casted_op2->value.type))13666 if (type_is_invalid(casted_op2->value.type))
13577 return ira->codegen->invalid_instruction;13667 return ira->codegen->invalid_instruction;
1357813668
13579 if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) {13669 // If either operand is undef, result is undef.
13580 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);13670 ConstExprValue *op1_val = nullptr;
13581 result->value.special = ConstValSpecialUndef;13671 ConstExprValue *op2_val = nullptr;
13582 return result;13672 if (instr_is_comptime(op1)) {
13673 op1_val = ir_resolve_const(ira, op1, UndefOk);
13674 if (op1_val == nullptr)
13675 return ira->codegen->invalid_instruction;
13676 if (op1_val->special == ConstValSpecialUndef)
13677 return ir_const_undef(ira, &instruction->base, op1->value.type);
13583 }13678 }
13584 if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic &&13679 if (instr_is_comptime(casted_op2)) {
13680 op2_val = ir_resolve_const(ira, casted_op2, UndefOk);
13681 if (op2_val == nullptr)
13682 return ira->codegen->invalid_instruction;
13683 if (op2_val->special == ConstValSpecialUndef)
13684 return ir_const_undef(ira, &instruction->base, op1->value.type);
13685 }
13686
13687 if (op2_val != nullptr && op1_val != nullptr &&
13585 (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||13688 (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
13586 op1->value.data.x_ptr.special == ConstPtrSpecialNull))13689 op1->value.data.x_ptr.special == ConstPtrSpecialNull))
13587 {13690 {
13588 uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ?13691 uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ?
13589 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr;13692 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
13590 uint64_t elem_offset;13693 uint64_t elem_offset;
13591 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))13694 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
13592 return ira->codegen->invalid_instruction;13695 return ira->codegen->invalid_instruction;
13593 ZigType *elem_type = op1->value.type->data.pointer.child_type;13696 ZigType *elem_type = op1_val->type->data.pointer.child_type;
13594 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))13697 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
13595 return ira->codegen->invalid_instruction;13698 return ira->codegen->invalid_instruction;
13596 uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset;13699 uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
...@@ -13602,7 +13705,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -13602,7 +13705,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
13602 } else {13705 } else {
13603 zig_unreachable();13706 zig_unreachable();
13604 }13707 }
13605 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);13708 IrInstruction *result = ir_const(ira, &instruction->base, op1_val->type);
13606 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;13709 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
13607 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;13710 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
13608 result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr;13711 result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr;
...@@ -13829,7 +13932,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -13829,7 +13932,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
13829 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;13932 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
13830 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;13933 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
13831 ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index];13934 ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index];
13832 op1_array_end = op1_array_index + bigint_as_unsigned(&len_val->data.x_bigint);13935 op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint);
13833 } else {13936 } else {
13834 ir_add_error(ira, op1,13937 ir_add_error(ira, op1,
13835 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));13938 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
...@@ -13862,7 +13965,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -13862,7 +13965,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
13862 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;13965 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
13863 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;13966 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
13864 ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index];13967 ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index];
13865 op2_array_end = op2_array_index + bigint_as_unsigned(&len_val->data.x_bigint);13968 op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint);
13866 } else {13969 } else {
13867 ir_add_error(ira, op2,13970 ir_add_error(ira, op2,
13868 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));13971 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
...@@ -14171,9 +14274,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -14171,9 +14274,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
14171 }14274 }
14172 break;14275 break;
14173 case ReqCompTimeNo:14276 case ReqCompTimeNo:
14174 if (init_val != nullptr) {14277 if (init_val != nullptr && value_is_comptime(init_val)) {
14175 if (init_val->special == ConstValSpecialStatic &&14278 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
14176 init_val->type->id == ZigTypeIdFn &&14279 decl_var_instruction->base.source_node, init_val, UndefOk)))
14280 {
14281 result_type = ira->codegen->builtin_types.entry_invalid;
14282 } else if (init_val->type->id == ZigTypeIdFn &&
14283 init_val->special != ConstValSpecialUndef &&
14177 init_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&14284 init_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
14178 init_val->data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)14285 init_val->data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
14179 {14286 {
...@@ -14231,7 +14338,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -14231,7 +14338,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
14231 }14338 }
14232 }14339 }
1423314340
14234 if (init_val != nullptr && init_val->special != ConstValSpecialRuntime) {14341 if (init_val != nullptr && value_is_comptime(init_val)) {
14235 // Resolve ConstPtrMutInfer14342 // Resolve ConstPtrMutInfer
14236 if (var->gen_is_const) {14343 if (var->gen_is_const) {
14237 var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeConst;14344 var_ptr->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
...@@ -14242,6 +14349,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -14242,6 +14349,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
14242 // since it's a comptime val there are no instructions for it.14349 // since it's a comptime val there are no instructions for it.
14243 // we memcpy the init value here14350 // we memcpy the init value here
14244 IrInstruction *deref = ir_get_deref(ira, var_ptr, var_ptr, nullptr);14351 IrInstruction *deref = ir_get_deref(ira, var_ptr, var_ptr, nullptr);
14352 if (type_is_invalid(deref->value.type)) {
14353 var->var_type = ira->codegen->builtin_types.entry_invalid;
14354 return ira->codegen->invalid_instruction;
14355 }
14245 // If this assertion trips, something is wrong with the IR instructions, because14356 // If this assertion trips, something is wrong with the IR instructions, because
14246 // we expected the above deref to return a constant value, but it created a runtime14357 // we expected the above deref to return a constant value, but it created a runtime
14247 // instruction.14358 // instruction.
...@@ -14250,7 +14361,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -14250,7 +14361,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
14250 ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref, false);14361 ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref, false);
14251 }14362 }
1425214363
14253 if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) {14364 if (instr_is_comptime(var_ptr) && var->mem_slot_index != SIZE_MAX) {
14254 assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);14365 assert(var->mem_slot_index < ira->exec_context.mem_slot_list.length);
14255 ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);14366 ConstExprValue *mem_slot = ira->exec_context.mem_slot_list.at(var->mem_slot_index);
14256 copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const);14367 copy_const_val(mem_slot, init_val, !is_comptime_var || var->gen_is_const);
...@@ -14515,28 +14626,23 @@ static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,...@@ -14515,28 +14626,23 @@ static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
14515static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira,14626static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira,
14516 IrInstructionErrorUnion *instruction)14627 IrInstructionErrorUnion *instruction)
14517{14628{
14518 Error err;14629 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
14630 result->value.special = ConstValSpecialLazy;
1451914631
14520 ZigType *err_set_type = ir_resolve_type(ira, instruction->err_set->child);14632 LazyValueErrUnionType *lazy_err_union_type = allocate<LazyValueErrUnionType>(1);
14521 if (type_is_invalid(err_set_type))14633 lazy_err_union_type->ira = ira;
14522 return ira->codegen->invalid_instruction;14634 result->value.data.x_lazy = &lazy_err_union_type->base;
1452314635 lazy_err_union_type->base.id = LazyValueIdErrUnionType;
14524 ZigType *payload_type = ir_resolve_type(ira, instruction->payload->child);
14525 if (type_is_invalid(payload_type))
14526 return ira->codegen->invalid_instruction;
1452714636
14528 if (err_set_type->id != ZigTypeIdErrorSet) {14637 lazy_err_union_type->err_set_type = instruction->err_set->child;
14529 ir_add_error(ira, instruction->err_set->child,14638 if (ir_resolve_type_lazy(ira, lazy_err_union_type->err_set_type) == nullptr)
14530 buf_sprintf("expected error set type, found type '%s'",
14531 buf_ptr(&err_set_type->name)));
14532 return ira->codegen->invalid_instruction;14639 return ira->codegen->invalid_instruction;
14533 }
1453414640
14535 if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))14641 lazy_err_union_type->payload_type = instruction->payload->child;
14642 if (ir_resolve_type_lazy(ira, lazy_err_union_type->payload_type) == nullptr)
14536 return ira->codegen->invalid_instruction;14643 return ira->codegen->invalid_instruction;
14537 ZigType *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type);
1453814644
14539 return ir_const_type(ira, &instruction->base, result_type);14645 return result;
14540}14646}
1454114647
14542static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type,14648static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type,
...@@ -14555,6 +14661,10 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in...@@ -14555,6 +14661,10 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in
1455514661
14556 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))14662 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown)))
14557 return ira->codegen->invalid_instruction;14663 return ira->codegen->invalid_instruction;
14664 if (align != 0) {
14665 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown)))
14666 return ira->codegen->invalid_instruction;
14667 }
14558 assert(result->base.value.data.x_ptr.special != ConstPtrSpecialInvalid);14668 assert(result->base.value.data.x_ptr.special != ConstPtrSpecialInvalid);
1455914669
14560 pointee->type = var_type;14670 pointee->type = var_type;
...@@ -15174,23 +15284,25 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -15174,23 +15284,25 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1517415284
15175 bool comptime_var_mem = ir_get_var_is_comptime(var);15285 bool comptime_var_mem = ir_get_var_is_comptime(var);
15176 bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern;15286 bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern;
15177 bool is_const = var->src_is_const;
15178 bool is_volatile = false;15287 bool is_volatile = false;
1517915288
15289 IrInstruction *result = ir_build_var_ptr(&ira->new_irb,
15290 instruction->scope, instruction->source_node, var);
15291 result->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type,
15292 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0, false);
15293
15180 if (linkage_makes_it_runtime)15294 if (linkage_makes_it_runtime)
15181 goto no_mem_slot;15295 goto no_mem_slot;
1518215296
15183 if (var->const_value->special == ConstValSpecialStatic) {15297 if (value_is_comptime(var->const_value)) {
15184 mem_slot = var->const_value;15298 mem_slot = var->const_value;
15185 } else {15299 } else if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
15186 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {15300 // find the relevant exec_context
15187 // find the relevant exec_context15301 assert(var->owner_exec != nullptr);
15188 assert(var->owner_exec != nullptr);15302 assert(var->owner_exec->analysis != nullptr);
15189 assert(var->owner_exec->analysis != nullptr);15303 IrExecContext *exec_context = &var->owner_exec->analysis->exec_context;
15190 IrExecContext *exec_context = &var->owner_exec->analysis->exec_context;15304 assert(var->mem_slot_index < exec_context->mem_slot_list.length);
15191 assert(var->mem_slot_index < exec_context->mem_slot_list.length);15305 mem_slot = exec_context->mem_slot_list.at(var->mem_slot_index);
15192 mem_slot = exec_context->mem_slot_list.at(var->mem_slot_index);
15193 }
15194 }15306 }
1519515307
15196 if (mem_slot != nullptr) {15308 if (mem_slot != nullptr) {
...@@ -15198,6 +15310,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -15198,6 +15310,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
15198 case ConstValSpecialRuntime:15310 case ConstValSpecialRuntime:
15199 goto no_mem_slot;15311 goto no_mem_slot;
15200 case ConstValSpecialStatic: // fallthrough15312 case ConstValSpecialStatic: // fallthrough
15313 case ConstValSpecialLazy: // fallthrough
15201 case ConstValSpecialUndef: {15314 case ConstValSpecialUndef: {
15202 ConstPtrMut ptr_mut;15315 ConstPtrMut ptr_mut;
15203 if (comptime_var_mem) {15316 if (comptime_var_mem) {
...@@ -15208,8 +15321,11 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -15208,8 +15321,11 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
15208 assert(!comptime_var_mem);15321 assert(!comptime_var_mem);
15209 ptr_mut = ConstPtrMutRuntimeVar;15322 ptr_mut = ConstPtrMutRuntimeVar;
15210 }15323 }
15211 return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type,15324 result->value.special = ConstValSpecialStatic;
15212 ptr_mut, is_const, is_volatile, var->align_bytes);15325 result->value.data.x_ptr.mut = ptr_mut;
15326 result->value.data.x_ptr.special = ConstPtrSpecialRef;
15327 result->value.data.x_ptr.data.ref.pointee = mem_slot;
15328 return result;
15213 }15329 }
15214 }15330 }
15215 zig_unreachable();15331 zig_unreachable();
...@@ -15217,15 +15333,10 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -15217,15 +15333,10 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1521715333
15218no_mem_slot:15334no_mem_slot:
1521915335
15220 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
15221 instruction->scope, instruction->source_node, var);
15222 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type,
15223 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0, false);
15224
15225 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);15336 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
15226 var_ptr_instruction->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack;15337 result->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack;
1522715338
15228 return var_ptr_instruction;15339 return result;
15229}15340}
1523015341
15231// This function is called when a comptime value becomes accessible at runtime.15342// This function is called when a comptime value becomes accessible at runtime.
...@@ -15489,7 +15600,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15489,7 +15600,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15489 AstNode *body_node = fn_entry->body_node;15600 AstNode *body_node = fn_entry->body_node;
15490 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,15601 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
15491 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,15602 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
15492 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node);15603 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node,
15604 UndefOk);
1549315605
15494 if (inferred_err_set_type != nullptr) {15606 if (inferred_err_set_type != nullptr) {
15495 inferred_err_set_type->data.error_set.infer_fn = nullptr;15607 inferred_err_set_type->data.error_set.infer_fn = nullptr;
...@@ -15513,8 +15625,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15513,8 +15625,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15513 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);15625 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
15514 }15626 }
1551515627
15516 if (type_is_invalid(result->type))15628 if (type_is_invalid(result->type)) {
15517 return ira->codegen->invalid_instruction;15629 return ira->codegen->invalid_instruction;
15630 }
15518 }15631 }
1551915632
15520 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);15633 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);
...@@ -15685,7 +15798,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15685,7 +15798,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15685 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,15798 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
15686 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),15799 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
15687 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,15800 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
15688 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);15801 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec,
15802 nullptr, UndefBad);
15689 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,15803 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
15690 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);15804 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
15691 copy_const_val(&const_instruction->base.value, align_result, true);15805 copy_const_val(&const_instruction->base.value, align_result, true);
...@@ -16066,51 +16180,20 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -16066,51 +16180,20 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
16066 zig_unreachable();16180 zig_unreachable();
16067}16181}
1606816182
16069static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {16183static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *instruction) {
16070 Error err;16184 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
16071 IrInstruction *value = un_op_instruction->value->child;16185 result->value.special = ConstValSpecialLazy;
16072 ZigType *type_entry = ir_resolve_type(ira, value);
16073 if (type_is_invalid(type_entry))
16074 return ira->codegen->invalid_instruction;
16075 if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
16076 return ira->codegen->invalid_instruction;
1607716186
16078 switch (type_entry->id) {16187 LazyValueOptType *lazy_opt_type = allocate<LazyValueOptType>(1);
16079 case ZigTypeIdInvalid:16188 lazy_opt_type->ira = ira;
16080 zig_unreachable();16189 result->value.data.x_lazy = &lazy_opt_type->base;
16081 case ZigTypeIdMetaType:16190 lazy_opt_type->base.id = LazyValueIdOptType;
16082 case ZigTypeIdVoid:
16083 case ZigTypeIdBool:
16084 case ZigTypeIdInt:
16085 case ZigTypeIdVector:
16086 case ZigTypeIdFloat:
16087 case ZigTypeIdPointer:
16088 case ZigTypeIdArray:
16089 case ZigTypeIdStruct:
16090 case ZigTypeIdComptimeFloat:
16091 case ZigTypeIdComptimeInt:
16092 case ZigTypeIdEnumLiteral:
16093 case ZigTypeIdUndefined:
16094 case ZigTypeIdNull:
16095 case ZigTypeIdOptional:
16096 case ZigTypeIdErrorUnion:
16097 case ZigTypeIdErrorSet:
16098 case ZigTypeIdEnum:
16099 case ZigTypeIdUnion:
16100 case ZigTypeIdFn:
16101 case ZigTypeIdBoundFn:
16102 case ZigTypeIdArgTuple:
16103 case ZigTypeIdFnFrame:
16104 case ZigTypeIdAnyFrame:
16105 return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry));
1610616191
16107 case ZigTypeIdUnreachable:16192 lazy_opt_type->payload_type = instruction->value->child;
16108 case ZigTypeIdOpaque:16193 if (ir_resolve_type_lazy(ira, lazy_opt_type->payload_type) == nullptr)
16109 ir_add_error_node(ira, un_op_instruction->base.source_node,16194 return ira->codegen->invalid_instruction;
16110 buf_sprintf("type '%s' not optional", buf_ptr(&type_entry->name)));16195
16111 return ira->codegen->invalid_instruction;16196 return result;
16112 }
16113 zig_unreachable();
16114}16197}
1611516198
16116static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *scalar_type,16199static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *scalar_type,
...@@ -16727,14 +16810,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -16727,14 +16810,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
16727 return ira->codegen->invalid_instruction;16810 return ira->codegen->invalid_instruction;
1672816811
16729 bool safety_check_on = elem_ptr_instruction->safety_check_on;16812 bool safety_check_on = elem_ptr_instruction->safety_check_on;
16730 if ((err = ensure_complete_type(ira->codegen, return_type->data.pointer.child_type)))16813 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))
16731 return ira->codegen->invalid_instruction;16814 return ira->codegen->invalid_instruction;
1673216815
16733 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);16816 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
16734 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);16817 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
16735 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);16818 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
16736 if (instr_is_comptime(casted_elem_index)) {16819 if (instr_is_comptime(casted_elem_index)) {
16737 uint64_t index = bigint_as_unsigned(&casted_elem_index->value.data.x_bigint);16820 uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);
16738 if (array_type->id == ZigTypeIdArray) {16821 if (array_type->id == ZigTypeIdArray) {
16739 uint64_t array_len = array_type->data.array.len;16822 uint64_t array_len = array_type->data.array.len;
16740 if (index >= array_len) {16823 if (index >= array_len) {
...@@ -16896,7 +16979,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -16896,7 +16979,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
16896 ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];16979 ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
16897 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);16980 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
16898 ConstExprValue *out_val = &result->value;16981 ConstExprValue *out_val = &result->value;
16899 uint64_t slice_len = bigint_as_unsigned(&len_field->data.x_bigint);16982 uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint);
16900 if (index >= slice_len) {16983 if (index >= slice_len) {
16901 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,16984 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
16902 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,16985 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
...@@ -17005,7 +17088,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,...@@ -17005,7 +17088,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
17005 auto entry = container_scope->decl_table.maybe_get(field_name);17088 auto entry = container_scope->decl_table.maybe_get(field_name);
17006 Tld *tld = entry ? entry->value : nullptr;17089 Tld *tld = entry ? entry->value : nullptr;
17007 if (tld && tld->id == TldIdFn) {17090 if (tld && tld->id == TldIdFn) {
17008 resolve_top_level_decl(ira->codegen, tld, source_instr->source_node);17091 resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false);
17009 if (tld->resolution == TldResolutionInvalid)17092 if (tld->resolution == TldResolutionInvalid)
17010 return ira->codegen->invalid_instruction;17093 return ira->codegen->invalid_instruction;
17011 TldFn *tld_fn = (TldFn *)tld;17094 TldFn *tld_fn = (TldFn *)tld;
...@@ -17038,27 +17121,31 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,...@@ -17038,27 +17121,31 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
17038static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,17121static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,
17039 TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)17122 TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)
17040{17123{
17041 switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {17124 Error err;
17125 ZigType *field_type = resolve_struct_field_type(ira->codegen, field);
17126 if (field_type == nullptr)
17127 return ira->codegen->invalid_instruction;
17128 switch (type_has_one_possible_value(ira->codegen, field_type)) {
17042 case OnePossibleValueInvalid:17129 case OnePossibleValueInvalid:
17043 return ira->codegen->invalid_instruction;17130 return ira->codegen->invalid_instruction;
17044 case OnePossibleValueYes: {17131 case OnePossibleValueYes: {
17045 IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);17132 IrInstruction *elem = ir_const(ira, source_instr, field_type);
17046 return ir_get_ref(ira, source_instr, elem, false, false);17133 return ir_get_ref(ira, source_instr, elem, false, false);
17047 }17134 }
17048 case OnePossibleValueNo:17135 case OnePossibleValueNo:
17049 break;17136 break;
17050 }17137 }
17138 if ((err = type_resolve(ira->codegen, struct_type, ResolveStatusAlignmentKnown)))
17139 return ira->codegen->invalid_instruction;
17051 assert(struct_ptr->value.type->id == ZigTypeIdPointer);17140 assert(struct_ptr->value.type->id == ZigTypeIdPointer);
17052 bool is_packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
17053 uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
17054 uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;17141 uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host;
17055 uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;17142 uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes;
17056 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?17143 uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ?
17057 get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;17144 get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes;
17058 bool is_const = struct_ptr->value.type->data.pointer.is_const;17145 bool is_const = struct_ptr->value.type->data.pointer.is_const;
17059 bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;17146 bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile;
17060 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,17147 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
17061 is_const, is_volatile, PtrLenSingle, align_bytes,17148 is_const, is_volatile, PtrLenSingle, field->align,
17062 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),17149 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
17063 (uint32_t)host_int_bytes_for_result_type, false);17150 (uint32_t)host_int_bytes_for_result_type, false);
17064 if (instr_is_comptime(struct_ptr)) {17151 if (instr_is_comptime(struct_ptr)) {
...@@ -17113,7 +17200,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -17113,7 +17200,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
17113 Error err;17200 Error err;
1711417201
17115 ZigType *bare_type = container_ref_type(container_type);17202 ZigType *bare_type = container_ref_type(container_type);
17116 if ((err = ensure_complete_type(ira->codegen, bare_type)))17203 if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusSizeKnown)))
17117 return ira->codegen->invalid_instruction;17204 return ira->codegen->invalid_instruction;
1711817205
17119 assert(container_ptr->value.type->id == ZigTypeIdPointer);17206 assert(container_ptr->value.type->id == ZigTypeIdPointer);
...@@ -17243,23 +17330,22 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,...@@ -17243,23 +17330,22 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name,
17243}17330}
1724417331
17245static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) {17332static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) {
17246 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));17333 ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected"));
17247 emit_error_notes_for_ref_stack(ira->codegen, msg);
17248 return ira->codegen->invalid_instruction;17334 return ira->codegen->invalid_instruction;
17249}17335}
1725017336
17251static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {17337static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) {
17252 resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node);17338 resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node, true);
17253 if (tld->resolution == TldResolutionInvalid)17339 if (tld->resolution == TldResolutionInvalid) {
17254 return ira->codegen->invalid_instruction;17340 return ira->codegen->invalid_instruction;
17341 }
1725517342
17256 switch (tld->id) {17343 switch (tld->id) {
17257 case TldIdContainer:17344 case TldIdContainer:
17258 case TldIdCompTime:17345 case TldIdCompTime:
17259 case TldIdUsingNamespace:17346 case TldIdUsingNamespace:
17260 zig_unreachable();17347 zig_unreachable();
17261 case TldIdVar:17348 case TldIdVar: {
17262 {
17263 TldVar *tld_var = (TldVar *)tld;17349 TldVar *tld_var = (TldVar *)tld;
17264 ZigVar *var = tld_var->var;17350 ZigVar *var = tld_var->var;
17265 if (var == nullptr) {17351 if (var == nullptr) {
...@@ -17271,8 +17357,7 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_...@@ -17271,8 +17357,7 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_
1727117357
17272 return ir_get_var_ptr(ira, source_instruction, var);17358 return ir_get_var_ptr(ira, source_instruction, var);
17273 }17359 }
17274 case TldIdFn:17360 case TldIdFn: {
17275 {
17276 TldFn *tld_fn = (TldFn *)tld;17361 TldFn *tld_fn = (TldFn *)tld;
17277 ZigFn *fn_entry = tld_fn->fn_entry;17362 ZigFn *fn_entry = tld_fn->fn_entry;
17278 assert(fn_entry->type_entry);17363 assert(fn_entry->type_entry);
...@@ -17396,7 +17481,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -17396,7 +17481,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
17396 return ira->codegen->invalid_instruction;17481 return ira->codegen->invalid_instruction;
17397 } else if (is_container(child_type)) {17482 } else if (is_container(child_type)) {
17398 if (child_type->id == ZigTypeIdEnum) {17483 if (child_type->id == ZigTypeIdEnum) {
17399 if ((err = ensure_complete_type(ira->codegen, child_type)))17484 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
17400 return ira->codegen->invalid_instruction;17485 return ira->codegen->invalid_instruction;
1740117486
17402 TypeEnumField *field = find_enum_type_field(child_type, field_name);17487 TypeEnumField *field = find_enum_type_field(child_type, field_name);
...@@ -17425,7 +17510,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -17425,7 +17510,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
17425 (child_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr ||17510 (child_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr ||
17426 child_type->data.unionation.decl_node->data.container_decl.auto_enum))17511 child_type->data.unionation.decl_node->data.container_decl.auto_enum))
17427 {17512 {
17428 if ((err = ensure_complete_type(ira->codegen, child_type)))17513 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
17429 return ira->codegen->invalid_instruction;17514 return ira->codegen->invalid_instruction;
17430 TypeUnionField *field = find_union_type_field(child_type, field_name);17515 TypeUnionField *field = find_union_type_field(child_type, field_name);
17431 if (field) {17516 if (field) {
...@@ -17844,65 +17929,29 @@ static IrInstruction *ir_analyze_instruction_any_frame_type(IrAnalyze *ira,...@@ -17844,65 +17929,29 @@ static IrInstruction *ir_analyze_instruction_any_frame_type(IrAnalyze *ira,
17844static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,17929static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
17845 IrInstructionSliceType *slice_type_instruction)17930 IrInstructionSliceType *slice_type_instruction)
17846{17931{
17847 Error err;17932 IrInstruction *result = ir_const(ira, &slice_type_instruction->base, ira->codegen->builtin_types.entry_type);
17848 uint32_t align_bytes = 0;17933 result->value.special = ConstValSpecialLazy;
17934
17935 LazyValueSliceType *lazy_slice_type = allocate<LazyValueSliceType>(1);
17936 lazy_slice_type->ira = ira;
17937 result->value.data.x_lazy = &lazy_slice_type->base;
17938 lazy_slice_type->base.id = LazyValueIdSliceType;
17939
17849 if (slice_type_instruction->align_value != nullptr) {17940 if (slice_type_instruction->align_value != nullptr) {
17850 if (!ir_resolve_align(ira, slice_type_instruction->align_value->child, &align_bytes))17941 lazy_slice_type->align_inst = slice_type_instruction->align_value->child;
17942 if (ir_resolve_const(ira, lazy_slice_type->align_inst, LazyOk) == nullptr)
17851 return ira->codegen->invalid_instruction;17943 return ira->codegen->invalid_instruction;
17852 }17944 }
1785317945
17854 ZigType *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->child);17946 lazy_slice_type->elem_type = slice_type_instruction->child_type->child;
17855 if (type_is_invalid(child_type))17947 if (ir_resolve_type_lazy(ira, lazy_slice_type->elem_type) == nullptr)
17856 return ira->codegen->invalid_instruction;17948 return ira->codegen->invalid_instruction;
1785717949
17858 bool is_const = slice_type_instruction->is_const;17950 lazy_slice_type->is_const = slice_type_instruction->is_const;
17859 bool is_volatile = slice_type_instruction->is_volatile;17951 lazy_slice_type->is_volatile = slice_type_instruction->is_volatile;
17860 bool is_allow_zero = slice_type_instruction->is_allow_zero;17952 lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero;
1786117953
17862 switch (child_type->id) {17954 return result;
17863 case ZigTypeIdInvalid: // handled above
17864 zig_unreachable();
17865 case ZigTypeIdUnreachable:
17866 case ZigTypeIdUndefined:
17867 case ZigTypeIdNull:
17868 case ZigTypeIdArgTuple:
17869 case ZigTypeIdOpaque:
17870 ir_add_error_node(ira, slice_type_instruction->base.source_node,
17871 buf_sprintf("slice of type '%s' not allowed", buf_ptr(&child_type->name)));
17872 return ira->codegen->invalid_instruction;
17873 case ZigTypeIdMetaType:
17874 case ZigTypeIdVoid:
17875 case ZigTypeIdBool:
17876 case ZigTypeIdInt:
17877 case ZigTypeIdFloat:
17878 case ZigTypeIdPointer:
17879 case ZigTypeIdArray:
17880 case ZigTypeIdStruct:
17881 case ZigTypeIdComptimeFloat:
17882 case ZigTypeIdComptimeInt:
17883 case ZigTypeIdEnumLiteral:
17884 case ZigTypeIdOptional:
17885 case ZigTypeIdErrorUnion:
17886 case ZigTypeIdErrorSet:
17887 case ZigTypeIdEnum:
17888 case ZigTypeIdUnion:
17889 case ZigTypeIdFn:
17890 case ZigTypeIdBoundFn:
17891 case ZigTypeIdVector:
17892 case ZigTypeIdFnFrame:
17893 case ZigTypeIdAnyFrame:
17894 {
17895 ResolveStatus needed_status = (align_bytes == 0) ?
17896 ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
17897 if ((err = type_resolve(ira->codegen, child_type, needed_status)))
17898 return ira->codegen->invalid_instruction;
17899 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
17900 is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0, is_allow_zero);
17901 ZigType *result_type = get_slice_type(ira->codegen, slice_ptr_type);
17902 return ir_const_type(ira, &slice_type_instruction->base, result_type);
17903 }
17904 }
17905 zig_unreachable();
17906}17955}
1790717956
17908static IrInstruction *ir_analyze_instruction_global_asm(IrAnalyze *ira, IrInstructionGlobalAsm *instruction) {17957static IrInstruction *ir_analyze_instruction_global_asm(IrAnalyze *ira, IrInstructionGlobalAsm *instruction) {
...@@ -18008,7 +18057,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -18008,7 +18057,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
18008 case ZigTypeIdFnFrame:18057 case ZigTypeIdFnFrame:
18009 case ZigTypeIdAnyFrame:18058 case ZigTypeIdAnyFrame:
18010 {18059 {
18011 if ((err = ensure_complete_type(ira->codegen, child_type)))18060 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
18012 return ira->codegen->invalid_instruction;18061 return ira->codegen->invalid_instruction;
18013 ZigType *result_type = get_array_type(ira->codegen, child_type, size);18062 ZigType *result_type = get_array_type(ira->codegen, child_type, size);
18014 return ir_const_type(ira, &array_type_instruction->base, result_type);18063 return ir_const_type(ira, &array_type_instruction->base, result_type);
...@@ -18024,7 +18073,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -18024,7 +18073,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
18024 IrInstruction *type_value = size_of_instruction->type_value->child;18073 IrInstruction *type_value = size_of_instruction->type_value->child;
18025 ZigType *type_entry = ir_resolve_type(ira, type_value);18074 ZigType *type_entry = ir_resolve_type(ira, type_value);
1802618075
18027 if ((err = ensure_complete_type(ira->codegen, type_entry)))18076 if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
18028 return ira->codegen->invalid_instruction;18077 return ira->codegen->invalid_instruction;
1802918078
18030 switch (type_entry->id) {18079 switch (type_entry->id) {
...@@ -18529,7 +18578,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -18529,7 +18578,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
18529 if (pointee_val->special == ConstValSpecialRuntime)18578 if (pointee_val->special == ConstValSpecialRuntime)
18530 pointee_val = nullptr;18579 pointee_val = nullptr;
18531 }18580 }
18532 if ((err = ensure_complete_type(ira->codegen, target_type)))18581 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusSizeKnown)))
18533 return ira->codegen->invalid_instruction;18582 return ira->codegen->invalid_instruction;
1853418583
18535 switch (target_type->id) {18584 switch (target_type->id) {
...@@ -19070,7 +19119,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -19070,7 +19119,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
19070 Scope *analyze_scope = &get_container_scope(container_type)->base;19119 Scope *analyze_scope = &get_container_scope(container_type)->base;
19071 // memoize it19120 // memoize it
19072 field->init_val = analyze_const_value(ira->codegen, analyze_scope, init_node,19121 field->init_val = analyze_const_value(ira->codegen, analyze_scope, init_node,
19073 field->type_entry, nullptr);19122 field->type_entry, nullptr, UndefOk);
19074 }19123 }
19075 if (type_is_invalid(field->init_val->type))19124 if (type_is_invalid(field->init_val->type))
19076 return ira->codegen->invalid_instruction;19125 return ira->codegen->invalid_instruction;
...@@ -19276,8 +19325,7 @@ static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,...@@ -19276,8 +19325,7 @@ static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira,
19276 if (!msg_buf)19325 if (!msg_buf)
19277 return ira->codegen->invalid_instruction;19326 return ira->codegen->invalid_instruction;
1927819327
19279 ErrorMsg *msg = ir_add_error(ira, &instruction->base, msg_buf);19328 ir_add_error(ira, &instruction->base, msg_buf);
19280 emit_error_notes_for_ref_stack(ira->codegen, msg);
1928119329
19282 return ira->codegen->invalid_instruction;19330 return ira->codegen->invalid_instruction;
19283}19331}
...@@ -19319,7 +19367,10 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct...@@ -19319,7 +19367,10 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
19319 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,19367 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
19320 true, false, PtrLenUnknown, 0, 0, 0, false);19368 true, false, PtrLenUnknown, 0, 0, 0, false);
19321 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);19369 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
19322 if (casted_value->value.special == ConstValSpecialStatic) {19370 if (instr_is_comptime(casted_value)) {
19371 ConstExprValue *val = ir_resolve_const(ira, casted_value, UndefBad);
19372 if (val == nullptr)
19373 return ira->codegen->invalid_instruction;
19323 ErrorTableEntry *err = casted_value->value.data.x_err_set;19374 ErrorTableEntry *err = casted_value->value.data.x_err_set;
19324 if (!err->cached_error_name_val) {19375 if (!err->cached_error_name_val) {
19325 ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name);19376 ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name);
...@@ -19391,7 +19442,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,...@@ -19391,7 +19442,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
19391 return ira->codegen->invalid_instruction;19442 return ira->codegen->invalid_instruction;
19392 }19443 }
1939319444
19394 if ((err = ensure_complete_type(ira->codegen, container_type)))19445 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
19395 return ira->codegen->invalid_instruction;19446 return ira->codegen->invalid_instruction;
1939619447
19397 TypeStructField *field = find_struct_type_field(container_type, field_name);19448 TypeStructField *field = find_struct_type_field(container_type, field_name);
...@@ -19470,7 +19521,7 @@ static TypeStructField *validate_byte_offset(IrAnalyze *ira,...@@ -19470,7 +19521,7 @@ static TypeStructField *validate_byte_offset(IrAnalyze *ira,
19470 return nullptr;19521 return nullptr;
1947119522
19472 Error err;19523 Error err;
19473 if ((err = ensure_complete_type(ira->codegen, container_type)))19524 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
19474 return nullptr;19525 return nullptr;
1947519526
19476 Buf *field_name = ir_resolve_str(ira, field_name_value);19527 Buf *field_name = ir_resolve_str(ira, field_name_value);
...@@ -19574,11 +19625,9 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig...@@ -19574,11 +19625,9 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
1957419625
19575 ZigVar *var = tld->var;19626 ZigVar *var = tld->var;
1957619627
19577 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
19578 return ira->codegen->builtin_types.entry_invalid;
19579
19580 assert(var->const_value->type->id == ZigTypeIdMetaType);19628 assert(var->const_value->type->id == ZigTypeIdMetaType);
19581 return var->const_value->data.x_type;19629
19630 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, nullptr, var->const_value);
19582}19631}
1958319632
19584static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *out_val,19633static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *out_val,
...@@ -19594,15 +19643,15 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -19594,15 +19643,15 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
19594 ensure_field_index(type_info_declaration_type, "data", 2);19643 ensure_field_index(type_info_declaration_type, "data", 2);
1959519644
19596 ZigType *type_info_declaration_data_type = ir_type_info_get_type(ira, "Data", type_info_declaration_type);19645 ZigType *type_info_declaration_data_type = ir_type_info_get_type(ira, "Data", type_info_declaration_type);
19597 if ((err = ensure_complete_type(ira->codegen, type_info_declaration_data_type)))19646 if ((err = type_resolve(ira->codegen, type_info_declaration_data_type, ResolveStatusSizeKnown)))
19598 return err;19647 return err;
1959919648
19600 ZigType *type_info_fn_decl_type = ir_type_info_get_type(ira, "FnDecl", type_info_declaration_data_type);19649 ZigType *type_info_fn_decl_type = ir_type_info_get_type(ira, "FnDecl", type_info_declaration_data_type);
19601 if ((err = ensure_complete_type(ira->codegen, type_info_fn_decl_type)))19650 if ((err = type_resolve(ira->codegen, type_info_fn_decl_type, ResolveStatusSizeKnown)))
19602 return err;19651 return err;
1960319652
19604 ZigType *type_info_fn_decl_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_decl_type);19653 ZigType *type_info_fn_decl_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_decl_type);
19605 if ((err = ensure_complete_type(ira->codegen, type_info_fn_decl_inline_type)))19654 if ((err = type_resolve(ira->codegen, type_info_fn_decl_inline_type, ResolveStatusSizeKnown)))
19606 return err;19655 return err;
1960719656
19608 // Loop through our declarations once to figure out how many declarations we will generate info for.19657 // Loop through our declarations once to figure out how many declarations we will generate info for.
...@@ -19613,7 +19662,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -19613,7 +19662,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
19613 while ((curr_entry = decl_it.next()) != nullptr) {19662 while ((curr_entry = decl_it.next()) != nullptr) {
19614 // If the declaration is unresolved, force it to be resolved again.19663 // If the declaration is unresolved, force it to be resolved again.
19615 if (curr_entry->value->resolution == TldResolutionUnresolved) {19664 if (curr_entry->value->resolution == TldResolutionUnresolved) {
19616 resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node);19665 resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false);
19617 if (curr_entry->value->resolution != TldResolutionOk) {19666 if (curr_entry->value->resolution != TldResolutionOk) {
19618 return ErrorSemanticAnalyzeFail;19667 return ErrorSemanticAnalyzeFail;
19619 }19668 }
...@@ -19673,7 +19722,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -19673,7 +19722,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
19673 case TldIdVar:19722 case TldIdVar:
19674 {19723 {
19675 ZigVar *var = ((TldVar *)curr_entry->value)->var;19724 ZigVar *var = ((TldVar *)curr_entry->value)->var;
19676 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))19725 if ((err = type_resolve(ira->codegen, var->const_value->type, ResolveStatusSizeKnown)))
19677 return ErrorSemanticAnalyzeFail;19726 return ErrorSemanticAnalyzeFail;
1967819727
19679 if (var->const_value->type->id == ZigTypeIdMetaType) {19728 if (var->const_value->type->id == ZigTypeIdMetaType) {
...@@ -19799,7 +19848,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -19799,7 +19848,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
19799 case TldIdContainer:19848 case TldIdContainer:
19800 {19849 {
19801 ZigType *type_entry = ((TldContainer *)curr_entry->value)->type_entry;19850 ZigType *type_entry = ((TldContainer *)curr_entry->value)->type_entry;
19802 if ((err = ensure_complete_type(ira->codegen, type_entry)))19851 if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
19803 return ErrorSemanticAnalyzeFail;19852 return ErrorSemanticAnalyzeFail;
1980419853
19805 // This is a type.19854 // This is a type.
...@@ -19855,7 +19904,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -19855,7 +19904,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
19855 return nullptr;19904 return nullptr;
1985619905
19857 ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr);19906 ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr);
19858 assertNoError(ensure_complete_type(ira->codegen, type_info_pointer_type));19907 assertNoError(type_resolve(ira->codegen, type_info_pointer_type, ResolveStatusSizeKnown));
1985919908
19860 ConstExprValue *result = create_const_vals(1);19909 ConstExprValue *result = create_const_vals(1);
19861 result->special = ConstValSpecialStatic;19910 result->special = ConstValSpecialStatic;
...@@ -19867,7 +19916,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -19867,7 +19916,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
19867 // size: Size19916 // size: Size
19868 ensure_field_index(result->type, "size", 0);19917 ensure_field_index(result->type, "size", 0);
19869 ZigType *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type);19918 ZigType *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type);
19870 assertNoError(ensure_complete_type(ira->codegen, type_info_pointer_size_type));19919 assertNoError(type_resolve(ira->codegen, type_info_pointer_size_type, ResolveStatusSizeKnown));
19871 fields[0].special = ConstValSpecialStatic;19920 fields[0].special = ConstValSpecialStatic;
19872 fields[0].type = type_info_pointer_size_type;19921 fields[0].type = type_info_pointer_size_type;
19873 bigint_init_unsigned(&fields[0].data.x_enum_tag, size_enum_index);19922 bigint_init_unsigned(&fields[0].data.x_enum_tag, size_enum_index);
...@@ -20345,6 +20394,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -20345,6 +20394,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
20345 inner_fields[1].special = ConstValSpecialStatic;20394 inner_fields[1].special = ConstValSpecialStatic;
20346 inner_fields[1].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int);20395 inner_fields[1].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int);
2034720396
20397 ZigType *field_type = resolve_struct_field_type(ira->codegen, struct_field);
20398 if (field_type == nullptr)
20399 return ErrorSemanticAnalyzeFail;
20400 if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown)))
20401 return err;
20348 if (!type_has_bits(struct_field->type_entry)) {20402 if (!type_has_bits(struct_field->type_entry)) {
20349 inner_fields[1].data.x_optional = nullptr;20403 inner_fields[1].data.x_optional = nullptr;
20350 } else {20404 } else {
...@@ -20581,7 +20635,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -20581,7 +20635,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
20581 ZigType *void_type = ira->codegen->builtin_types.entry_void;20635 ZigType *void_type = ira->codegen->builtin_types.entry_void;
20582 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,20636 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
20583 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,20637 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
20584 &cimport_scope->buf, block_node, nullptr, nullptr, nullptr);20638 &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, UndefBad);
20585 if (type_is_invalid(cimport_result->type))20639 if (type_is_invalid(cimport_result->type))
20586 return ira->codegen->invalid_instruction;20640 return ira->codegen->invalid_instruction;
2058720641
...@@ -21181,7 +21235,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru...@@ -21181,7 +21235,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
2118121235
21182 ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index];21236 ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index];
21183 if (value_is_comptime(len_val)) {21237 if (value_is_comptime(len_val)) {
21184 known_len = bigint_as_unsigned(&len_val->data.x_bigint);21238 known_len = bigint_as_u64(&len_val->data.x_bigint);
21185 have_known_len = true;21239 have_known_len = true;
21186 }21240 }
21187 }21241 }
...@@ -21482,64 +21536,75 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio...@@ -21482,64 +21536,75 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
21482 return ira->codegen->invalid_instruction;21536 return ira->codegen->invalid_instruction;
2148321537
21484 // TODO test this at comptime with u8 and non-u8 types21538 // TODO test this at comptime with u8 and non-u8 types
21485 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&21539 if (instr_is_comptime(casted_dest_ptr) &&
21486 casted_byte->value.special == ConstValSpecialStatic &&21540 instr_is_comptime(casted_byte) &&
21487 casted_count->value.special == ConstValSpecialStatic &&21541 instr_is_comptime(casted_count))
21488 casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
21489 casted_dest_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
21490 {21542 {
21491 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;21543 ConstExprValue *dest_ptr_val = ir_resolve_const(ira, casted_dest_ptr, UndefBad);
21544 if (dest_ptr_val == nullptr)
21545 return ira->codegen->invalid_instruction;
2149221546
21493 ConstExprValue *dest_elements;21547 ConstExprValue *byte_val = ir_resolve_const(ira, casted_byte, UndefOk);
21494 size_t start;21548 if (byte_val == nullptr)
21495 size_t bound_end;21549 return ira->codegen->invalid_instruction;
21496 switch (dest_ptr_val->data.x_ptr.special) {
21497 case ConstPtrSpecialInvalid:
21498 case ConstPtrSpecialDiscard:
21499 zig_unreachable();
21500 case ConstPtrSpecialRef:
21501 dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee;
21502 start = 0;
21503 bound_end = 1;
21504 break;
21505 case ConstPtrSpecialBaseArray:
21506 {
21507 ConstExprValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
21508 expand_undef_array(ira->codegen, array_val);
21509 dest_elements = array_val->data.x_array.data.s_none.elements;
21510 start = dest_ptr_val->data.x_ptr.data.base_array.elem_index;
21511 bound_end = array_val->type->data.array.len;
21512 break;
21513 }
21514 case ConstPtrSpecialBaseStruct:
21515 zig_panic("TODO memset on const inner struct");
21516 case ConstPtrSpecialBaseErrorUnionCode:
21517 zig_panic("TODO memset on const inner error union code");
21518 case ConstPtrSpecialBaseErrorUnionPayload:
21519 zig_panic("TODO memset on const inner error union payload");
21520 case ConstPtrSpecialBaseOptionalPayload:
21521 zig_panic("TODO memset on const inner optional payload");
21522 case ConstPtrSpecialHardCodedAddr:
21523 zig_unreachable();
21524 case ConstPtrSpecialFunction:
21525 zig_panic("TODO memset on ptr cast from function");
21526 case ConstPtrSpecialNull:
21527 zig_panic("TODO memset on null ptr");
21528 }
2152921550
21530 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);21551 ConstExprValue *count_val = ir_resolve_const(ira, casted_count, UndefBad);
21531 size_t end = start + count;21552 if (count_val == nullptr)
21532 if (end > bound_end) {
21533 ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access"));
21534 return ira->codegen->invalid_instruction;21553 return ira->codegen->invalid_instruction;
21535 }
2153621554
21537 ConstExprValue *byte_val = &casted_byte->value;21555 if (casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
21538 for (size_t i = start; i < end; i += 1) {21556 casted_dest_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
21539 copy_const_val(&dest_elements[i], byte_val, true);21557 {
21540 }21558 ConstExprValue *dest_elements;
21559 size_t start;
21560 size_t bound_end;
21561 switch (dest_ptr_val->data.x_ptr.special) {
21562 case ConstPtrSpecialInvalid:
21563 case ConstPtrSpecialDiscard:
21564 zig_unreachable();
21565 case ConstPtrSpecialRef:
21566 dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee;
21567 start = 0;
21568 bound_end = 1;
21569 break;
21570 case ConstPtrSpecialBaseArray:
21571 {
21572 ConstExprValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
21573 expand_undef_array(ira->codegen, array_val);
21574 dest_elements = array_val->data.x_array.data.s_none.elements;
21575 start = dest_ptr_val->data.x_ptr.data.base_array.elem_index;
21576 bound_end = array_val->type->data.array.len;
21577 break;
21578 }
21579 case ConstPtrSpecialBaseStruct:
21580 zig_panic("TODO memset on const inner struct");
21581 case ConstPtrSpecialBaseErrorUnionCode:
21582 zig_panic("TODO memset on const inner error union code");
21583 case ConstPtrSpecialBaseErrorUnionPayload:
21584 zig_panic("TODO memset on const inner error union payload");
21585 case ConstPtrSpecialBaseOptionalPayload:
21586 zig_panic("TODO memset on const inner optional payload");
21587 case ConstPtrSpecialHardCodedAddr:
21588 zig_unreachable();
21589 case ConstPtrSpecialFunction:
21590 zig_panic("TODO memset on ptr cast from function");
21591 case ConstPtrSpecialNull:
21592 zig_panic("TODO memset on null ptr");
21593 }
2154121594
21542 return ir_const_void(ira, &instruction->base);21595 size_t count = bigint_as_usize(&count_val->data.x_bigint);
21596 size_t end = start + count;
21597 if (end > bound_end) {
21598 ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access"));
21599 return ira->codegen->invalid_instruction;
21600 }
21601
21602 for (size_t i = start; i < end; i += 1) {
21603 copy_const_val(&dest_elements[i], byte_val, true);
21604 }
21605
21606 return ir_const_void(ira, &instruction->base);
21607 }
21543 }21608 }
2154421609
21545 IrInstruction *result = ir_build_memset(&ira->new_irb, instruction->base.scope, instruction->base.source_node,21610 IrInstruction *result = ir_build_memset(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
...@@ -21607,107 +21672,118 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -21607,107 +21672,118 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
2160721672
21608 // TODO test this at comptime with u8 and non-u8 types21673 // TODO test this at comptime with u8 and non-u8 types
21609 // TODO test with dest ptr being a global runtime variable21674 // TODO test with dest ptr being a global runtime variable
21610 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&21675 if (instr_is_comptime(casted_dest_ptr) &&
21611 casted_src_ptr->value.special == ConstValSpecialStatic &&21676 instr_is_comptime(casted_src_ptr) &&
21612 casted_count->value.special == ConstValSpecialStatic &&21677 instr_is_comptime(casted_count))
21613 casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
21614 {21678 {
21615 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);21679 ConstExprValue *dest_ptr_val = ir_resolve_const(ira, casted_dest_ptr, UndefBad);
21680 if (dest_ptr_val == nullptr)
21681 return ira->codegen->invalid_instruction;
2161621682
21617 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;21683 ConstExprValue *src_ptr_val = ir_resolve_const(ira, casted_src_ptr, UndefBad);
21618 ConstExprValue *dest_elements;21684 if (src_ptr_val == nullptr)
21619 size_t dest_start;21685 return ira->codegen->invalid_instruction;
21620 size_t dest_end;
21621 switch (dest_ptr_val->data.x_ptr.special) {
21622 case ConstPtrSpecialInvalid:
21623 case ConstPtrSpecialDiscard:
21624 zig_unreachable();
21625 case ConstPtrSpecialRef:
21626 dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee;
21627 dest_start = 0;
21628 dest_end = 1;
21629 break;
21630 case ConstPtrSpecialBaseArray:
21631 {
21632 ConstExprValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
21633 expand_undef_array(ira->codegen, array_val);
21634 dest_elements = array_val->data.x_array.data.s_none.elements;
21635 dest_start = dest_ptr_val->data.x_ptr.data.base_array.elem_index;
21636 dest_end = array_val->type->data.array.len;
21637 break;
21638 }
21639 case ConstPtrSpecialBaseStruct:
21640 zig_panic("TODO memcpy on const inner struct");
21641 case ConstPtrSpecialBaseErrorUnionCode:
21642 zig_panic("TODO memcpy on const inner error union code");
21643 case ConstPtrSpecialBaseErrorUnionPayload:
21644 zig_panic("TODO memcpy on const inner error union payload");
21645 case ConstPtrSpecialBaseOptionalPayload:
21646 zig_panic("TODO memcpy on const inner optional payload");
21647 case ConstPtrSpecialHardCodedAddr:
21648 zig_unreachable();
21649 case ConstPtrSpecialFunction:
21650 zig_panic("TODO memcpy on ptr cast from function");
21651 case ConstPtrSpecialNull:
21652 zig_panic("TODO memcpy on null ptr");
21653 }
2165421686
21655 if (dest_start + count > dest_end) {21687 ConstExprValue *count_val = ir_resolve_const(ira, casted_count, UndefBad);
21656 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access"));21688 if (count_val == nullptr)
21657 return ira->codegen->invalid_instruction;21689 return ira->codegen->invalid_instruction;
21658 }
2165921690
21660 ConstExprValue *src_ptr_val = &casted_src_ptr->value;21691 if (dest_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
21661 ConstExprValue *src_elements;21692 size_t count = bigint_as_usize(&count_val->data.x_bigint);
21662 size_t src_start;
21663 size_t src_end;
2166421693
21665 switch (src_ptr_val->data.x_ptr.special) {21694 ConstExprValue *dest_elements;
21666 case ConstPtrSpecialInvalid:21695 size_t dest_start;
21667 case ConstPtrSpecialDiscard:21696 size_t dest_end;
21668 zig_unreachable();21697 switch (dest_ptr_val->data.x_ptr.special) {
21669 case ConstPtrSpecialRef:21698 case ConstPtrSpecialInvalid:
21670 src_elements = src_ptr_val->data.x_ptr.data.ref.pointee;21699 case ConstPtrSpecialDiscard:
21671 src_start = 0;21700 zig_unreachable();
21672 src_end = 1;21701 case ConstPtrSpecialRef:
21673 break;21702 dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee;
21674 case ConstPtrSpecialBaseArray:21703 dest_start = 0;
21675 {21704 dest_end = 1;
21676 ConstExprValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val;
21677 expand_undef_array(ira->codegen, array_val);
21678 src_elements = array_val->data.x_array.data.s_none.elements;
21679 src_start = src_ptr_val->data.x_ptr.data.base_array.elem_index;
21680 src_end = array_val->type->data.array.len;
21681 break;21705 break;
21682 }21706 case ConstPtrSpecialBaseArray:
21683 case ConstPtrSpecialBaseStruct:21707 {
21684 zig_panic("TODO memcpy on const inner struct");21708 ConstExprValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
21685 case ConstPtrSpecialBaseErrorUnionCode:21709 expand_undef_array(ira->codegen, array_val);
21686 zig_panic("TODO memcpy on const inner error union code");21710 dest_elements = array_val->data.x_array.data.s_none.elements;
21687 case ConstPtrSpecialBaseErrorUnionPayload:21711 dest_start = dest_ptr_val->data.x_ptr.data.base_array.elem_index;
21688 zig_panic("TODO memcpy on const inner error union payload");21712 dest_end = array_val->type->data.array.len;
21689 case ConstPtrSpecialBaseOptionalPayload:21713 break;
21690 zig_panic("TODO memcpy on const inner optional payload");21714 }
21691 case ConstPtrSpecialHardCodedAddr:21715 case ConstPtrSpecialBaseStruct:
21692 zig_unreachable();21716 zig_panic("TODO memcpy on const inner struct");
21693 case ConstPtrSpecialFunction:21717 case ConstPtrSpecialBaseErrorUnionCode:
21694 zig_panic("TODO memcpy on ptr cast from function");21718 zig_panic("TODO memcpy on const inner error union code");
21695 case ConstPtrSpecialNull:21719 case ConstPtrSpecialBaseErrorUnionPayload:
21696 zig_panic("TODO memcpy on null ptr");21720 zig_panic("TODO memcpy on const inner error union payload");
21697 }21721 case ConstPtrSpecialBaseOptionalPayload:
21722 zig_panic("TODO memcpy on const inner optional payload");
21723 case ConstPtrSpecialHardCodedAddr:
21724 zig_unreachable();
21725 case ConstPtrSpecialFunction:
21726 zig_panic("TODO memcpy on ptr cast from function");
21727 case ConstPtrSpecialNull:
21728 zig_panic("TODO memcpy on null ptr");
21729 }
2169821730
21699 if (src_start + count > src_end) {21731 if (dest_start + count > dest_end) {
21700 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access"));21732 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access"));
21701 return ira->codegen->invalid_instruction;21733 return ira->codegen->invalid_instruction;
21702 }21734 }
2170321735
21704 // TODO check for noalias violations - this should be generalized to work for any function21736 ConstExprValue *src_elements;
21737 size_t src_start;
21738 size_t src_end;
2170521739
21706 for (size_t i = 0; i < count; i += 1) {21740 switch (src_ptr_val->data.x_ptr.special) {
21707 copy_const_val(&dest_elements[dest_start + i], &src_elements[src_start + i], true);21741 case ConstPtrSpecialInvalid:
21708 }21742 case ConstPtrSpecialDiscard:
21743 zig_unreachable();
21744 case ConstPtrSpecialRef:
21745 src_elements = src_ptr_val->data.x_ptr.data.ref.pointee;
21746 src_start = 0;
21747 src_end = 1;
21748 break;
21749 case ConstPtrSpecialBaseArray:
21750 {
21751 ConstExprValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val;
21752 expand_undef_array(ira->codegen, array_val);
21753 src_elements = array_val->data.x_array.data.s_none.elements;
21754 src_start = src_ptr_val->data.x_ptr.data.base_array.elem_index;
21755 src_end = array_val->type->data.array.len;
21756 break;
21757 }
21758 case ConstPtrSpecialBaseStruct:
21759 zig_panic("TODO memcpy on const inner struct");
21760 case ConstPtrSpecialBaseErrorUnionCode:
21761 zig_panic("TODO memcpy on const inner error union code");
21762 case ConstPtrSpecialBaseErrorUnionPayload:
21763 zig_panic("TODO memcpy on const inner error union payload");
21764 case ConstPtrSpecialBaseOptionalPayload:
21765 zig_panic("TODO memcpy on const inner optional payload");
21766 case ConstPtrSpecialHardCodedAddr:
21767 zig_unreachable();
21768 case ConstPtrSpecialFunction:
21769 zig_panic("TODO memcpy on ptr cast from function");
21770 case ConstPtrSpecialNull:
21771 zig_panic("TODO memcpy on null ptr");
21772 }
2170921773
21710 return ir_const_void(ira, &instruction->base);21774 if (src_start + count > src_end) {
21775 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access"));
21776 return ira->codegen->invalid_instruction;
21777 }
21778
21779 // TODO check for noalias violations - this should be generalized to work for any function
21780
21781 for (size_t i = 0; i < count; i += 1) {
21782 copy_const_val(&dest_elements[dest_start + i], &src_elements[src_start + i], true);
21783 }
21784
21785 return ir_const_void(ira, &instruction->base);
21786 }
21711 }21787 }
2171221788
21713 IrInstruction *result = ir_build_memcpy(&ira->new_irb, instruction->base.scope, instruction->base.source_node,21789 IrInstruction *result = ir_build_memcpy(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
...@@ -21877,6 +21953,11 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -21877,6 +21953,11 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
21877 if (slice_ptr == nullptr)21953 if (slice_ptr == nullptr)
21878 return ira->codegen->invalid_instruction;21954 return ira->codegen->invalid_instruction;
2187921955
21956 if (slice_ptr->special == ConstValSpecialUndef) {
21957 ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined"));
21958 return ira->codegen->invalid_instruction;
21959 }
21960
21880 parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index];21961 parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index];
21881 if (parent_ptr->special == ConstValSpecialUndef) {21962 if (parent_ptr->special == ConstValSpecialUndef) {
21882 ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined"));21963 ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined"));
...@@ -21897,7 +21978,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -21897,7 +21978,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
21897 case ConstPtrSpecialBaseArray:21978 case ConstPtrSpecialBaseArray:
21898 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;21979 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
21899 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;21980 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
21900 rel_end = bigint_as_unsigned(&len_val->data.x_bigint);21981 rel_end = bigint_as_usize(&len_val->data.x_bigint);
21901 break;21982 break;
21902 case ConstPtrSpecialBaseStruct:21983 case ConstPtrSpecialBaseStruct:
21903 zig_panic("TODO slice const inner struct");21984 zig_panic("TODO slice const inner struct");
...@@ -21910,7 +21991,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -21910,7 +21991,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
21910 case ConstPtrSpecialHardCodedAddr:21991 case ConstPtrSpecialHardCodedAddr:
21911 array_val = nullptr;21992 array_val = nullptr;
21912 abs_offset = 0;21993 abs_offset = 0;
21913 rel_end = bigint_as_unsigned(&len_val->data.x_bigint);21994 rel_end = bigint_as_usize(&len_val->data.x_bigint);
21914 break;21995 break;
21915 case ConstPtrSpecialFunction:21996 case ConstPtrSpecialFunction:
21916 zig_panic("TODO slice of slice cast from function");21997 zig_panic("TODO slice of slice cast from function");
...@@ -21921,7 +22002,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -21921,7 +22002,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
21921 zig_unreachable();22002 zig_unreachable();
21922 }22003 }
2192322004
21924 uint64_t start_scalar = bigint_as_unsigned(&casted_start->value.data.x_bigint);22005 uint64_t start_scalar = bigint_as_u64(&casted_start->value.data.x_bigint);
21925 if (!ptr_is_undef && start_scalar > rel_end) {22006 if (!ptr_is_undef && start_scalar > rel_end) {
21926 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));22007 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
21927 return ira->codegen->invalid_instruction;22008 return ira->codegen->invalid_instruction;
...@@ -21929,7 +22010,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -21929,7 +22010,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2192922010
21930 uint64_t end_scalar;22011 uint64_t end_scalar;
21931 if (end) {22012 if (end) {
21932 end_scalar = bigint_as_unsigned(&end->value.data.x_bigint);22013 end_scalar = bigint_as_u64(&end->value.data.x_bigint);
21933 } else {22014 } else {
21934 end_scalar = rel_end;22015 end_scalar = rel_end;
21935 }22016 }
...@@ -22021,7 +22102,7 @@ static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInst...@@ -22021,7 +22102,7 @@ static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInst
22021 return ira->codegen->invalid_instruction;22102 return ira->codegen->invalid_instruction;
22022 ZigType *container_type = ir_resolve_type(ira, container);22103 ZigType *container_type = ir_resolve_type(ira, container);
2202322104
22024 if ((err = ensure_complete_type(ira->codegen, container_type)))22105 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
22025 return ira->codegen->invalid_instruction;22106 return ira->codegen->invalid_instruction;
2202622107
22027 uint64_t result;22108 uint64_t result;
...@@ -22057,7 +22138,7 @@ static IrInstruction *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstr...@@ -22057,7 +22138,7 @@ static IrInstruction *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstr
22057 if (type_is_invalid(container_type))22138 if (type_is_invalid(container_type))
22058 return ira->codegen->invalid_instruction;22139 return ira->codegen->invalid_instruction;
2205922140
22060 if ((err = ensure_complete_type(ira->codegen, container_type)))22141 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
22061 return ira->codegen->invalid_instruction;22142 return ira->codegen->invalid_instruction;
2206222143
2206322144
...@@ -22100,7 +22181,7 @@ static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstr...@@ -22100,7 +22181,7 @@ static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstr
22100 if (type_is_invalid(container_type))22181 if (type_is_invalid(container_type))
22101 return ira->codegen->invalid_instruction;22182 return ira->codegen->invalid_instruction;
2210222183
22103 if ((err = ensure_complete_type(ira->codegen, container_type)))22184 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
22104 return ira->codegen->invalid_instruction;22185 return ira->codegen->invalid_instruction;
2210522186
22106 uint64_t member_index;22187 uint64_t member_index;
...@@ -22249,53 +22330,24 @@ static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstru...@@ -22249,53 +22330,24 @@ static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstru
22249}22330}
2225022331
22251static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {22332static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
22252 Error err;22333 // Here we create a lazy value in order to avoid resolving the alignment of the type
22253 IrInstruction *type_value = instruction->type_value->child;22334 // immediately. This avoids false positive dependency loops such as:
22254 if (type_is_invalid(type_value->value.type))22335 // const Node = struct {
22255 return ira->codegen->invalid_instruction;22336 // field: []align(@alignOf(Node)) Node,
22256 ZigType *type_entry = ir_resolve_type(ira, type_value);22337 // };
22338 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int);
22339 result->value.special = ConstValSpecialLazy;
22340
22341 LazyValueAlignOf *lazy_align_of = allocate<LazyValueAlignOf>(1);
22342 lazy_align_of->ira = ira;
22343 result->value.data.x_lazy = &lazy_align_of->base;
22344 lazy_align_of->base.id = LazyValueIdAlignOf;
2225722345
22258 if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusAlignmentKnown)))22346 lazy_align_of->target_type = instruction->type_value->child;
22347 if (ir_resolve_type_lazy(ira, lazy_align_of->target_type) == nullptr)
22259 return ira->codegen->invalid_instruction;22348 return ira->codegen->invalid_instruction;
2226022349
22261 switch (type_entry->id) {22350 return result;
22262 case ZigTypeIdInvalid:
22263 zig_unreachable();
22264 case ZigTypeIdMetaType:
22265 case ZigTypeIdUnreachable:
22266 case ZigTypeIdComptimeFloat:
22267 case ZigTypeIdComptimeInt:
22268 case ZigTypeIdEnumLiteral:
22269 case ZigTypeIdUndefined:
22270 case ZigTypeIdNull:
22271 case ZigTypeIdBoundFn:
22272 case ZigTypeIdArgTuple:
22273 case ZigTypeIdVoid:
22274 case ZigTypeIdOpaque:
22275 ir_add_error(ira, instruction->type_value,
22276 buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
22277 return ira->codegen->invalid_instruction;
22278 case ZigTypeIdBool:
22279 case ZigTypeIdInt:
22280 case ZigTypeIdFloat:
22281 case ZigTypeIdPointer:
22282 case ZigTypeIdArray:
22283 case ZigTypeIdStruct:
22284 case ZigTypeIdOptional:
22285 case ZigTypeIdErrorUnion:
22286 case ZigTypeIdErrorSet:
22287 case ZigTypeIdEnum:
22288 case ZigTypeIdUnion:
22289 case ZigTypeIdFn:
22290 case ZigTypeIdVector:
22291 case ZigTypeIdFnFrame:
22292 case ZigTypeIdAnyFrame:
22293 {
22294 uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
22295 return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
22296 }
22297 }
22298 zig_unreachable();
22299}22351}
2230022352
22301static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {22353static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {
...@@ -22359,13 +22411,26 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr...@@ -22359,13 +22411,26 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
22359 if (type_is_invalid(casted_result_ptr->value.type))22411 if (type_is_invalid(casted_result_ptr->value.type))
22360 return ira->codegen->invalid_instruction;22412 return ira->codegen->invalid_instruction;
2236122413
22362 if (casted_op1->value.special == ConstValSpecialStatic &&22414 if (instr_is_comptime(casted_op1) &&
22363 casted_op2->value.special == ConstValSpecialStatic &&22415 instr_is_comptime(casted_op2) &&
22364 casted_result_ptr->value.special == ConstValSpecialStatic)22416 instr_is_comptime(casted_result_ptr))
22365 {22417 {
22366 BigInt *op1_bigint = &casted_op1->value.data.x_bigint;22418 ConstExprValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad);
22367 BigInt *op2_bigint = &casted_op2->value.data.x_bigint;22419 if (op1_val == nullptr)
22368 ConstExprValue *pointee_val = const_ptr_pointee(ira, ira->codegen, &casted_result_ptr->value, casted_result_ptr->source_node);22420 return ira->codegen->invalid_instruction;
22421
22422 ConstExprValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad);
22423 if (op2_val == nullptr)
22424 return ira->codegen->invalid_instruction;
22425
22426 ConstExprValue *result_val = ir_resolve_const(ira, casted_result_ptr, UndefBad);
22427 if (result_val == nullptr)
22428 return ira->codegen->invalid_instruction;
22429
22430 BigInt *op1_bigint = &op1_val->data.x_bigint;
22431 BigInt *op2_bigint = &op2_val->data.x_bigint;
22432 ConstExprValue *pointee_val = const_ptr_pointee(ira, ira->codegen, result_val,
22433 casted_result_ptr->source_node);
22369 if (pointee_val == nullptr)22434 if (pointee_val == nullptr)
22370 return ira->codegen->invalid_instruction;22435 return ira->codegen->invalid_instruction;
22371 BigInt *dest_bigint = &pointee_val->data.x_bigint;22436 BigInt *dest_bigint = &pointee_val->data.x_bigint;
...@@ -22754,84 +22819,64 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct...@@ -22754,84 +22819,64 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
22754 AstNode *proto_node = instruction->base.source_node;22819 AstNode *proto_node = instruction->base.source_node;
22755 assert(proto_node->type == NodeTypeFnProto);22820 assert(proto_node->type == NodeTypeFnProto);
2275622821
22822 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
22823 result->value.special = ConstValSpecialLazy;
22824
22825 LazyValueFnType *lazy_fn_type = allocate<LazyValueFnType>(1);
22826 lazy_fn_type->ira = ira;
22827 result->value.data.x_lazy = &lazy_fn_type->base;
22828 lazy_fn_type->base.id = LazyValueIdFnType;
22829
22757 if (proto_node->data.fn_proto.auto_err_set) {22830 if (proto_node->data.fn_proto.auto_err_set) {
22758 ir_add_error(ira, &instruction->base,22831 ir_add_error(ira, &instruction->base,
22759 buf_sprintf("inferring error set of return type valid only for function definitions"));22832 buf_sprintf("inferring error set of return type valid only for function definitions"));
22760 return ira->codegen->invalid_instruction;22833 return ira->codegen->invalid_instruction;
22761 }22834 }
2276222835
22763 FnTypeId fn_type_id = {0};22836 size_t param_count = proto_node->data.fn_proto.params.length;
22764 init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);22837 lazy_fn_type->proto_node = proto_node;
22838 lazy_fn_type->param_types = allocate<IrInstruction *>(param_count);
2276522839
22766 for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {22840 for (size_t param_index = 0; param_index < param_count; param_index += 1) {
22767 AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);22841 AstNode *param_node = proto_node->data.fn_proto.params.at(param_index);
22768 assert(param_node->type == NodeTypeParamDecl);22842 assert(param_node->type == NodeTypeParamDecl);
2276922843
22770 bool param_is_var_args = param_node->data.param_decl.is_var_args;22844 bool param_is_var_args = param_node->data.param_decl.is_var_args;
22771 if (param_is_var_args) {22845 if (param_is_var_args) {
22772 if (fn_type_id.cc == CallingConventionC) {22846 if (proto_node->data.fn_proto.cc == CallingConventionC) {
22773 fn_type_id.param_count = fn_type_id.next_param_index;22847 break;
22774 continue;22848 } else if (proto_node->data.fn_proto.cc == CallingConventionUnspecified) {
22775 } else if (fn_type_id.cc == CallingConventionUnspecified) {22849 lazy_fn_type->is_generic = true;
22776 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));22850 return result;
22777 } else {22851 } else {
22778 zig_unreachable();22852 zig_unreachable();
22779 }22853 }
22780 }22854 }
22781 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
22782 param_info->is_noalias = param_node->data.param_decl.is_noalias;
2278322855
22784 if (instruction->param_types[fn_type_id.next_param_index] == nullptr) {22856 if (instruction->param_types[param_index] == nullptr) {
22785 param_info->type = nullptr;22857 lazy_fn_type->is_generic = true;
22786 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));22858 return result;
22787 } else {
22788 IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->child;
22789 if (type_is_invalid(param_type_value->value.type))
22790 return ira->codegen->invalid_instruction;
22791 ZigType *param_type = ir_resolve_type(ira, param_type_value);
22792 switch (type_requires_comptime(ira->codegen, param_type)) {
22793 case ReqCompTimeYes:
22794 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
22795 ir_add_error(ira, param_type_value,
22796 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
22797 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
22798 return ira->codegen->invalid_instruction;
22799 }
22800 param_info->type = param_type;
22801 fn_type_id.next_param_index += 1;
22802 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
22803 case ReqCompTimeInvalid:
22804 return ira->codegen->invalid_instruction;
22805 case ReqCompTimeNo:
22806 break;
22807 }
22808 if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) {
22809 ir_add_error(ira, param_type_value,
22810 buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
22811 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
22812 return ira->codegen->invalid_instruction;
22813 }
22814 param_info->type = param_type;
22815 }22859 }
2281622860
22861 IrInstruction *param_type_value = instruction->param_types[param_index]->child;
22862 if (type_is_invalid(param_type_value->value.type))
22863 return ira->codegen->invalid_instruction;
22864 if (ir_resolve_const(ira, param_type_value, LazyOk) == nullptr)
22865 return ira->codegen->invalid_instruction;
22866 lazy_fn_type->param_types[param_index] = param_type_value;
22817 }22867 }
2281822868
22819 if (instruction->align_value != nullptr) {22869 if (instruction->align_value != nullptr) {
22820 if (!ir_resolve_align(ira, instruction->align_value->child, &fn_type_id.alignment))22870 lazy_fn_type->align_inst = instruction->align_value->child;
22871 if (ir_resolve_const(ira, lazy_fn_type->align_inst, LazyOk) == nullptr)
22821 return ira->codegen->invalid_instruction;22872 return ira->codegen->invalid_instruction;
22822 }22873 }
2282322874
22824 IrInstruction *return_type_value = instruction->return_type->child;22875 lazy_fn_type->return_type = instruction->return_type->child;
22825 fn_type_id.return_type = ir_resolve_type(ira, return_type_value);22876 if (ir_resolve_const(ira, lazy_fn_type->return_type, LazyOk) == nullptr)
22826 if (type_is_invalid(fn_type_id.return_type))22877 return ira->codegen->invalid_instruction;
22827 return ira->codegen->invalid_instruction;
22828 if (fn_type_id.return_type->id == ZigTypeIdOpaque) {
22829 ir_add_error(ira, instruction->return_type,
22830 buf_sprintf("return type cannot be opaque"));
22831 return ira->codegen->invalid_instruction;
22832 }
2283322878
22834 return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id));22879 return result;
22835}22880}
2283622881
22837static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) {22882static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) {
...@@ -23218,7 +23263,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -23218,7 +23263,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
23218 if (!val)23263 if (!val)
23219 return ira->codegen->invalid_instruction;23264 return ira->codegen->invalid_instruction;
2322023265
23221 if (val->special == ConstValSpecialStatic) {23266 if (value_is_comptime(val) && val->special != ConstValSpecialUndef) {
23222 bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull ||23267 bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull ||
23223 (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&23268 (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
23224 val->data.x_ptr.data.hard_coded_addr.addr == 0);23269 val->data.x_ptr.data.hard_coded_addr.addr == 0);
...@@ -23258,6 +23303,12 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -23258,6 +23303,12 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2325823303
23259 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);23304 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
2326023305
23306 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
23307 return ira->codegen->invalid_instruction;
23308
23309 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown)))
23310 return ira->codegen->invalid_instruction;
23311
23261 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {23312 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
23262 ErrorMsg *msg = ir_add_error(ira, source_instr,23313 ErrorMsg *msg = ir_add_error(ira, source_instr,
23263 buf_sprintf("'%s' and '%s' do not have the same in-memory representation",23314 buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
...@@ -23309,8 +23360,10 @@ static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExp...@@ -23309,8 +23360,10 @@ static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExp
23309}23360}
2331023361
23311static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {23362static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
23312 if (val->special == ConstValSpecialUndef)23363 if (val->special == ConstValSpecialUndef) {
23364 expand_undef_struct(codegen, val);
23313 val->special = ConstValSpecialStatic;23365 val->special = ConstValSpecialStatic;
23366 }
23314 assert(val->special == ConstValSpecialStatic);23367 assert(val->special == ConstValSpecialStatic);
23315 switch (val->type->id) {23368 switch (val->type->id) {
23316 case ZigTypeIdInvalid:23369 case ZigTypeIdInvalid:
...@@ -23500,7 +23553,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -23500,7 +23553,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
23500 BigInt bn;23553 BigInt bn;
23501 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,23554 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
23502 codegen->is_big_endian, false);23555 codegen->is_big_endian, false);
23503 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);23556 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_usize(&bn);
23504 return ErrorNone;23557 return ErrorNone;
23505 }23558 }
23506 case ZigTypeIdArray:23559 case ZigTypeIdArray:
...@@ -23693,7 +23746,7 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc...@@ -23693,7 +23746,7 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc
23693 if (!val)23746 if (!val)
23694 return ira->codegen->invalid_instruction;23747 return ira->codegen->invalid_instruction;
2369523748
23696 uint64_t addr = bigint_as_unsigned(&val->data.x_bigint);23749 uint64_t addr = bigint_as_u64(&val->data.x_bigint);
23697 if (!ptr_allows_addr_zero(ptr_type) && addr == 0) {23750 if (!ptr_allows_addr_zero(ptr_type) && addr == 0) {
23698 ir_add_error(ira, source_instr,23751 ir_add_error(ira, source_instr,
23699 buf_sprintf("pointer type '%s' does not allow address zero", buf_ptr(&ptr_type->name)));23752 buf_sprintf("pointer type '%s' does not allow address zero", buf_ptr(&ptr_type->name)));
...@@ -23746,8 +23799,9 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,...@@ -23746,8 +23799,9 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
23746 IrInstructionDeclRef *instruction)23799 IrInstructionDeclRef *instruction)
23747{23800{
23748 IrInstruction *ref_instruction = ir_analyze_decl_ref(ira, &instruction->base, instruction->tld);23801 IrInstruction *ref_instruction = ir_analyze_decl_ref(ira, &instruction->base, instruction->tld);
23749 if (type_is_invalid(ref_instruction->value.type))23802 if (type_is_invalid(ref_instruction->value.type)) {
23750 return ira->codegen->invalid_instruction;23803 return ira->codegen->invalid_instruction;
23804 }
2375123805
23752 if (instruction->lval == LValPtr) {23806 if (instruction->lval == LValPtr) {
23753 return ref_instruction;23807 return ref_instruction;
...@@ -23795,53 +23849,32 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru...@@ -23795,53 +23849,32 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru
23795}23849}
2379623850
23797static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtrType *instruction) {23851static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtrType *instruction) {
23798 Error err;23852 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
23799 ZigType *child_type = ir_resolve_type(ira, instruction->child_type->child);23853 result->value.special = ConstValSpecialLazy;
23800 if (type_is_invalid(child_type))
23801 return ira->codegen->invalid_instruction;
2380223854
23803 if (child_type->id == ZigTypeIdUnreachable) {23855 LazyValuePtrType *lazy_ptr_type = allocate<LazyValuePtrType>(1);
23804 ir_add_error(ira, &instruction->base, buf_sprintf("pointer to noreturn not allowed"));23856 lazy_ptr_type->ira = ira;
23805 return ira->codegen->invalid_instruction;23857 result->value.data.x_lazy = &lazy_ptr_type->base;
23806 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {23858 lazy_ptr_type->base.id = LazyValueIdPtrType;
23807 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));23859
23860 lazy_ptr_type->elem_type = instruction->child_type->child;
23861 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)
23808 return ira->codegen->invalid_instruction;23862 return ira->codegen->invalid_instruction;
23809 } else if (instruction->ptr_len == PtrLenC) {
23810 if (!type_allowed_in_extern(ira->codegen, child_type)) {
23811 ir_add_error(ira, &instruction->base,
23812 buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name)));
23813 return ira->codegen->invalid_instruction;
23814 } else if (child_type->id == ZigTypeIdOpaque) {
23815 ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types"));
23816 return ira->codegen->invalid_instruction;
23817 } else if (instruction->is_allow_zero) {
23818 ir_add_error(ira, &instruction->base, buf_sprintf("C pointers always allow address zero"));
23819 return ira->codegen->invalid_instruction;
23820 }
23821 }
2382223863
23823 uint32_t align_bytes;
23824 if (instruction->align_value != nullptr) {23864 if (instruction->align_value != nullptr) {
23825 if (!ir_resolve_align(ira, instruction->align_value->child, &align_bytes))23865 lazy_ptr_type->align_inst = instruction->align_value->child;
23866 if (ir_resolve_const(ira, lazy_ptr_type->align_inst, LazyOk) == nullptr)
23826 return ira->codegen->invalid_instruction;23867 return ira->codegen->invalid_instruction;
23827 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
23828 return ira->codegen->invalid_instruction;
23829 if (!type_has_bits(child_type)) {
23830 align_bytes = 0;
23831 }
23832 } else {
23833 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
23834 return ira->codegen->invalid_instruction;
23835 align_bytes = 0;
23836 }23868 }
2383723869
23838 bool allow_zero = instruction->is_allow_zero || instruction->ptr_len == PtrLenC;23870 lazy_ptr_type->ptr_len = instruction->ptr_len;
23871 lazy_ptr_type->is_const = instruction->is_const;
23872 lazy_ptr_type->is_volatile = instruction->is_volatile;
23873 lazy_ptr_type->is_allowzero = instruction->is_allow_zero;
23874 lazy_ptr_type->bit_offset_in_host = instruction->bit_offset_start;
23875 lazy_ptr_type->host_int_bytes = instruction->host_int_bytes;
2383923876
23840 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,23877 return result;
23841 instruction->is_const, instruction->is_volatile,
23842 instruction->ptr_len, align_bytes,
23843 instruction->bit_offset_start, instruction->host_int_bytes, allow_zero);
23844 return ir_const_type(ira, &instruction->base, result_type);
23845}23878}
2384623879
23847static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) {23880static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) {
...@@ -23954,7 +23987,7 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct...@@ -23954,7 +23987,7 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct
23954 return ira->codegen->invalid_instruction;23987 return ira->codegen->invalid_instruction;
2395523988
23956 if (enum_type->id == ZigTypeIdEnum) {23989 if (enum_type->id == ZigTypeIdEnum) {
23957 if ((err = ensure_complete_type(ira->codegen, enum_type)))23990 if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusSizeKnown)))
23958 return ira->codegen->invalid_instruction;23991 return ira->codegen->invalid_instruction;
2395923992
23960 return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type);23993 return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type);
...@@ -25100,7 +25133,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25100,7 +25133,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25100ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,25133ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,
25101 ZigType *expected_type, AstNode *expected_type_source_node)25134 ZigType *expected_type, AstNode *expected_type_source_node)
25102{25135{
25103 assert(!old_exec->invalid);25136 assert(old_exec->first_err_trace_msg == nullptr);
25104 assert(expected_type == nullptr || !type_is_invalid(expected_type));25137 assert(expected_type == nullptr || !type_is_invalid(expected_type));
2510525138
25106 IrAnalyze *ira = allocate<IrAnalyze>(1);25139 IrAnalyze *ira = allocate<IrAnalyze>(1);
...@@ -25147,6 +25180,18 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_...@@ -25147,6 +25180,18 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
25147 old_instruction->child = new_instruction;25180 old_instruction->child = new_instruction;
2514825181
25149 if (type_is_invalid(new_instruction->value.type)) {25182 if (type_is_invalid(new_instruction->value.type)) {
25183 if (new_exec->first_err_trace_msg != nullptr) {
25184 ira->codegen->trace_err = new_exec->first_err_trace_msg;
25185 } else {
25186 new_exec->first_err_trace_msg = ira->codegen->trace_err;
25187 }
25188 if (new_exec->first_err_trace_msg != nullptr &&
25189 !old_instruction->source_node->already_traced_this_node)
25190 {
25191 old_instruction->source_node->already_traced_this_node = true;
25192 new_exec->first_err_trace_msg = add_error_note(ira->codegen, new_exec->first_err_trace_msg,
25193 old_instruction->source_node, buf_create_from_str("referenced here"));
25194 }
25150 return ira->codegen->builtin_types.entry_invalid;25195 return ira->codegen->builtin_types.entry_invalid;
25151 }25196 }
2515225197
...@@ -25158,7 +25203,15 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_...@@ -25158,7 +25203,15 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
25158 ira->instruction_index += 1;25203 ira->instruction_index += 1;
25159 }25204 }
2516025205
25161 if (new_exec->invalid) {25206 if (new_exec->first_err_trace_msg != nullptr) {
25207 codegen->trace_err = new_exec->first_err_trace_msg;
25208 if (codegen->trace_err != nullptr && new_exec->source_node != nullptr &&
25209 !new_exec->source_node->already_traced_this_node)
25210 {
25211 new_exec->source_node->already_traced_this_node = true;
25212 codegen->trace_err = add_error_note(codegen, codegen->trace_err,
25213 new_exec->source_node, buf_create_from_str("referenced here"));
25214 }
25162 return ira->codegen->builtin_types.entry_invalid;25215 return ira->codegen->builtin_types.entry_invalid;
25163 } else if (ira->src_implicit_return_type_list.length == 0) {25216 } else if (ira->src_implicit_return_type_list.length == 0) {
25164 return codegen->builtin_types.entry_unreachable;25217 return codegen->builtin_types.entry_unreachable;
...@@ -25354,3 +25407,336 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -25354,3 +25407,336 @@ bool ir_has_side_effects(IrInstruction *instruction) {
25354 }25407 }
25355 zig_unreachable();25408 zig_unreachable();
25356}25409}
25410
25411static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, LazyValueFnType *lazy_fn_type) {
25412 Error err;
25413 AstNode *proto_node = lazy_fn_type->proto_node;
25414
25415 FnTypeId fn_type_id = {0};
25416 init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);
25417
25418 for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
25419 AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);
25420 assert(param_node->type == NodeTypeParamDecl);
25421
25422 bool param_is_var_args = param_node->data.param_decl.is_var_args;
25423 if (param_is_var_args) {
25424 if (fn_type_id.cc == CallingConventionC) {
25425 fn_type_id.param_count = fn_type_id.next_param_index;
25426 continue;
25427 } else if (fn_type_id.cc == CallingConventionUnspecified) {
25428 return get_generic_fn_type(ira->codegen, &fn_type_id);
25429 } else {
25430 zig_unreachable();
25431 }
25432 }
25433 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
25434 param_info->is_noalias = param_node->data.param_decl.is_noalias;
25435
25436 if (lazy_fn_type->param_types[fn_type_id.next_param_index] == nullptr) {
25437 param_info->type = nullptr;
25438 return get_generic_fn_type(ira->codegen, &fn_type_id);
25439 } else {
25440 IrInstruction *param_type_inst = lazy_fn_type->param_types[fn_type_id.next_param_index];
25441 ZigType *param_type = ir_resolve_type(ira, param_type_inst);
25442 if (type_is_invalid(param_type))
25443 return nullptr;
25444 switch (type_requires_comptime(ira->codegen, param_type)) {
25445 case ReqCompTimeYes:
25446 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
25447 ir_add_error(ira, param_type_inst,
25448 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
25449 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
25450 return nullptr;
25451 }
25452 param_info->type = param_type;
25453 fn_type_id.next_param_index += 1;
25454 return get_generic_fn_type(ira->codegen, &fn_type_id);
25455 case ReqCompTimeInvalid:
25456 return nullptr;
25457 case ReqCompTimeNo:
25458 break;
25459 }
25460 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
25461 if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown)))
25462 return nullptr;
25463 if (!type_has_bits(param_type)) {
25464 ir_add_error(ira, param_type_inst,
25465 buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
25466 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
25467 return nullptr;
25468 }
25469 }
25470 param_info->type = param_type;
25471 }
25472 }
25473
25474 if (lazy_fn_type->align_inst != nullptr) {
25475 if (!ir_resolve_align(ira, lazy_fn_type->align_inst, &fn_type_id.alignment))
25476 return nullptr;
25477 }
25478
25479 fn_type_id.return_type = ir_resolve_type(ira, lazy_fn_type->return_type);
25480 if (type_is_invalid(fn_type_id.return_type))
25481 return nullptr;
25482 if (fn_type_id.return_type->id == ZigTypeIdOpaque) {
25483 ir_add_error(ira, lazy_fn_type->return_type, buf_create_from_str("return type cannot be opaque"));
25484 return nullptr;
25485 }
25486
25487 return get_fn_type(ira->codegen, &fn_type_id);
25488}
25489
25490static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
25491 Error err;
25492 if (val->special != ConstValSpecialLazy)
25493 return ErrorNone;
25494 switch (val->data.x_lazy->id) {
25495 case LazyValueIdInvalid:
25496 zig_unreachable();
25497 case LazyValueIdAlignOf: {
25498 LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(val->data.x_lazy);
25499 IrAnalyze *ira = lazy_align_of->ira;
25500
25501 if (lazy_align_of->target_type->value.special == ConstValSpecialStatic) {
25502 switch (lazy_align_of->target_type->value.data.x_type->id) {
25503 case ZigTypeIdInvalid:
25504 zig_unreachable();
25505 case ZigTypeIdMetaType:
25506 case ZigTypeIdUnreachable:
25507 case ZigTypeIdComptimeFloat:
25508 case ZigTypeIdComptimeInt:
25509 case ZigTypeIdEnumLiteral:
25510 case ZigTypeIdUndefined:
25511 case ZigTypeIdNull:
25512 case ZigTypeIdBoundFn:
25513 case ZigTypeIdArgTuple:
25514 case ZigTypeIdVoid:
25515 case ZigTypeIdOpaque:
25516 ir_add_error(ira, lazy_align_of->target_type,
25517 buf_sprintf("no align available for type '%s'",
25518 buf_ptr(&lazy_align_of->target_type->value.data.x_type->name)));
25519 return ErrorSemanticAnalyzeFail;
25520 case ZigTypeIdBool:
25521 case ZigTypeIdInt:
25522 case ZigTypeIdFloat:
25523 case ZigTypeIdPointer:
25524 case ZigTypeIdArray:
25525 case ZigTypeIdStruct:
25526 case ZigTypeIdOptional:
25527 case ZigTypeIdErrorUnion:
25528 case ZigTypeIdErrorSet:
25529 case ZigTypeIdEnum:
25530 case ZigTypeIdUnion:
25531 case ZigTypeIdFn:
25532 case ZigTypeIdVector:
25533 case ZigTypeIdFnFrame:
25534 case ZigTypeIdAnyFrame:
25535 break;
25536 }
25537 }
25538
25539 uint32_t align_in_bytes;
25540 if ((err = type_val_resolve_abi_align(ira->codegen, &lazy_align_of->target_type->value,
25541 &align_in_bytes)))
25542 {
25543 return err;
25544 }
25545
25546 val->special = ConstValSpecialStatic;
25547 assert(val->type->id == ZigTypeIdComptimeInt);
25548 bigint_init_unsigned(&val->data.x_bigint, align_in_bytes);
25549 return ErrorNone;
25550 }
25551 case LazyValueIdSliceType: {
25552 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(val->data.x_lazy);
25553 IrAnalyze *ira = lazy_slice_type->ira;
25554
25555 uint32_t align_bytes = 0;
25556 if (lazy_slice_type->align_inst != nullptr) {
25557 if (!ir_resolve_align(ira, lazy_slice_type->align_inst, &align_bytes))
25558 return ErrorSemanticAnalyzeFail;
25559 }
25560 ZigType *elem_type = ir_resolve_type(ira, lazy_slice_type->elem_type);
25561 if (type_is_invalid(elem_type))
25562 return ErrorSemanticAnalyzeFail;
25563
25564 switch (elem_type->id) {
25565 case ZigTypeIdInvalid: // handled above
25566 zig_unreachable();
25567 case ZigTypeIdUnreachable:
25568 case ZigTypeIdUndefined:
25569 case ZigTypeIdNull:
25570 case ZigTypeIdArgTuple:
25571 case ZigTypeIdOpaque:
25572 ir_add_error(ira, lazy_slice_type->elem_type,
25573 buf_sprintf("slice of type '%s' not allowed", buf_ptr(&elem_type->name)));
25574 return ErrorSemanticAnalyzeFail;
25575 case ZigTypeIdMetaType:
25576 case ZigTypeIdVoid:
25577 case ZigTypeIdBool:
25578 case ZigTypeIdInt:
25579 case ZigTypeIdFloat:
25580 case ZigTypeIdPointer:
25581 case ZigTypeIdArray:
25582 case ZigTypeIdStruct:
25583 case ZigTypeIdComptimeFloat:
25584 case ZigTypeIdComptimeInt:
25585 case ZigTypeIdEnumLiteral:
25586 case ZigTypeIdOptional:
25587 case ZigTypeIdErrorUnion:
25588 case ZigTypeIdErrorSet:
25589 case ZigTypeIdEnum:
25590 case ZigTypeIdUnion:
25591 case ZigTypeIdFn:
25592 case ZigTypeIdBoundFn:
25593 case ZigTypeIdVector:
25594 case ZigTypeIdFnFrame:
25595 case ZigTypeIdAnyFrame:
25596 break;
25597 }
25598
25599 ResolveStatus needed_status = (align_bytes == 0) ?
25600 ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
25601 if ((err = type_resolve(ira->codegen, elem_type, needed_status)))
25602 return err;
25603 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type,
25604 lazy_slice_type->is_const, lazy_slice_type->is_volatile, PtrLenUnknown, align_bytes,
25605 0, 0, lazy_slice_type->is_allowzero);
25606 val->special = ConstValSpecialStatic;
25607 assert(val->type->id == ZigTypeIdMetaType);
25608 val->data.x_type = get_slice_type(ira->codegen, slice_ptr_type);
25609 return ErrorNone;
25610 }
25611 case LazyValueIdPtrType: {
25612 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(val->data.x_lazy);
25613 IrAnalyze *ira = lazy_ptr_type->ira;
25614
25615 uint32_t align_bytes = 0;
25616 if (lazy_ptr_type->align_inst != nullptr) {
25617 if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, &align_bytes))
25618 return ErrorSemanticAnalyzeFail;
25619 }
25620 ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
25621 if (type_is_invalid(elem_type))
25622 return ErrorSemanticAnalyzeFail;
25623
25624 if (elem_type->id == ZigTypeIdUnreachable) {
25625 ir_add_error(ira, lazy_ptr_type->elem_type,
25626 buf_create_from_str("pointer to noreturn not allowed"));
25627 return ErrorSemanticAnalyzeFail;
25628 } else if (elem_type->id == ZigTypeIdOpaque && lazy_ptr_type->ptr_len == PtrLenUnknown) {
25629 ir_add_error(ira, lazy_ptr_type->elem_type,
25630 buf_create_from_str("unknown-length pointer to opaque"));
25631 return ErrorSemanticAnalyzeFail;
25632 } else if (lazy_ptr_type->ptr_len == PtrLenC) {
25633 if (!type_allowed_in_extern(ira->codegen, elem_type)) {
25634 ir_add_error(ira, lazy_ptr_type->elem_type,
25635 buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'",
25636 buf_ptr(&elem_type->name)));
25637 return ErrorSemanticAnalyzeFail;
25638 } else if (elem_type->id == ZigTypeIdOpaque) {
25639 ir_add_error(ira, lazy_ptr_type->elem_type,
25640 buf_sprintf("C pointers cannot point opaque types"));
25641 return ErrorSemanticAnalyzeFail;
25642 } else if (lazy_ptr_type->is_allowzero) {
25643 ir_add_error(ira, lazy_ptr_type->elem_type,
25644 buf_sprintf("C pointers always allow address zero"));
25645 return ErrorSemanticAnalyzeFail;
25646 }
25647 }
25648
25649 if (align_bytes != 0) {
25650 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown)))
25651 return err;
25652 if (!type_has_bits(elem_type))
25653 align_bytes = 0;
25654 }
25655 bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC;
25656 assert(val->type->id == ZigTypeIdMetaType);
25657 val->data.x_type = get_pointer_to_type_extra(ira->codegen, elem_type,
25658 lazy_ptr_type->is_const, lazy_ptr_type->is_volatile, lazy_ptr_type->ptr_len, align_bytes,
25659 lazy_ptr_type->bit_offset_in_host, lazy_ptr_type->host_int_bytes,
25660 allow_zero);
25661 val->special = ConstValSpecialStatic;
25662 return ErrorNone;
25663 }
25664 case LazyValueIdOptType: {
25665 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(val->data.x_lazy);
25666 IrAnalyze *ira = lazy_opt_type->ira;
25667
25668 ZigType *payload_type = ir_resolve_type(ira, lazy_opt_type->payload_type);
25669 if (type_is_invalid(payload_type))
25670 return ErrorSemanticAnalyzeFail;
25671
25672 if (payload_type->id == ZigTypeIdOpaque || payload_type->id == ZigTypeIdUnreachable) {
25673 ir_add_error(ira, lazy_opt_type->payload_type,
25674 buf_sprintf("type '%s' cannot be optional", buf_ptr(&payload_type->name)));
25675 return ErrorSemanticAnalyzeFail;
25676 }
25677
25678 if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
25679 return err;
25680
25681 assert(val->type->id == ZigTypeIdMetaType);
25682 val->data.x_type = get_optional_type(ira->codegen, payload_type);
25683 val->special = ConstValSpecialStatic;
25684 return ErrorNone;
25685 }
25686 case LazyValueIdFnType: {
25687 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(val->data.x_lazy);
25688 ZigType *fn_type = ir_resolve_lazy_fn_type(lazy_fn_type->ira, source_node, lazy_fn_type);
25689 if (fn_type == nullptr)
25690 return ErrorSemanticAnalyzeFail;
25691 val->special = ConstValSpecialStatic;
25692 assert(val->type->id == ZigTypeIdMetaType);
25693 val->data.x_type = fn_type;
25694 return ErrorNone;
25695 }
25696 case LazyValueIdErrUnionType: {
25697 LazyValueErrUnionType *lazy_err_union_type =
25698 reinterpret_cast<LazyValueErrUnionType *>(val->data.x_lazy);
25699 IrAnalyze *ira = lazy_err_union_type->ira;
25700
25701 ZigType *err_set_type = ir_resolve_type(ira, lazy_err_union_type->err_set_type);
25702 if (type_is_invalid(err_set_type))
25703 return ErrorSemanticAnalyzeFail;
25704
25705 ZigType *payload_type = ir_resolve_type(ira, lazy_err_union_type->payload_type);
25706 if (type_is_invalid(payload_type))
25707 return ErrorSemanticAnalyzeFail;
25708
25709 if (err_set_type->id != ZigTypeIdErrorSet) {
25710 ir_add_error(ira, lazy_err_union_type->err_set_type,
25711 buf_sprintf("expected error set type, found type '%s'",
25712 buf_ptr(&err_set_type->name)));
25713 return ErrorSemanticAnalyzeFail;
25714 }
25715
25716 if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
25717 return ErrorSemanticAnalyzeFail;
25718
25719 assert(val->type->id == ZigTypeIdMetaType);
25720 val->data.x_type = get_error_union_type(ira->codegen, err_set_type, payload_type);
25721 val->special = ConstValSpecialStatic;
25722 return ErrorNone;
25723 }
25724 }
25725 zig_unreachable();
25726}
25727
25728Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) {
25729 Error err;
25730 if ((err = ir_resolve_lazy_raw(source_node, val))) {
25731 if (codegen->trace_err != nullptr && !source_node->already_traced_this_node) {
25732 source_node->already_traced_this_node = true;
25733 codegen->trace_err = add_error_note(codegen, codegen->trace_err, source_node,
25734 buf_create_from_str("referenced here"));
25735 }
25736 return err;
25737 }
25738 if (type_is_invalid(val->type)) {
25739 return ErrorSemanticAnalyzeFail;
25740 }
25741 return ErrorNone;
25742}
src/ir.hpp+3-3
...@@ -16,7 +16,9 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);...@@ -16,7 +16,9 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
16ConstExprValue *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, AstNode *expected_type_source_node);19 IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
20
21Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val);
2022
21ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,23ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
22 ZigType *expected_type, AstNode *expected_type_source_node);24 ZigType *expected_type, AstNode *expected_type_source_node);
...@@ -28,6 +30,4 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal...@@ -28,6 +30,4 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
28 AstNode *source_node);30 AstNode *source_node);
29const char *float_op_to_name(BuiltinFnId op, bool llvm_name);31const char *float_op_to_name(BuiltinFnId op, bool llvm_name);
3032
31void ir_add_analysis_trace(IrAnalyze *ira, ErrorMsg *err_msg, Buf *text);
32
33#endif33#endif
src/os.cpp+15-15
...@@ -1125,29 +1125,27 @@ Error os_get_cwd(Buf *out_cwd) {...@@ -1125,29 +1125,27 @@ Error os_get_cwd(Buf *out_cwd) {
1125#endif1125#endif
1126}1126}
11271127
1128#if defined(ZIG_OS_WINDOWS)
1129#define is_wprefix(s, prefix) \1128#define is_wprefix(s, prefix) \
1130 (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)1129 (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
1131static bool is_stderr_cyg_pty(void) {1130bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd) {
1132 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);1131#if defined(ZIG_OS_WINDOWS)
1133 if (stderr_handle == INVALID_HANDLE_VALUE)1132 HANDLE handle = (HANDLE)_get_osfhandle(fd);
1133
1134 // Cygwin/msys's pty is a pipe.
1135 if (handle == INVALID_HANDLE_VALUE || GetFileType(handle) != FILE_TYPE_PIPE) {
1134 return false;1136 return false;
1137 }
11351138
1136 int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;1139 int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;
1137 FILE_NAME_INFO *nameinfo;
1138 WCHAR *p = NULL;1140 WCHAR *p = NULL;
11391141
1140 // Cygwin/msys's pty is a pipe.1142 FILE_NAME_INFO *nameinfo = (FILE_NAME_INFO *)allocate<char>(size);
1141 if (GetFileType(stderr_handle) != FILE_TYPE_PIPE) {
1142 return 0;
1143 }
1144 nameinfo = (FILE_NAME_INFO *)allocate<char>(size);
1145 if (nameinfo == NULL) {1143 if (nameinfo == NULL) {
1146 return 0;1144 return false;
1147 }1145 }
1148 // Check the name of the pipe:1146 // Check the name of the pipe:
1149 // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master'1147 // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master'
1150 if (GetFileInformationByHandleEx(stderr_handle, FileNameInfo, nameinfo, size)) {1148 if (GetFileInformationByHandleEx(handle, FileNameInfo, nameinfo, size)) {
1151 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';1149 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
1152 p = nameinfo->FileName;1150 p = nameinfo->FileName;
1153 if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */1151 if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
...@@ -1180,12 +1178,14 @@ static bool is_stderr_cyg_pty(void) {...@@ -1180,12 +1178,14 @@ static bool is_stderr_cyg_pty(void) {
1180 }1178 }
1181 free(nameinfo);1179 free(nameinfo);
1182 return (p != NULL);1180 return (p != NULL);
1183}1181#else
1182 return false;
1184#endif1183#endif
1184}
11851185
1186bool os_stderr_tty(void) {1186bool os_stderr_tty(void) {
1187#if defined(ZIG_OS_WINDOWS)1187#if defined(ZIG_OS_WINDOWS)
1188 return _isatty(_fileno(stderr)) != 0 || is_stderr_cyg_pty();1188 return _isatty(fileno(stderr)) != 0 || os_is_cygwin_pty(fileno(stderr));
1189#elif defined(ZIG_OS_POSIX)1189#elif defined(ZIG_OS_POSIX)
1190 return isatty(STDERR_FILENO) != 0;1190 return isatty(STDERR_FILENO) != 0;
1191#else1191#else
...@@ -1486,7 +1486,7 @@ WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BL...@@ -1486,7 +1486,7 @@ WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BL
14861486
1487void os_stderr_set_color(TermColor color) {1487void os_stderr_set_color(TermColor color) {
1488#if defined(ZIG_OS_WINDOWS)1488#if defined(ZIG_OS_WINDOWS)
1489 if (is_stderr_cyg_pty()) {1489 if (os_stderr_tty()) {
1490 set_color_posix(color);1490 set_color_posix(color);
1491 return;1491 return;
1492 }1492 }
src/os.hpp+8
...@@ -11,6 +11,7 @@...@@ -11,6 +11,7 @@
11#include "list.hpp"11#include "list.hpp"
12#include "buffer.hpp"12#include "buffer.hpp"
13#include "error.hpp"13#include "error.hpp"
14#include "target.hpp"
14#include "zig_llvm.h"15#include "zig_llvm.h"
15#include "windows_sdk.h"16#include "windows_sdk.h"
1617
...@@ -88,6 +89,11 @@ struct Termination {...@@ -88,6 +89,11 @@ struct Termination {
88#define OsFile int89#define OsFile int
89#endif90#endif
9091
92#if defined(ZIG_OS_WINDOWS)
93#undef fileno
94#define fileno _fileno
95#endif
96
91struct OsTimeStamp {97struct OsTimeStamp {
92 uint64_t sec;98 uint64_t sec;
93 uint64_t nsec;99 uint64_t nsec;
...@@ -152,6 +158,8 @@ Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf...@@ -152,6 +158,8 @@ Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf
152Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);158Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
153Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);159Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
154160
161bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd);
162
155Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);163Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
156164
157#endif165#endif
src/parser.cpp+5-3
...@@ -782,24 +782,26 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {...@@ -782,24 +782,26 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
782 return res;782 return res;
783}783}
784784
785// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?785// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
786static AstNode *ast_parse_container_field(ParseContext *pc) {786static AstNode *ast_parse_container_field(ParseContext *pc) {
787 Token *identifier = eat_token_if(pc, TokenIdSymbol);787 Token *identifier = eat_token_if(pc, TokenIdSymbol);
788 if (identifier == nullptr)788 if (identifier == nullptr)
789 return nullptr;789 return nullptr;
790790
791 AstNode *type_expr = nullptr;791 AstNode *type_expr = nullptr;
792 if (eat_token_if(pc, TokenIdColon) != nullptr)792 if (eat_token_if(pc, TokenIdColon) != nullptr) {
793 type_expr = ast_expect(pc, ast_parse_type_expr);793 type_expr = ast_expect(pc, ast_parse_type_expr);
794 }
795 AstNode *align_expr = ast_parse_byte_align(pc);
794 AstNode *expr = nullptr;796 AstNode *expr = nullptr;
795 if (eat_token_if(pc, TokenIdEq) != nullptr)797 if (eat_token_if(pc, TokenIdEq) != nullptr)
796 expr = ast_expect(pc, ast_parse_expr);798 expr = ast_expect(pc, ast_parse_expr);
797799
798
799 AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier);800 AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier);
800 res->data.struct_field.name = token_buf(identifier);801 res->data.struct_field.name = token_buf(identifier);
801 res->data.struct_field.type = type_expr;802 res->data.struct_field.type = type_expr;
802 res->data.struct_field.value = expr;803 res->data.struct_field.value = expr;
804 res->data.struct_field.align_expr = align_expr;
803 return res;805 return res;
804}806}
805807
src/target.cpp+14-1
...@@ -504,6 +504,16 @@ Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) {...@@ -504,6 +504,16 @@ Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) {
504 return ErrorNone;504 return ErrorNone;
505}505}
506506
507static ZigLLVM_EnvironmentType target_get_win32_abi() {
508 FILE* files[] = { stdin, stdout, stderr, nullptr };
509 for (int i = 0; files[i] != nullptr; i++) {
510 if (os_is_cygwin_pty(fileno(files[i]))) {
511 return ZigLLVM_GNU;
512 }
513 }
514 return ZigLLVM_MSVC;
515}
516
507void get_native_target(ZigTarget *target) {517void get_native_target(ZigTarget *target) {
508 // first zero initialize518 // first zero initialize
509 *target = {};519 *target = {};
...@@ -518,6 +528,9 @@ void get_native_target(ZigTarget *target) {...@@ -518,6 +528,9 @@ void get_native_target(ZigTarget *target) {
518 &target->abi,528 &target->abi,
519 &oformat);529 &oformat);
520 target->os = get_zig_os_type(os_type);530 target->os = get_zig_os_type(os_type);
531 if (target->os == OsWindows) {
532 target->abi = target_get_win32_abi();
533 }
521 target->is_native = true;534 target->is_native = true;
522 if (target->abi == ZigLLVM_UnknownEnvironment) {535 if (target->abi == ZigLLVM_UnknownEnvironment) {
523 target->abi = target_default_abi(target->arch, target->os);536 target->abi = target_default_abi(target->arch, target->os);
...@@ -1651,7 +1664,7 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {...@@ -1651,7 +1664,7 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
1651 return ZigLLVM_GNU;1664 return ZigLLVM_GNU;
1652 case OsUefi:1665 case OsUefi:
1653 case OsWindows:1666 case OsWindows:
1654 return ZigLLVM_MSVC;1667 return ZigLLVM_MSVC;
1655 case OsLinux:1668 case OsLinux:
1656 case OsWASI:1669 case OsWASI:
1657 case OsEmscripten:1670 case OsEmscripten:
src/tokenizer.cpp+1-1
...@@ -841,7 +841,7 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -841,7 +841,7 @@ void tokenize(Buf *buf, Tokenization *out) {
841 case TokenizeStateSawAmpersand:841 case TokenizeStateSawAmpersand:
842 switch (c) {842 switch (c) {
843 case '&':843 case '&':
844 tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND.");844 tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND");
845 break;845 break;
846 case '=':846 case '=':
847 set_token_id(&t, t.cur_tok, TokenIdBitAndEq);847 set_token_id(&t, t.cur_tok, TokenIdBitAndEq);
src/zig_llvm.cpp+3-3
...@@ -15,9 +15,9 @@...@@ -15,9 +15,9 @@
1515
16#include "zig_llvm.h"16#include "zig_llvm.h"
1717
18#if __GNUC__ >= 818#if __GNUC__ >= 9
19#pragma GCC diagnostic push19#pragma GCC diagnostic push
20#pragma GCC diagnostic ignored "-Wclass-memaccess"20#pragma GCC diagnostic ignored "-Winit-list-lifetime"
21#endif21#endif
2222
23#include <llvm/Analysis/TargetLibraryInfo.h>23#include <llvm/Analysis/TargetLibraryInfo.h>
...@@ -50,7 +50,7 @@...@@ -50,7 +50,7 @@
5050
51#include <lld/Common/Driver.h>51#include <lld/Common/Driver.h>
5252
53#if __GNUC__ >= 853#if __GNUC__ >= 9
54#pragma GCC diagnostic pop54#pragma GCC diagnostic pop
55#endif55#endif
5656
std/array_list.zig+12-9
...@@ -6,20 +6,23 @@ const mem = std.mem;...@@ -6,20 +6,23 @@ const mem = std.mem;
6const Allocator = mem.Allocator;6const Allocator = mem.Allocator;
77
8pub fn ArrayList(comptime T: type) type {8pub fn ArrayList(comptime T: type) type {
9 return AlignedArrayList(T, @alignOf(T));9 return AlignedArrayList(T, null);
10}10}
1111
12pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {12pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
13 return struct {13 return struct {
14 const Self = @This();14 const Self = @This();
1515
16 /// Use toSlice instead of slicing this directly, because if you don't16 /// Use toSlice instead of slicing this directly, because if you don't
17 /// specify the end position of the slice, this will potentially give17 /// specify the end position of the slice, this will potentially give
18 /// you uninitialized memory.18 /// you uninitialized memory.
19 items: []align(A) T,19 items: Slice,
20 len: usize,20 len: usize,
21 allocator: *Allocator,21 allocator: *Allocator,
2222
23 pub const Slice = if (alignment) |a| ([]align(a) T) else []T;
24 pub const SliceConst = if (alignment) |a| ([]align(a) const T) else []const T;
25
23 /// Deinitialize with `deinit` or use `toOwnedSlice`.26 /// Deinitialize with `deinit` or use `toOwnedSlice`.
24 pub fn init(allocator: *Allocator) Self {27 pub fn init(allocator: *Allocator) Self {
25 return Self{28 return Self{
...@@ -33,11 +36,11 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {...@@ -33,11 +36,11 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
33 self.allocator.free(self.items);36 self.allocator.free(self.items);
34 }37 }
3538
36 pub fn toSlice(self: Self) []align(A) T {39 pub fn toSlice(self: Self) Slice {
37 return self.items[0..self.len];40 return self.items[0..self.len];
38 }41 }
3942
40 pub fn toSliceConst(self: Self) []align(A) const T {43 pub fn toSliceConst(self: Self) SliceConst {
41 return self.items[0..self.len];44 return self.items[0..self.len];
42 }45 }
4346
...@@ -69,7 +72,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {...@@ -69,7 +72,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
69 /// ArrayList takes ownership of the passed in slice. The slice must have been72 /// ArrayList takes ownership of the passed in slice. The slice must have been
70 /// allocated with `allocator`.73 /// allocated with `allocator`.
71 /// Deinitialize with `deinit` or use `toOwnedSlice`.74 /// Deinitialize with `deinit` or use `toOwnedSlice`.
72 pub fn fromOwnedSlice(allocator: *Allocator, slice: []align(A) T) Self {75 pub fn fromOwnedSlice(allocator: *Allocator, slice: Slice) Self {
73 return Self{76 return Self{
74 .items = slice,77 .items = slice,
75 .len = slice.len,78 .len = slice.len,
...@@ -78,7 +81,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {...@@ -78,7 +81,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
78 }81 }
7982
80 /// The caller owns the returned memory. ArrayList becomes empty.83 /// The caller owns the returned memory. ArrayList becomes empty.
81 pub fn toOwnedSlice(self: *Self) []align(A) T {84 pub fn toOwnedSlice(self: *Self) Slice {
82 const allocator = self.allocator;85 const allocator = self.allocator;
83 const result = allocator.shrink(self.items, self.len);86 const result = allocator.shrink(self.items, self.len);
84 self.* = init(allocator);87 self.* = init(allocator);
...@@ -93,7 +96,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {...@@ -93,7 +96,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
93 self.items[n] = item;96 self.items[n] = item;
94 }97 }
9598
96 pub fn insertSlice(self: *Self, n: usize, items: []align(A) const T) !void {99 pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void {
97 try self.ensureCapacity(self.len + items.len);100 try self.ensureCapacity(self.len + items.len);
98 self.len += items.len;101 self.len += items.len;
99102
...@@ -141,7 +144,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {...@@ -141,7 +144,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
141 return self.swapRemove(i);144 return self.swapRemove(i);
142 }145 }
143146
144 pub fn appendSlice(self: *Self, items: []align(A) const T) !void {147 pub fn appendSlice(self: *Self, items: SliceConst) !void {
145 try self.ensureCapacity(self.len + items.len);148 try self.ensureCapacity(self.len + items.len);
146 mem.copy(T, self.items[self.len..], items);149 mem.copy(T, self.items[self.len..], items);
147 self.len += items.len;150 self.len += items.len;
std/crypto/benchmark.zig created+198
...@@ -0,0 +1,198 @@
1// zig run benchmark.zig --release-fast --override-std-dir ..
2
3const builtin = @import("builtin");
4const std = @import("../std.zig");
5const time = std.time;
6const Timer = time.Timer;
7const crypto = std.crypto;
8
9const KiB = 1024;
10const MiB = 1024 * KiB;
11
12var prng = std.rand.DefaultPrng.init(0);
13
14const Crypto = struct {
15 ty: type,
16 name: []const u8,
17};
18
19const hashes = [_]Crypto{
20 Crypto{ .ty = crypto.Md5, .name = "md5" },
21 Crypto{ .ty = crypto.Sha1, .name = "sha1" },
22 Crypto{ .ty = crypto.Sha256, .name = "sha256" },
23 Crypto{ .ty = crypto.Sha512, .name = "sha512" },
24 Crypto{ .ty = crypto.Sha3_256, .name = "sha3-256" },
25 Crypto{ .ty = crypto.Sha3_512, .name = "sha3-512" },
26 Crypto{ .ty = crypto.Blake2s256, .name = "blake2s" },
27 Crypto{ .ty = crypto.Blake2b512, .name = "blake2b" },
28};
29
30pub fn benchmarkHash(comptime Hash: var, comptime bytes: comptime_int) !u64 {
31 var h = Hash.init();
32
33 var block: [Hash.digest_length]u8 = undefined;
34 prng.random.bytes(block[0..]);
35
36 var offset: usize = 0;
37 var timer = try Timer.start();
38 const start = timer.lap();
39 while (offset < bytes) : (offset += block.len) {
40 h.update(block[0..]);
41 }
42 const end = timer.read();
43
44 const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
45 const throughput = @floatToInt(u64, bytes / elapsed_s);
46
47 return throughput;
48}
49
50const macs = [_]Crypto{
51 Crypto{ .ty = crypto.Poly1305, .name = "poly1305" },
52 Crypto{ .ty = crypto.HmacMd5, .name = "hmac-md5" },
53 Crypto{ .ty = crypto.HmacSha1, .name = "hmac-sha1" },
54 Crypto{ .ty = crypto.HmacSha256, .name = "hmac-sha256" },
55};
56
57pub fn benchmarkMac(comptime Mac: var, comptime bytes: comptime_int) !u64 {
58 std.debug.assert(32 >= Mac.mac_length and 32 >= Mac.minimum_key_length);
59
60 var in: [1 * MiB]u8 = undefined;
61 prng.random.bytes(in[0..]);
62
63 var key: [32]u8 = undefined;
64 prng.random.bytes(key[0..]);
65
66 var offset: usize = 0;
67 var timer = try Timer.start();
68 const start = timer.lap();
69 while (offset < bytes) : (offset += in.len) {
70 Mac.create(key[0..], in[0..], key);
71 }
72 const end = timer.read();
73
74 const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
75 const throughput = @floatToInt(u64, bytes / elapsed_s);
76
77 return throughput;
78}
79
80const exchanges = [_]Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }};
81
82pub fn benchmarkKeyExchange(comptime DhKeyExchange: var, comptime exchange_count: comptime_int) !u64 {
83 std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length);
84
85 var in: [DhKeyExchange.minimum_key_length]u8 = undefined;
86 prng.random.bytes(in[0..]);
87
88 var out: [DhKeyExchange.minimum_key_length]u8 = undefined;
89 prng.random.bytes(out[0..]);
90
91 var offset: usize = 0;
92 var timer = try Timer.start();
93 const start = timer.lap();
94 {
95 var i: usize = 0;
96 while (i < exchange_count) : (i += 1) {
97 _ = DhKeyExchange.create(out[0..], out, in);
98 }
99 }
100 const end = timer.read();
101
102 const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
103 const throughput = @floatToInt(u64, exchange_count / elapsed_s);
104
105 return throughput;
106}
107
108fn usage() void {
109 std.debug.warn(
110 \\throughput_test [options]
111 \\
112 \\Options:
113 \\ --filter [test-name]
114 \\ --seed [int]
115 \\ --help
116 \\
117 );
118}
119
120fn mode(comptime x: comptime_int) comptime_int {
121 return if (builtin.mode == builtin.Mode.Debug) x / 64 else x;
122}
123
124// TODO(#1358): Replace with builtin formatted padding when available.
125fn printPad(stdout: var, s: []const u8) !void {
126 var i: usize = 0;
127 while (i < 12 - s.len) : (i += 1) {
128 try stdout.print(" ");
129 }
130 try stdout.print("{}", s);
131}
132
133pub fn main() !void {
134 var stdout_file = try std.io.getStdOut();
135 var stdout_out_stream = stdout_file.outStream();
136 const stdout = &stdout_out_stream.stream;
137
138 var buffer: [1024]u8 = undefined;
139 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
140 const args = try std.process.argsAlloc(&fixed.allocator);
141
142 var filter: ?[]u8 = "";
143
144 var i: usize = 1;
145 while (i < args.len) : (i += 1) {
146 if (std.mem.eql(u8, args[i], "--mode")) {
147 try stdout.print("{}\n", builtin.mode);
148 return;
149 } else if (std.mem.eql(u8, args[i], "--seed")) {
150 i += 1;
151 if (i == args.len) {
152 usage();
153 std.os.exit(1);
154 }
155
156 const seed = try std.fmt.parseUnsigned(u32, args[i], 10);
157 prng.seed(seed);
158 } else if (std.mem.eql(u8, args[i], "--filter")) {
159 i += 1;
160 if (i == args.len) {
161 usage();
162 std.os.exit(1);
163 }
164
165 filter = args[i];
166 } else if (std.mem.eql(u8, args[i], "--help")) {
167 usage();
168 return;
169 } else {
170 usage();
171 std.os.exit(1);
172 }
173 }
174
175 inline for (hashes) |H| {
176 if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) {
177 const throughput = try benchmarkHash(H.ty, mode(32 * MiB));
178 try printPad(stdout, H.name);
179 try stdout.print(": {} MiB/s\n", throughput / (1 * MiB));
180 }
181 }
182
183 inline for (macs) |M| {
184 if (filter == null or std.mem.indexOf(u8, M.name, filter.?) != null) {
185 const throughput = try benchmarkMac(M.ty, mode(128 * MiB));
186 try printPad(stdout, M.name);
187 try stdout.print(": {} MiB/s\n", throughput / (1 * MiB));
188 }
189 }
190
191 inline for (exchanges) |E| {
192 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
193 const throughput = try benchmarkKeyExchange(E.ty, mode(1000));
194 try printPad(stdout, E.name);
195 try stdout.print(": {} exchanges/s\n", throughput);
196 }
197 }
198}
std/crypto/blake2.zig+2-2
...@@ -269,8 +269,8 @@ pub const Blake2b512 = Blake2b(512);...@@ -269,8 +269,8 @@ pub const Blake2b512 = Blake2b(512);
269fn Blake2b(comptime out_len: usize) type {269fn Blake2b(comptime out_len: usize) type {
270 return struct {270 return struct {
271 const Self = @This();271 const Self = @This();
272 const block_length = 128;272 pub const block_length = 128;
273 const digest_length = out_len / 8;273 pub const digest_length = out_len / 8;
274274
275 const iv = [8]u64{275 const iv = [8]u64{
276 0x6a09e667f3bcc908,276 0x6a09e667f3bcc908,
std/crypto/sha2.zig+2-2
...@@ -420,8 +420,8 @@ pub const Sha512 = Sha2_64(Sha512Params);...@@ -420,8 +420,8 @@ pub const Sha512 = Sha2_64(Sha512Params);
420fn Sha2_64(comptime params: Sha2Params64) type {420fn Sha2_64(comptime params: Sha2Params64) type {
421 return struct {421 return struct {
422 const Self = @This();422 const Self = @This();
423 const block_length = 128;423 pub const block_length = 128;
424 const digest_length = params.out_len / 8;424 pub const digest_length = params.out_len / 8;
425425
426 s: [8]u64,426 s: [8]u64,
427 // Streaming Cache427 // Streaming Cache
std/crypto/throughput_test.zig deleted-193
...@@ -1,193 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const time = std.time;
4const Timer = time.Timer;
5const crypto = @import("../crypto.zig");
6
7const KiB = 1024;
8const MiB = 1024 * KiB;
9
10var prng = std.rand.DefaultPrng.init(0);
11
12const Crypto = struct {
13 ty: type,
14 name: []const u8,
15};
16
17const hashes = []Crypto{
18 Crypto{ .ty = crypto.Md5, .name = "md5" },
19 Crypto{ .ty = crypto.Sha1, .name = "sha1" },
20 Crypto{ .ty = crypto.Sha256, .name = "sha256" },
21 Crypto{ .ty = crypto.Sha512, .name = "sha512" },
22 Crypto{ .ty = crypto.Sha3_256, .name = "sha3-256" },
23 Crypto{ .ty = crypto.Sha3_512, .name = "sha3-512" },
24 Crypto{ .ty = crypto.Blake2s256, .name = "blake2s" },
25 Crypto{ .ty = crypto.Blake2b512, .name = "blake2b" },
26};
27
28pub fn benchmarkHash(comptime Hash: var, comptime bytes: comptime_int) !u64 {
29 var h = Hash.init();
30
31 var block: [Hash.digest_length]u8 = undefined;
32 prng.random.bytes(block[0..]);
33
34 var offset: usize = 0;
35 var timer = try Timer.start();
36 const start = timer.lap();
37 while (offset < bytes) : (offset += block.len) {
38 h.update(block[0..]);
39 }
40 const end = timer.read();
41
42 const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
43 const throughput = @floatToInt(u64, bytes / elapsed_s);
44
45 return throughput;
46}
47
48const macs = []Crypto{
49 Crypto{ .ty = crypto.Poly1305, .name = "poly1305" },
50 Crypto{ .ty = crypto.HmacMd5, .name = "hmac-md5" },
51 Crypto{ .ty = crypto.HmacSha1, .name = "hmac-sha1" },
52 Crypto{ .ty = crypto.HmacSha256, .name = "hmac-sha256" },
53};
54
55pub fn benchmarkMac(comptime Mac: var, comptime bytes: comptime_int) !u64 {
56 std.debug.assert(32 >= Mac.mac_length and 32 >= Mac.minimum_key_length);
57
58 var in: [1 * MiB]u8 = undefined;
59 prng.random.bytes(in[0..]);
60
61 var key: [32]u8 = undefined;
62 prng.random.bytes(key[0..]);
63
64 var offset: usize = 0;
65 var timer = try Timer.start();
66 const start = timer.lap();
67 while (offset < bytes) : (offset += in.len) {
68 Mac.create(key[0..], in[0..], key);
69 }
70 const end = timer.read();
71
72 const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
73 const throughput = @floatToInt(u64, bytes / elapsed_s);
74
75 return throughput;
76}
77
78const exchanges = []Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }};
79
80pub fn benchmarkKeyExchange(comptime DhKeyExchange: var, comptime exchange_count: comptime_int) !u64 {
81 std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length);
82
83 var in: [DhKeyExchange.minimum_key_length]u8 = undefined;
84 prng.random.bytes(in[0..]);
85
86 var out: [DhKeyExchange.minimum_key_length]u8 = undefined;
87 prng.random.bytes(out[0..]);
88
89 var offset: usize = 0;
90 var timer = try Timer.start();
91 const start = timer.lap();
92 {
93 var i: usize = 0;
94 while (i < exchange_count) : (i += 1) {
95 _ = DhKeyExchange.create(out[0..], out, in);
96 }
97 }
98 const end = timer.read();
99
100 const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
101 const throughput = @floatToInt(u64, exchange_count / elapsed_s);
102
103 return throughput;
104}
105
106fn usage() void {
107 std.debug.warn(
108 \\throughput_test [options]
109 \\
110 \\Options:
111 \\ --filter [test-name]
112 \\ --seed [int]
113 \\ --help
114 \\
115 );
116}
117
118fn mode(comptime x: comptime_int) comptime_int {
119 return if (builtin.mode == builtin.Mode.Debug) x / 64 else x;
120}
121
122// TODO(#1358): Replace with builtin formatted padding when available.
123fn printPad(stdout: var, s: []const u8) !void {
124 var i: usize = 0;
125 while (i < 12 - s.len) : (i += 1) {
126 try stdout.print(" ");
127 }
128 try stdout.print("{}", s);
129}
130
131pub fn main() !void {
132 var stdout_file = try std.io.getStdOut();
133 var stdout_out_stream = stdout_file.outStream();
134 const stdout = &stdout_out_stream.stream;
135
136 var buffer: [1024]u8 = undefined;
137 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
138 const args = try std.os.argsAlloc(&fixed.allocator);
139
140 var filter: ?[]u8 = "";
141
142 var i: usize = 1;
143 while (i < args.len) : (i += 1) {
144 if (std.mem.eql(u8, args[i], "--seed")) {
145 i += 1;
146 if (i == args.len) {
147 usage();
148 std.os.exit(1);
149 }
150
151 const seed = try std.fmt.parseUnsigned(u32, args[i], 10);
152 prng.seed(seed);
153 } else if (std.mem.eql(u8, args[i], "--filter")) {
154 i += 1;
155 if (i == args.len) {
156 usage();
157 std.os.exit(1);
158 }
159
160 filter = args[i];
161 } else if (std.mem.eql(u8, args[i], "--help")) {
162 usage();
163 return;
164 } else {
165 usage();
166 std.os.exit(1);
167 }
168 }
169
170 inline for (hashes) |H| {
171 if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) {
172 const throughput = try benchmarkHash(H.ty, mode(32 * MiB));
173 try printPad(stdout, H.name);
174 try stdout.print(": {} MiB/s\n", throughput / (1 * MiB));
175 }
176 }
177
178 inline for (macs) |M| {
179 if (filter == null or std.mem.indexOf(u8, M.name, filter.?) != null) {
180 const throughput = try benchmarkMac(M.ty, mode(128 * MiB));
181 try printPad(stdout, M.name);
182 try stdout.print(": {} MiB/s\n", throughput / (1 * MiB));
183 }
184 }
185
186 inline for (exchanges) |E| {
187 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
188 const throughput = try benchmarkKeyExchange(E.ty, mode(1000));
189 try printPad(stdout, E.name);
190 try stdout.print(": {} exchanges/s\n", throughput);
191 }
192 }
193}
std/event/fs.zig+15-5
...@@ -719,6 +719,16 @@ pub const WatchEventId = enum {...@@ -719,6 +719,16 @@ pub const WatchEventId = enum {
719 Delete,719 Delete,
720};720};
721721
722fn eqlString(a: []const u16, b: []const u16) bool {
723 if (a.len != b.len) return false;
724 if (a.ptr == b.ptr) return true;
725 return mem.compare(u16, a, b) == .Equal;
726}
727
728fn hashString(s: []const u16) u32 {
729 return @truncate(u32, std.hash.Wyhash.hash(0, @sliceToBytes(s)));
730}
731
722//pub const WatchEventError = error{732//pub const WatchEventError = error{
723// UserResourceLimitReached,733// UserResourceLimitReached,
724// SystemResources,734// SystemResources,
...@@ -736,7 +746,7 @@ pub const WatchEventId = enum {...@@ -736,7 +746,7 @@ pub const WatchEventId = enum {
736// file_table: FileTable,746// file_table: FileTable,
737// table_lock: event.Lock,747// table_lock: event.Lock,
738//748//
739// const FileTable = std.AutoHashMap([]const u8, *Put);749// const FileTable = std.StringHashmap(*Put);
740// const Put = struct {750// const Put = struct {
741// putter: anyframe,751// putter: anyframe,
742// value_ptr: *V,752// value_ptr: *V,
...@@ -755,8 +765,8 @@ pub const WatchEventId = enum {...@@ -755,8 +765,8 @@ pub const WatchEventId = enum {
755// all_putters: std.atomic.Queue(anyframe),765// all_putters: std.atomic.Queue(anyframe),
756// ref_count: std.atomic.Int(usize),766// ref_count: std.atomic.Int(usize),
757//767//
758// const DirTable = std.AutoHashMap([]const u8, *Dir);768// const DirTable = std.StringHashMap(*Dir);
759// const FileTable = std.AutoHashMap([]const u16, V);769// const FileTable = std.HashMap([]const u16, V, hashString, eqlString);
760//770//
761// const Dir = struct {771// const Dir = struct {
762// putter: anyframe,772// putter: anyframe,
...@@ -772,7 +782,7 @@ pub const WatchEventId = enum {...@@ -772,7 +782,7 @@ pub const WatchEventId = enum {
772// table_lock: event.Lock,782// table_lock: event.Lock,
773//783//
774// const WdTable = std.AutoHashMap(i32, Dir);784// const WdTable = std.AutoHashMap(i32, Dir);
775// const FileTable = std.AutoHashMap([]const u8, V);785// const FileTable = std.StringHashMap(V);
776//786//
777// const Dir = struct {787// const Dir = struct {
778// dirname: []const u8,788// dirname: []const u8,
...@@ -780,7 +790,7 @@ pub const WatchEventId = enum {...@@ -780,7 +790,7 @@ pub const WatchEventId = enum {
780// };790// };
781// };791// };
782//792//
783// const FileToHandle = std.AutoHashMap([]const u8, anyframe);793// const FileToHandle = std.StringHashMap(anyframe);
784//794//
785// const Self = @This();795// const Self = @This();
786//796//
std/hash/auto_hash.zig+229-62
...@@ -1,11 +1,79 @@...@@ -1,11 +1,79 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;
3const mem = std.mem;4const mem = std.mem;
4const meta = std.meta;5const meta = std.meta;
56
7/// Describes how pointer types should be hashed.
8pub const HashStrategy = enum {
9 /// Do not follow pointers, only hash their value.
10 Shallow,
11
12 /// Follow pointers, hash the pointee content.
13 /// Only dereferences one level, ie. it is changed into .Shallow when a
14 /// pointer type is encountered.
15 Deep,
16
17 /// Follow pointers, hash the pointee content.
18 /// Dereferences all pointers encountered.
19 /// Assumes no cycle.
20 DeepRecursive,
21};
22
23/// Helper function to hash a pointer and mutate the strategy if needed.
24pub fn hashPointer(hasher: var, key: var, comptime strat: HashStrategy) void {
25 const info = @typeInfo(@typeOf(key));
26
27 switch (info.Pointer.size) {
28 builtin.TypeInfo.Pointer.Size.One => switch (strat) {
29 .Shallow => hash(hasher, @ptrToInt(key), .Shallow),
30 .Deep => hash(hasher, key.*, .Shallow),
31 .DeepRecursive => hash(hasher, key.*, .DeepRecursive),
32 },
33
34 builtin.TypeInfo.Pointer.Size.Slice => switch (strat) {
35 .Shallow => {
36 hashPointer(hasher, key.ptr, .Shallow);
37 hash(hasher, key.len, .Shallow);
38 },
39 .Deep => hashArray(hasher, key, .Shallow),
40 .DeepRecursive => hashArray(hasher, key, .DeepRecursive),
41 },
42
43 builtin.TypeInfo.Pointer.Size.Many,
44 builtin.TypeInfo.Pointer.Size.C,
45 => switch (strat) {
46 .Shallow => hash(hasher, @ptrToInt(key), .Shallow),
47 else => @compileError(
48 \\ unknown-length pointers and C pointers cannot be hashed deeply.
49 \\ Consider providing your own hash function.
50 ),
51 },
52 }
53}
54
55/// Helper function to hash a set of contiguous objects, from an array or slice.
56pub fn hashArray(hasher: var, key: var, comptime strat: HashStrategy) void {
57 switch (strat) {
58 .Shallow => {
59 // TODO detect via a trait when Key has no padding bits to
60 // hash it as an array of bytes.
61 // Otherwise, hash every element.
62 for (key) |element| {
63 hash(hasher, element, .Shallow);
64 }
65 },
66 else => {
67 for (key) |element| {
68 hash(hasher, element, strat);
69 }
70 },
71 }
72}
73
6/// Provides generic hashing for any eligible type.74/// Provides generic hashing for any eligible type.
7/// Only hashes `key` itself, pointers are not followed.75/// Strategy is provided to determine if pointers should be followed or not.
8pub fn autoHash(hasher: var, key: var) void {76pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {
9 const Key = @typeOf(key);77 const Key = @typeOf(key);
10 switch (@typeInfo(Key)) {78 switch (@typeInfo(Key)) {
11 .NoReturn,79 .NoReturn,
...@@ -26,35 +94,18 @@ pub fn autoHash(hasher: var, key: var) void {...@@ -26,35 +94,18 @@ pub fn autoHash(hasher: var, key: var) void {
26 // TODO Check if the situation is better after #561 is resolved.94 // TODO Check if the situation is better after #561 is resolved.
27 .Int => @inlineCall(hasher.update, std.mem.asBytes(&key)),95 .Int => @inlineCall(hasher.update, std.mem.asBytes(&key)),
2896
29 .Float => |info| autoHash(hasher, @bitCast(@IntType(false, info.bits), key)),97 .Float => |info| hash(hasher, @bitCast(@IntType(false, info.bits), key), strat),
3098
31 .Bool => autoHash(hasher, @boolToInt(key)),99 .Bool => hash(hasher, @boolToInt(key), strat),
32 .Enum => autoHash(hasher, @enumToInt(key)),100 .Enum => hash(hasher, @enumToInt(key), strat),
33 .ErrorSet => autoHash(hasher, @errorToInt(key)),101 .ErrorSet => hash(hasher, @errorToInt(key), strat),
34 .AnyFrame, .Fn => autoHash(hasher, @ptrToInt(key)),102 .AnyFrame, .Fn => hash(hasher, @ptrToInt(key), strat),
35103
36 .Pointer => |info| switch (info.size) {104 .Pointer => @inlineCall(hashPointer, hasher, key, strat),
37 builtin.TypeInfo.Pointer.Size.One,
38 builtin.TypeInfo.Pointer.Size.Many,
39 builtin.TypeInfo.Pointer.Size.C,
40 => autoHash(hasher, @ptrToInt(key)),
41105
42 builtin.TypeInfo.Pointer.Size.Slice => {106 .Optional => if (key) |k| hash(hasher, k, strat),
43 autoHash(hasher, key.ptr);
44 autoHash(hasher, key.len);
45 },
46 },
47
48 .Optional => if (key) |k| autoHash(hasher, k),
49107
50 .Array => {108 .Array => hashArray(hasher, key, strat),
51 // TODO detect via a trait when Key has no padding bits to
52 // hash it as an array of bytes.
53 // Otherwise, hash every element.
54 for (key) |element| {
55 autoHash(hasher, element);
56 }
57 },
58109
59 .Vector => |info| {110 .Vector => |info| {
60 if (info.child.bit_count % 8 == 0) {111 if (info.child.bit_count % 8 == 0) {
...@@ -67,7 +118,7 @@ pub fn autoHash(hasher: var, key: var) void {...@@ -67,7 +118,7 @@ pub fn autoHash(hasher: var, key: var) void {
67 const array: [info.len]info.child = key;118 const array: [info.len]info.child = key;
68 comptime var i: u32 = 0;119 comptime var i: u32 = 0;
69 inline while (i < info.len) : (i += 1) {120 inline while (i < info.len) : (i += 1) {
70 autoHash(hasher, array[i]);121 hash(hasher, array[i], strat);
71 }122 }
72 }123 }
73 },124 },
...@@ -79,19 +130,19 @@ pub fn autoHash(hasher: var, key: var) void {...@@ -79,19 +130,19 @@ pub fn autoHash(hasher: var, key: var) void {
79 inline for (info.fields) |field| {130 inline for (info.fields) |field| {
80 // We reuse the hash of the previous field as the seed for the131 // We reuse the hash of the previous field as the seed for the
81 // next one so that they're dependant.132 // next one so that they're dependant.
82 autoHash(hasher, @field(key, field.name));133 hash(hasher, @field(key, field.name), strat);
83 }134 }
84 },135 },
85136
86 .Union => |info| blk: {137 .Union => |info| blk: {
87 if (info.tag_type) |tag_type| {138 if (info.tag_type) |tag_type| {
88 const tag = meta.activeTag(key);139 const tag = meta.activeTag(key);
89 const s = autoHash(hasher, tag);140 const s = hash(hasher, tag, strat);
90 inline for (info.fields) |field| {141 inline for (info.fields) |field| {
91 const enum_field = field.enum_field.?;142 const enum_field = field.enum_field.?;
92 if (enum_field.value == @enumToInt(tag)) {143 if (enum_field.value == @enumToInt(tag)) {
93 autoHash(hasher, @field(key, enum_field.name));144 hash(hasher, @field(key, enum_field.name), strat);
94 // TODO use a labelled break when it does not crash the compiler.145 // TODO use a labelled break when it does not crash the compiler. cf #2908
95 // break :blk;146 // break :blk;
96 return;147 return;
97 }148 }
...@@ -102,25 +153,102 @@ pub fn autoHash(hasher: var, key: var) void {...@@ -102,25 +153,102 @@ pub fn autoHash(hasher: var, key: var) void {
102153
103 .ErrorUnion => blk: {154 .ErrorUnion => blk: {
104 const payload = key catch |err| {155 const payload = key catch |err| {
105 autoHash(hasher, err);156 hash(hasher, err, strat);
106 break :blk;157 break :blk;
107 };158 };
108 autoHash(hasher, payload);159 hash(hasher, payload, strat);
109 },160 },
110 }161 }
111}162}
112163
164/// Provides generic hashing for any eligible type.
165/// Only hashes `key` itself, pointers are not followed.
166/// Slices are rejected to avoid ambiguity on the user's intention.
167pub fn autoHash(hasher: var, key: var) void {
168 const Key = @typeOf(key);
169 if (comptime meta.trait.isSlice(Key)) {
170 comptime assert(@hasDecl(std, "StringHashMap")); // detect when the following message needs updated
171 const extra_help = if (Key == []const u8)
172 " Consider std.StringHashMap for hashing the contents of []const u8."
173 else
174 "";
175
176 @compileError("std.auto_hash.autoHash does not allow slices (here " ++ @typeName(Key) ++
177 ") because the intent is unclear. Consider using std.auto_hash.hash or providing your own hash function instead." ++
178 extra_help);
179 }
180
181 hash(hasher, key, .Shallow);
182}
183
113const testing = std.testing;184const testing = std.testing;
114const Wyhash = std.hash.Wyhash;185const Wyhash = std.hash.Wyhash;
115186
116fn testAutoHash(key: var) u64 {187fn testHash(key: var) u64 {
188 // Any hash could be used here, for testing autoHash.
189 var hasher = Wyhash.init(0);
190 hash(&hasher, key, .Shallow);
191 return hasher.final();
192}
193
194fn testHashShallow(key: var) u64 {
195 // Any hash could be used here, for testing autoHash.
196 var hasher = Wyhash.init(0);
197 hash(&hasher, key, .Shallow);
198 return hasher.final();
199}
200
201fn testHashDeep(key: var) u64 {
117 // Any hash could be used here, for testing autoHash.202 // Any hash could be used here, for testing autoHash.
118 var hasher = Wyhash.init(0);203 var hasher = Wyhash.init(0);
119 autoHash(&hasher, key);204 hash(&hasher, key, .Deep);
120 return hasher.final();205 return hasher.final();
121}206}
122207
123test "autoHash slice" {208fn testHashDeepRecursive(key: var) u64 {
209 // Any hash could be used here, for testing autoHash.
210 var hasher = Wyhash.init(0);
211 hash(&hasher, key, .DeepRecursive);
212 return hasher.final();
213}
214
215test "hash pointer" {
216 const array = [_]u32{ 123, 123, 123 };
217 const a = &array[0];
218 const b = &array[1];
219 const c = &array[2];
220 const d = a;
221
222 testing.expect(testHashShallow(a) == testHashShallow(d));
223 testing.expect(testHashShallow(a) != testHashShallow(c));
224 testing.expect(testHashShallow(a) != testHashShallow(b));
225
226 testing.expect(testHashDeep(a) == testHashDeep(a));
227 testing.expect(testHashDeep(a) == testHashDeep(c));
228 testing.expect(testHashDeep(a) == testHashDeep(b));
229
230 testing.expect(testHashDeepRecursive(a) == testHashDeepRecursive(a));
231 testing.expect(testHashDeepRecursive(a) == testHashDeepRecursive(c));
232 testing.expect(testHashDeepRecursive(a) == testHashDeepRecursive(b));
233}
234
235test "hash slice shallow" {
236 // Allocate one array dynamically so that we're assured it is not merged
237 // with the other by the optimization passes.
238 const array1 = try std.heap.direct_allocator.create([6]u32);
239 defer std.heap.direct_allocator.destroy(array1);
240 array1.* = [_]u32{ 1, 2, 3, 4, 5, 6 };
241 const array2 = [_]u32{ 1, 2, 3, 4, 5, 6 };
242 const a = array1[0..];
243 const b = array2[0..];
244 const c = array1[0..3];
245 testing.expect(testHashShallow(a) == testHashShallow(a));
246 testing.expect(testHashShallow(a) != testHashShallow(array1));
247 testing.expect(testHashShallow(a) != testHashShallow(b));
248 testing.expect(testHashShallow(a) != testHashShallow(c));
249}
250
251test "hash slice deep" {
124 // Allocate one array dynamically so that we're assured it is not merged252 // Allocate one array dynamically so that we're assured it is not merged
125 // with the other by the optimization passes.253 // with the other by the optimization passes.
126 const array1 = try std.heap.direct_allocator.create([6]u32);254 const array1 = try std.heap.direct_allocator.create([6]u32);
...@@ -130,23 +258,62 @@ test "autoHash slice" {...@@ -130,23 +258,62 @@ test "autoHash slice" {
130 const a = array1[0..];258 const a = array1[0..];
131 const b = array2[0..];259 const b = array2[0..];
132 const c = array1[0..3];260 const c = array1[0..3];
133 testing.expect(testAutoHash(a) == testAutoHash(a));261 testing.expect(testHashDeep(a) == testHashDeep(a));
134 testing.expect(testAutoHash(a) != testAutoHash(array1));262 testing.expect(testHashDeep(a) == testHashDeep(array1));
135 testing.expect(testAutoHash(a) != testAutoHash(b));263 testing.expect(testHashDeep(a) == testHashDeep(b));
136 testing.expect(testAutoHash(a) != testAutoHash(c));264 testing.expect(testHashDeep(a) != testHashDeep(c));
265}
266
267test "hash struct deep" {
268 const Foo = struct {
269 a: u32,
270 b: f64,
271 c: *bool,
272
273 const Self = @This();
274
275 pub fn init(allocator: *mem.Allocator, a_: u32, b_: f64, c_: bool) !Self {
276 const ptr = try allocator.create(bool);
277 ptr.* = c_;
278 return Self{ .a = a_, .b = b_, .c = ptr };
279 }
280 };
281
282 const allocator = std.heap.direct_allocator;
283 const foo = try Foo.init(allocator, 123, 1.0, true);
284 const bar = try Foo.init(allocator, 123, 1.0, true);
285 const baz = try Foo.init(allocator, 123, 1.0, false);
286 defer allocator.destroy(foo.c);
287 defer allocator.destroy(bar.c);
288 defer allocator.destroy(baz.c);
289
290 testing.expect(testHashDeep(foo) == testHashDeep(bar));
291 testing.expect(testHashDeep(foo) != testHashDeep(baz));
292 testing.expect(testHashDeep(bar) != testHashDeep(baz));
293
294 var hasher = Wyhash.init(0);
295 const h = testHashDeep(foo);
296 autoHash(&hasher, foo.a);
297 autoHash(&hasher, foo.b);
298 autoHash(&hasher, foo.c.*);
299 testing.expectEqual(h, hasher.final());
300
301 const h2 = testHashDeepRecursive(&foo);
302 testing.expect(h2 != testHashDeep(&foo));
303 testing.expect(h2 == testHashDeep(foo));
137}304}
138305
139test "testAutoHash optional" {306test "testHash optional" {
140 const a: ?u32 = 123;307 const a: ?u32 = 123;
141 const b: ?u32 = null;308 const b: ?u32 = null;
142 testing.expectEqual(testAutoHash(a), testAutoHash(u32(123)));309 testing.expectEqual(testHash(a), testHash(u32(123)));
143 testing.expect(testAutoHash(a) != testAutoHash(b));310 testing.expect(testHash(a) != testHash(b));
144 testing.expectEqual(testAutoHash(b), 0);311 testing.expectEqual(testHash(b), 0);
145}312}
146313
147test "testAutoHash array" {314test "testHash array" {
148 const a = [_]u32{ 1, 2, 3 };315 const a = [_]u32{ 1, 2, 3 };
149 const h = testAutoHash(a);316 const h = testHash(a);
150 var hasher = Wyhash.init(0);317 var hasher = Wyhash.init(0);
151 autoHash(&hasher, u32(1));318 autoHash(&hasher, u32(1));
152 autoHash(&hasher, u32(2));319 autoHash(&hasher, u32(2));
...@@ -154,14 +321,14 @@ test "testAutoHash array" {...@@ -154,14 +321,14 @@ test "testAutoHash array" {
154 testing.expectEqual(h, hasher.final());321 testing.expectEqual(h, hasher.final());
155}322}
156323
157test "testAutoHash struct" {324test "testHash struct" {
158 const Foo = struct {325 const Foo = struct {
159 a: u32 = 1,326 a: u32 = 1,
160 b: u32 = 2,327 b: u32 = 2,
161 c: u32 = 3,328 c: u32 = 3,
162 };329 };
163 const f = Foo{};330 const f = Foo{};
164 const h = testAutoHash(f);331 const h = testHash(f);
165 var hasher = Wyhash.init(0);332 var hasher = Wyhash.init(0);
166 autoHash(&hasher, u32(1));333 autoHash(&hasher, u32(1));
167 autoHash(&hasher, u32(2));334 autoHash(&hasher, u32(2));
...@@ -169,7 +336,7 @@ test "testAutoHash struct" {...@@ -169,7 +336,7 @@ test "testAutoHash struct" {
169 testing.expectEqual(h, hasher.final());336 testing.expectEqual(h, hasher.final());
170}337}
171338
172test "testAutoHash union" {339test "testHash union" {
173 const Foo = union(enum) {340 const Foo = union(enum) {
174 A: u32,341 A: u32,
175 B: f32,342 B: f32,
...@@ -179,24 +346,24 @@ test "testAutoHash union" {...@@ -179,24 +346,24 @@ test "testAutoHash union" {
179 const a = Foo{ .A = 18 };346 const a = Foo{ .A = 18 };
180 var b = Foo{ .B = 12.34 };347 var b = Foo{ .B = 12.34 };
181 const c = Foo{ .C = 18 };348 const c = Foo{ .C = 18 };
182 testing.expect(testAutoHash(a) == testAutoHash(a));349 testing.expect(testHash(a) == testHash(a));
183 testing.expect(testAutoHash(a) != testAutoHash(b));350 testing.expect(testHash(a) != testHash(b));
184 testing.expect(testAutoHash(a) != testAutoHash(c));351 testing.expect(testHash(a) != testHash(c));
185352
186 b = Foo{ .A = 18 };353 b = Foo{ .A = 18 };
187 testing.expect(testAutoHash(a) == testAutoHash(b));354 testing.expect(testHash(a) == testHash(b));
188}355}
189356
190test "testAutoHash vector" {357test "testHash vector" {
191 const a: @Vector(4, u32) = [_]u32{ 1, 2, 3, 4 };358 const a: @Vector(4, u32) = [_]u32{ 1, 2, 3, 4 };
192 const b: @Vector(4, u32) = [_]u32{ 1, 2, 3, 5 };359 const b: @Vector(4, u32) = [_]u32{ 1, 2, 3, 5 };
193 const c: @Vector(4, u31) = [_]u31{ 1, 2, 3, 4 };360 const c: @Vector(4, u31) = [_]u31{ 1, 2, 3, 4 };
194 testing.expect(testAutoHash(a) == testAutoHash(a));361 testing.expect(testHash(a) == testHash(a));
195 testing.expect(testAutoHash(a) != testAutoHash(b));362 testing.expect(testHash(a) != testHash(b));
196 testing.expect(testAutoHash(a) != testAutoHash(c));363 testing.expect(testHash(a) != testHash(c));
197}364}
198365
199test "testAutoHash error union" {366test "testHash error union" {
200 const Errors = error{Test};367 const Errors = error{Test};
201 const Foo = struct {368 const Foo = struct {
202 a: u32 = 1,369 a: u32 = 1,
...@@ -205,7 +372,7 @@ test "testAutoHash error union" {...@@ -205,7 +372,7 @@ test "testAutoHash error union" {
205 };372 };
206 const f = Foo{};373 const f = Foo{};
207 const g: Errors!Foo = Errors.Test;374 const g: Errors!Foo = Errors.Test;
208 testing.expect(testAutoHash(f) != testAutoHash(g));375 testing.expect(testHash(f) != testHash(g));
209 testing.expect(testAutoHash(f) == testAutoHash(Foo{}));376 testing.expect(testHash(f) == testHash(Foo{}));
210 testing.expect(testAutoHash(g) == testAutoHash(Errors.Test));377 testing.expect(testHash(g) == testHash(Errors.Test));
211}378}
std/hash/benchmark.zig created+273
...@@ -0,0 +1,273 @@
1// zig run benchmark.zig --release-fast --override-std-dir ..
2
3const builtin = @import("builtin");
4const std = @import("std");
5const time = std.time;
6const Timer = time.Timer;
7const hash = std.hash;
8
9const KiB = 1024;
10const MiB = 1024 * KiB;
11const GiB = 1024 * MiB;
12
13var prng = std.rand.DefaultPrng.init(0);
14
15const Hash = struct {
16 ty: type,
17 name: []const u8,
18 has_iterative_api: bool = true,
19 init_u8s: ?[]const u8 = null,
20 init_u64: ?u64 = null,
21};
22
23const siphash_key = "0123456789abcdef";
24
25const hashes = [_]Hash{
26 Hash{
27 .ty = hash.Wyhash,
28 .name = "wyhash",
29 .init_u64 = 0,
30 },
31 Hash{
32 .ty = hash.SipHash64(1, 3),
33 .name = "siphash(1,3)",
34 .init_u8s = siphash_key,
35 },
36 Hash{
37 .ty = hash.SipHash64(2, 4),
38 .name = "siphash(2,4)",
39 .init_u8s = siphash_key,
40 },
41 Hash{
42 .ty = hash.Fnv1a_64,
43 .name = "fnv1a",
44 },
45 Hash{
46 .ty = hash.Adler32,
47 .name = "adler32",
48 },
49 Hash{
50 .ty = hash.crc.Crc32WithPoly(hash.crc.Polynomial.IEEE),
51 .name = "crc32-slicing-by-8",
52 },
53 Hash{
54 .ty = hash.crc.Crc32SmallWithPoly(hash.crc.Polynomial.IEEE),
55 .name = "crc32-half-byte-lookup",
56 },
57 Hash{
58 .ty = hash.CityHash32,
59 .name = "cityhash-32",
60 .has_iterative_api = false,
61 },
62 Hash{
63 .ty = hash.CityHash64,
64 .name = "cityhash-64",
65 .has_iterative_api = false,
66 },
67 Hash{
68 .ty = hash.Murmur2_32,
69 .name = "murmur2-32",
70 .has_iterative_api = false,
71 },
72 Hash{
73 .ty = hash.Murmur2_64,
74 .name = "murmur2-64",
75 .has_iterative_api = false,
76 },
77 Hash{
78 .ty = hash.Murmur3_32,
79 .name = "murmur3-32",
80 .has_iterative_api = false,
81 },
82};
83
84const Result = struct {
85 hash: u64,
86 throughput: u64,
87};
88
89const block_size: usize = 8 * 8192;
90
91pub fn benchmarkHash(comptime H: var, bytes: usize) !Result {
92 var h = blk: {
93 if (H.init_u8s) |init| {
94 break :blk H.ty.init(init);
95 }
96 if (H.init_u64) |init| {
97 break :blk H.ty.init(init);
98 }
99 break :blk H.ty.init();
100 };
101
102 var block: [block_size]u8 = undefined;
103 prng.random.bytes(block[0..]);
104
105 var offset: usize = 0;
106 var timer = try Timer.start();
107 const start = timer.lap();
108 while (offset < bytes) : (offset += block.len) {
109 h.update(block[0..]);
110 }
111 const end = timer.read();
112
113 const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
114 const throughput = @floatToInt(u64, @intToFloat(f64, bytes) / elapsed_s);
115
116 return Result{
117 .hash = h.final(),
118 .throughput = throughput,
119 };
120}
121
122pub fn benchmarkHashSmallKeys(comptime H: var, key_size: usize, bytes: usize) !Result {
123 const key_count = bytes / key_size;
124 var block: [block_size]u8 = undefined;
125 prng.random.bytes(block[0..]);
126
127 var i: usize = 0;
128 var timer = try Timer.start();
129 const start = timer.lap();
130
131 var sum: u64 = 0;
132 while (i < key_count) : (i += 1) {
133 const small_key = block[0..key_size];
134 sum +%= blk: {
135 if (H.init_u8s) |init| {
136 break :blk H.ty.hash(init, small_key);
137 }
138 if (H.init_u64) |init| {
139 break :blk H.ty.hash(init, small_key);
140 }
141 break :blk H.ty.hash(small_key);
142 };
143 }
144 const end = timer.read();
145
146 const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
147 const throughput = @floatToInt(u64, @intToFloat(f64, bytes) / elapsed_s);
148
149 return Result{
150 .hash = sum,
151 .throughput = throughput,
152 };
153}
154
155fn usage() void {
156 std.debug.warn(
157 \\throughput_test [options]
158 \\
159 \\Options:
160 \\ --filter [test-name]
161 \\ --seed [int]
162 \\ --count [int]
163 \\ --key-size [int]
164 \\ --iterative-only
165 \\ --help
166 \\
167 );
168}
169
170fn mode(comptime x: comptime_int) comptime_int {
171 return if (builtin.mode == builtin.Mode.Debug) x / 64 else x;
172}
173
174// TODO(#1358): Replace with builtin formatted padding when available.
175fn printPad(stdout: var, s: []const u8) !void {
176 var i: usize = 0;
177 while (i < 12 - s.len) : (i += 1) {
178 try stdout.print(" ");
179 }
180 try stdout.print("{}", s);
181}
182
183pub fn main() !void {
184 var stdout_file = try std.io.getStdOut();
185 var stdout_out_stream = stdout_file.outStream();
186 const stdout = &stdout_out_stream.stream;
187
188 var buffer: [1024]u8 = undefined;
189 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
190 const args = try std.process.argsAlloc(&fixed.allocator);
191
192 var filter: ?[]u8 = "";
193 var count: usize = mode(128 * MiB);
194 var key_size: usize = 32;
195 var seed: u32 = 0;
196 var test_iterative_only = false;
197
198 var i: usize = 1;
199 while (i < args.len) : (i += 1) {
200 if (std.mem.eql(u8, args[i], "--mode")) {
201 try stdout.print("{}\n", builtin.mode);
202 return;
203 } else if (std.mem.eql(u8, args[i], "--seed")) {
204 i += 1;
205 if (i == args.len) {
206 usage();
207 std.os.exit(1);
208 }
209
210 seed = try std.fmt.parseUnsigned(u32, args[i], 10);
211 // we seed later
212 } else if (std.mem.eql(u8, args[i], "--filter")) {
213 i += 1;
214 if (i == args.len) {
215 usage();
216 std.os.exit(1);
217 }
218
219 filter = args[i];
220 } else if (std.mem.eql(u8, args[i], "--count")) {
221 i += 1;
222 if (i == args.len) {
223 usage();
224 std.os.exit(1);
225 }
226
227 const c = try std.fmt.parseUnsigned(usize, args[i], 10);
228 count = c * MiB;
229 } else if (std.mem.eql(u8, args[i], "--key-size")) {
230 i += 1;
231 if (i == args.len) {
232 usage();
233 std.os.exit(1);
234 }
235
236 key_size = try std.fmt.parseUnsigned(usize, args[i], 10);
237 if (key_size > block_size) {
238 try stdout.print("key_size cannot exceed block size of {}\n", block_size);
239 std.os.exit(1);
240 }
241 } else if (std.mem.eql(u8, args[i], "--iterative-only")) {
242 test_iterative_only = true;
243 } else if (std.mem.eql(u8, args[i], "--help")) {
244 usage();
245 return;
246 } else {
247 usage();
248 std.os.exit(1);
249 }
250 }
251
252 inline for (hashes) |H| {
253 if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) {
254 if (!test_iterative_only or H.has_iterative_api) {
255 try stdout.print("{}\n", H.name);
256
257 // Always reseed prior to every call so we are hashing the same buffer contents.
258 // This allows easier comparison between different implementations.
259 if (H.has_iterative_api) {
260 prng.seed(seed);
261 const result = try benchmarkHash(H, count);
262 try stdout.print(" iterative: {:4} MiB/s [{x:0<16}]\n", result.throughput / (1 * MiB), result.hash);
263 }
264
265 if (!test_iterative_only) {
266 prng.seed(seed);
267 const result_small = try benchmarkHashSmallKeys(H, key_size, count);
268 try stdout.print(" small keys: {:4} MiB/s [{x:0<16}]\n", result_small.throughput / (1 * MiB), result_small.hash);
269 }
270 }
271 }
272 }
273}
std/hash/crc.zig+3-3
...@@ -10,9 +10,9 @@ const debug = std.debug;...@@ -10,9 +10,9 @@ const debug = std.debug;
10const testing = std.testing;10const testing = std.testing;
1111
12pub const Polynomial = struct {12pub const Polynomial = struct {
13 const IEEE = 0xedb88320;13 pub const IEEE = 0xedb88320;
14 const Castagnoli = 0x82f63b78;14 pub const Castagnoli = 0x82f63b78;
15 const Koopman = 0xeb31d82e;15 pub const Koopman = 0xeb31d82e;
16};16};
1717
18// IEEE is by far the most common CRC and so is aliased by default.18// IEEE is by far the most common CRC and so is aliased by default.
std/hash/siphash.zig+107-45
...@@ -21,7 +21,7 @@ pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type {...@@ -21,7 +21,7 @@ pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type {
21 return SipHash(u128, c_rounds, d_rounds);21 return SipHash(u128, c_rounds, d_rounds);
22}22}
2323
24fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {24fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {
25 assert(T == u64 or T == u128);25 assert(T == u64 or T == u128);
26 assert(c_rounds > 0 and d_rounds > 0);26 assert(c_rounds > 0 and d_rounds > 0);
2727
...@@ -34,10 +34,6 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -34,10 +34,6 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
34 v1: u64,34 v1: u64,
35 v2: u64,35 v2: u64,
36 v3: u64,36 v3: u64,
37
38 // streaming cache
39 buf: [8]u8,
40 buf_len: usize,
41 msg_len: u8,37 msg_len: u8,
4238
43 pub fn init(key: []const u8) Self {39 pub fn init(key: []const u8) Self {
...@@ -51,9 +47,6 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -51,9 +47,6 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
51 .v1 = k1 ^ 0x646f72616e646f6d,47 .v1 = k1 ^ 0x646f72616e646f6d,
52 .v2 = k0 ^ 0x6c7967656e657261,48 .v2 = k0 ^ 0x6c7967656e657261,
53 .v3 = k1 ^ 0x7465646279746573,49 .v3 = k1 ^ 0x7465646279746573,
54
55 .buf = undefined,
56 .buf_len = 0,
57 .msg_len = 0,50 .msg_len = 0,
58 };51 };
5952
...@@ -64,73 +57,66 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -64,73 +57,66 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
64 return d;57 return d;
65 }58 }
6659
67 pub fn update(d: *Self, b: []const u8) void {60 pub fn update(self: *Self, b: []const u8) void {
68 var off: usize = 0;61 std.debug.assert(b.len % 8 == 0);
69
70 // Partial from previous.
71 if (d.buf_len != 0 and d.buf_len + b.len > 8) {
72 off += 8 - d.buf_len;
73 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
74 d.round(d.buf[0..]);
75 d.buf_len = 0;
76 }
7762
78 // Full middle blocks.63 var off: usize = 0;
79 while (off + 8 <= b.len) : (off += 8) {64 while (off < b.len) : (off += 8) {
80 d.round(b[off .. off + 8]);65 @inlineCall(self.round, b[off .. off + 8]);
81 }66 }
8267
83 // Remainder for next pass.68 self.msg_len +%= @truncate(u8, b.len);
84 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
85 d.buf_len += @intCast(u8, b[off..].len);
86 d.msg_len +%= @truncate(u8, b.len);
87 }69 }
8870
89 pub fn final(d: *Self) T {71 pub fn final(self: *Self, b: []const u8) T {
90 // Padding72 std.debug.assert(b.len < 8);
91 mem.set(u8, d.buf[d.buf_len..], 0);73
92 d.buf[7] = d.msg_len;74 self.msg_len +%= @truncate(u8, b.len);
93 d.round(d.buf[0..]);75
76 var buf = [_]u8{0} ** 8;
77 mem.copy(u8, buf[0..], b[0..]);
78 buf[7] = self.msg_len;
79 self.round(buf[0..]);
9480
95 if (T == u128) {81 if (T == u128) {
96 d.v2 ^= 0xee;82 self.v2 ^= 0xee;
97 } else {83 } else {
98 d.v2 ^= 0xff;84 self.v2 ^= 0xff;
99 }85 }
10086
101 comptime var i: usize = 0;87 comptime var i: usize = 0;
102 inline while (i < d_rounds) : (i += 1) {88 inline while (i < d_rounds) : (i += 1) {
103 @inlineCall(sipRound, d);89 @inlineCall(sipRound, self);
104 }90 }
10591
106 const b1 = d.v0 ^ d.v1 ^ d.v2 ^ d.v3;92 const b1 = self.v0 ^ self.v1 ^ self.v2 ^ self.v3;
107 if (T == u64) {93 if (T == u64) {
108 return b1;94 return b1;
109 }95 }
11096
111 d.v1 ^= 0xdd;97 self.v1 ^= 0xdd;
11298
113 comptime var j: usize = 0;99 comptime var j: usize = 0;
114 inline while (j < d_rounds) : (j += 1) {100 inline while (j < d_rounds) : (j += 1) {
115 @inlineCall(sipRound, d);101 @inlineCall(sipRound, self);
116 }102 }
117103
118 const b2 = d.v0 ^ d.v1 ^ d.v2 ^ d.v3;104 const b2 = self.v0 ^ self.v1 ^ self.v2 ^ self.v3;
119 return (u128(b2) << 64) | b1;105 return (u128(b2) << 64) | b1;
120 }106 }
121107
122 fn round(d: *Self, b: []const u8) void {108 fn round(self: *Self, b: []const u8) void {
123 assert(b.len == 8);109 assert(b.len == 8);
124110
125 const m = mem.readIntSliceLittle(u64, b[0..]);111 const m = mem.readIntSliceLittle(u64, b[0..]);
126 d.v3 ^= m;112 self.v3 ^= m;
127113
128 comptime var i: usize = 0;114 comptime var i: usize = 0;
129 inline while (i < c_rounds) : (i += 1) {115 inline while (i < c_rounds) : (i += 1) {
130 @inlineCall(sipRound, d);116 @inlineCall(sipRound, self);
131 }117 }
132118
133 d.v0 ^= m;119 self.v0 ^= m;
134 }120 }
135121
136 fn sipRound(d: *Self) void {122 fn sipRound(d: *Self) void {
...@@ -151,9 +137,61 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -151,9 +137,61 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
151 }137 }
152138
153 pub fn hash(key: []const u8, input: []const u8) T {139 pub fn hash(key: []const u8, input: []const u8) T {
140 const aligned_len = input.len - (input.len % 8);
141
154 var c = Self.init(key);142 var c = Self.init(key);
155 c.update(input);143 @inlineCall(c.update, input[0..aligned_len]);
156 return c.final();144 return @inlineCall(c.final, input[aligned_len..]);
145 }
146 };
147}
148
149pub fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {
150 assert(T == u64 or T == u128);
151 assert(c_rounds > 0 and d_rounds > 0);
152
153 return struct {
154 const State = SipHashStateless(T, c_rounds, d_rounds);
155 const Self = @This();
156 const digest_size = 64;
157 const block_size = 64;
158
159 state: State,
160 buf: [8]u8,
161 buf_len: usize,
162
163 pub fn init(key: []const u8) Self {
164 return Self{
165 .state = State.init(key),
166 .buf = undefined,
167 .buf_len = 0,
168 };
169 }
170
171 pub fn update(self: *Self, b: []const u8) void {
172 var off: usize = 0;
173
174 if (self.buf_len != 0 and self.buf_len + b.len >= 8) {
175 off += 8 - self.buf_len;
176 mem.copy(u8, self.buf[self.buf_len..], b[0..off]);
177 self.state.update(self.buf[0..]);
178 self.buf_len = 0;
179 }
180
181 const remain_len = b.len - off;
182 const aligned_len = remain_len - (remain_len % 8);
183 self.state.update(b[off .. off + aligned_len]);
184
185 mem.copy(u8, self.buf[self.buf_len..], b[off + aligned_len ..]);
186 self.buf_len += @intCast(u8, b[off + aligned_len ..].len);
187 }
188
189 pub fn final(self: *Self) T {
190 return self.state.final(self.buf[0..self.buf_len]);
191 }
192
193 pub fn hash(key: []const u8, input: []const u8) T {
194 return State.hash(key, input);
157 }195 }
158 };196 };
159}197}
...@@ -237,7 +275,7 @@ test "siphash64-2-4 sanity" {...@@ -237,7 +275,7 @@ test "siphash64-2-4 sanity" {
237 buffer[i] = @intCast(u8, i);275 buffer[i] = @intCast(u8, i);
238276
239 const expected = mem.readIntLittle(u64, &vector);277 const expected = mem.readIntLittle(u64, &vector);
240 testing.expect(siphash.hash(test_key, buffer[0..i]) == expected);278 testing.expectEqual(siphash.hash(test_key, buffer[0..i]), expected);
241 }279 }
242}280}
243281
...@@ -316,6 +354,30 @@ test "siphash128-2-4 sanity" {...@@ -316,6 +354,30 @@ test "siphash128-2-4 sanity" {
316 buffer[i] = @intCast(u8, i);354 buffer[i] = @intCast(u8, i);
317355
318 const expected = mem.readIntLittle(u128, &vector);356 const expected = mem.readIntLittle(u128, &vector);
319 testing.expect(siphash.hash(test_key, buffer[0..i]) == expected);357 testing.expectEqual(siphash.hash(test_key, buffer[0..i]), expected);
358 }
359}
360
361test "iterative non-divisible update" {
362 var buf: [1024]u8 = undefined;
363 for (buf) |*e, i| {
364 e.* = @truncate(u8, i);
365 }
366
367 const key = "0x128dad08f12307";
368 const Siphash = SipHash64(2, 4);
369
370 var end: usize = 9;
371 while (end < buf.len) : (end += 9) {
372 const non_iterative_hash = Siphash.hash(key, buf[0..end]);
373
374 var wy = Siphash.init(key);
375 var i: usize = 0;
376 while (i < end) : (i += 7) {
377 wy.update(buf[i..std.math.min(i + 7, end)]);
378 }
379 const iterative_hash = wy.final();
380
381 std.testing.expectEqual(iterative_hash, non_iterative_hash);
320 }382 }
321}383}
std/hash/throughput_test.zig deleted-148
...@@ -1,148 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const time = std.time;
4const Timer = time.Timer;
5const hash = std.hash;
6
7const KiB = 1024;
8const MiB = 1024 * KiB;
9const GiB = 1024 * MiB;
10
11var prng = std.rand.DefaultPrng.init(0);
12
13const Hash = struct {
14 ty: type,
15 name: []const u8,
16 init_u8s: ?[]const u8 = null,
17 init_u64: ?u64 = null,
18};
19
20const siphash_key = "0123456789abcdef";
21
22const hashes = [_]Hash{
23 Hash{ .ty = hash.Wyhash, .name = "wyhash", .init_u64 = 0 },
24 Hash{ .ty = hash.SipHash64(1, 3), .name = "siphash(1,3)", .init_u8s = siphash_key },
25 Hash{ .ty = hash.SipHash64(2, 4), .name = "siphash(2,4)", .init_u8s = siphash_key },
26 Hash{ .ty = hash.Fnv1a_64, .name = "fnv1a" },
27 Hash{ .ty = hash.Crc32, .name = "crc32" },
28};
29
30const Result = struct {
31 hash: u64,
32 throughput: u64,
33};
34
35pub fn benchmarkHash(comptime H: var, bytes: usize) !Result {
36 var h = blk: {
37 if (H.init_u8s) |init| {
38 break :blk H.ty.init(init);
39 }
40 if (H.init_u64) |init| {
41 break :blk H.ty.init(init);
42 }
43 break :blk H.ty.init();
44 };
45
46 var block: [8192]u8 = undefined;
47 prng.random.bytes(block[0..]);
48
49 var offset: usize = 0;
50 var timer = try Timer.start();
51 const start = timer.lap();
52 while (offset < bytes) : (offset += block.len) {
53 h.update(block[0..]);
54 }
55 const end = timer.read();
56
57 const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
58 const throughput = @floatToInt(u64, @intToFloat(f64, bytes) / elapsed_s);
59
60 return Result{
61 .hash = h.final(),
62 .throughput = throughput,
63 };
64}
65
66fn usage() void {
67 std.debug.warn(
68 \\throughput_test [options]
69 \\
70 \\Options:
71 \\ --filter [test-name]
72 \\ --seed [int]
73 \\ --count [int]
74 \\ --help
75 \\
76 );
77}
78
79fn mode(comptime x: comptime_int) comptime_int {
80 return if (builtin.mode == builtin.Mode.Debug) x / 64 else x;
81}
82
83// TODO(#1358): Replace with builtin formatted padding when available.
84fn printPad(stdout: var, s: []const u8) !void {
85 var i: usize = 0;
86 while (i < 12 - s.len) : (i += 1) {
87 try stdout.print(" ");
88 }
89 try stdout.print("{}", s);
90}
91
92pub fn main() !void {
93 var stdout_file = try std.io.getStdOut();
94 var stdout_out_stream = stdout_file.outStream();
95 const stdout = &stdout_out_stream.stream;
96
97 var buffer: [1024]u8 = undefined;
98 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
99 const args = try std.process.argsAlloc(&fixed.allocator);
100
101 var filter: ?[]u8 = "";
102 var count: usize = mode(128 * MiB);
103
104 var i: usize = 1;
105 while (i < args.len) : (i += 1) {
106 if (std.mem.eql(u8, args[i], "--seed")) {
107 i += 1;
108 if (i == args.len) {
109 usage();
110 std.os.exit(1);
111 }
112
113 const seed = try std.fmt.parseUnsigned(u32, args[i], 10);
114 prng.seed(seed);
115 } else if (std.mem.eql(u8, args[i], "--filter")) {
116 i += 1;
117 if (i == args.len) {
118 usage();
119 std.os.exit(1);
120 }
121
122 filter = args[i];
123 } else if (std.mem.eql(u8, args[i], "--count")) {
124 i += 1;
125 if (i == args.len) {
126 usage();
127 std.os.exit(1);
128 }
129
130 const c = try std.fmt.parseUnsigned(u32, args[i], 10);
131 count = c * MiB;
132 } else if (std.mem.eql(u8, args[i], "--help")) {
133 usage();
134 return;
135 } else {
136 usage();
137 std.os.exit(1);
138 }
139 }
140
141 inline for (hashes) |H| {
142 if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) {
143 const result = try benchmarkHash(H, count);
144 try printPad(stdout, H.name);
145 try stdout.print(": {:4} MiB/s [{:16}]\n", result.throughput / (1 * MiB), result.hash);
146 }
147 }
148}
std/hash/wyhash.zig+117-21
...@@ -10,7 +10,8 @@ const primes = [_]u64{...@@ -10,7 +10,8 @@ const primes = [_]u64{
10};10};
1111
12fn read_bytes(comptime bytes: u8, data: []const u8) u64 {12fn read_bytes(comptime bytes: u8, data: []const u8) u64 {
13 return mem.readVarInt(u64, data[0..bytes], .Little);13 const T = @IntType(false, 8 * bytes);
14 return mem.readIntSliceLittle(T, data[0..bytes]);
14}15}
1516
16fn read_8bytes_swapped(data: []const u8) u64 {17fn read_8bytes_swapped(data: []const u8) u64 {
...@@ -31,18 +32,21 @@ fn mix1(a: u64, b: u64, seed: u64) u64 {...@@ -31,18 +32,21 @@ fn mix1(a: u64, b: u64, seed: u64) u64 {
31 return mum(a ^ seed ^ primes[2], b ^ seed ^ primes[3]);32 return mum(a ^ seed ^ primes[2], b ^ seed ^ primes[3]);
32}33}
3334
34pub const Wyhash = struct {35// Wyhash version which does not store internal state for handling partial buffers.
36// This is needed so that we can maximize the speed for the short key case, which will
37// use the non-iterative api which the public Wyhash exposes.
38const WyhashStateless = struct {
35 seed: u64,39 seed: u64,
36 msg_len: usize,40 msg_len: usize,
3741
38 pub fn init(seed: u64) Wyhash {42 pub fn init(seed: u64) WyhashStateless {
39 return Wyhash{43 return WyhashStateless{
40 .seed = seed,44 .seed = seed,
41 .msg_len = 0,45 .msg_len = 0,
42 };46 };
43 }47 }
4448
45 fn round(self: *Wyhash, b: []const u8) void {49 fn round(self: *WyhashStateless, b: []const u8) void {
46 std.debug.assert(b.len == 32);50 std.debug.assert(b.len == 32);
4751
48 self.seed = mix0(52 self.seed = mix0(
...@@ -56,12 +60,25 @@ pub const Wyhash = struct {...@@ -56,12 +60,25 @@ pub const Wyhash = struct {
56 );60 );
57 }61 }
5862
59 fn partial(self: *Wyhash, b: []const u8) void {63 pub fn update(self: *WyhashStateless, b: []const u8) void {
60 const rem_key = b;64 std.debug.assert(b.len % 32 == 0);
61 const rem_len = b.len;65
66 var off: usize = 0;
67 while (off < b.len) : (off += 32) {
68 @inlineCall(self.round, b[off .. off + 32]);
69 }
6270
63 var seed = self.seed;71 self.msg_len += b.len;
64 seed = switch (@intCast(u5, rem_len)) {72 }
73
74 pub fn final(self: *WyhashStateless, b: []const u8) u64 {
75 std.debug.assert(b.len < 32);
76
77 const seed = self.seed;
78 const rem_len = @intCast(u5, b.len);
79 const rem_key = b[0..rem_len];
80
81 self.seed = switch (rem_len) {
65 0 => seed,82 0 => seed,
66 1 => mix0(read_bytes(1, rem_key), primes[4], seed),83 1 => mix0(read_bytes(1, rem_key), primes[4], seed),
67 2 => mix0(read_bytes(2, rem_key), primes[4], seed),84 2 => mix0(read_bytes(2, rem_key), primes[4], seed),
...@@ -95,34 +112,70 @@ pub const Wyhash = struct {...@@ -95,34 +112,70 @@ pub const Wyhash = struct {
95 30 => mix0(read_8bytes_swapped(rem_key), read_8bytes_swapped(rem_key[8..]), seed) ^ mix1(read_8bytes_swapped(rem_key[16..]), (read_bytes(4, rem_key[24..]) << 16) | read_bytes(2, rem_key[28..]), seed),112 30 => mix0(read_8bytes_swapped(rem_key), read_8bytes_swapped(rem_key[8..]), seed) ^ mix1(read_8bytes_swapped(rem_key[16..]), (read_bytes(4, rem_key[24..]) << 16) | read_bytes(2, rem_key[28..]), seed),
96 31 => mix0(read_8bytes_swapped(rem_key), read_8bytes_swapped(rem_key[8..]), seed) ^ mix1(read_8bytes_swapped(rem_key[16..]), (read_bytes(4, rem_key[24..]) << 24) | (read_bytes(2, rem_key[28..]) << 8) | read_bytes(1, rem_key[30..]), seed),113 31 => mix0(read_8bytes_swapped(rem_key), read_8bytes_swapped(rem_key[8..]), seed) ^ mix1(read_8bytes_swapped(rem_key[16..]), (read_bytes(4, rem_key[24..]) << 24) | (read_bytes(2, rem_key[28..]) << 8) | read_bytes(1, rem_key[30..]), seed),
97 };114 };
98 self.seed = seed;115
116 self.msg_len += b.len;
117 return mum(self.seed ^ self.msg_len, primes[4]);
118 }
119
120 pub fn hash(seed: u64, input: []const u8) u64 {
121 const aligned_len = input.len - (input.len % 32);
122
123 var c = WyhashStateless.init(seed);
124 @inlineCall(c.update, input[0..aligned_len]);
125 return @inlineCall(c.final, input[aligned_len..]);
126 }
127};
128
129/// Fast non-cryptographic 64bit hash function.
130/// See https://github.com/wangyi-fudan/wyhash
131pub const Wyhash = struct {
132 state: WyhashStateless,
133
134 buf: [32]u8,
135 buf_len: usize,
136
137 pub fn init(seed: u64) Wyhash {
138 return Wyhash{
139 .state = WyhashStateless.init(seed),
140 .buf = undefined,
141 .buf_len = 0,
142 };
99 }143 }
100144
101 pub fn update(self: *Wyhash, b: []const u8) void {145 pub fn update(self: *Wyhash, b: []const u8) void {
102 var off: usize = 0;146 var off: usize = 0;
103147
104 // Full middle blocks.148 if (self.buf_len != 0 and self.buf_len + b.len >= 32) {
105 while (off + 32 <= b.len) : (off += 32) {149 off += 32 - self.buf_len;
106 @inlineCall(self.round, b[off .. off + 32]);150 mem.copy(u8, self.buf[self.buf_len..], b[0..off]);
151 self.state.update(self.buf[0..]);
152 self.buf_len = 0;
107 }153 }
108154
109 self.partial(b[off..]);155 const remain_len = b.len - off;
110 self.msg_len += b.len;156 const aligned_len = remain_len - (remain_len % 32);
157 self.state.update(b[off .. off + aligned_len]);
158
159 mem.copy(u8, self.buf[self.buf_len..], b[off + aligned_len ..]);
160 self.buf_len += @intCast(u8, b[off + aligned_len ..].len);
111 }161 }
112162
113 pub fn final(self: *Wyhash) u64 {163 pub fn final(self: *Wyhash) u64 {
114 return mum(self.seed ^ self.msg_len, primes[4]);164 const seed = self.state.seed;
165 const rem_len = @intCast(u5, self.buf_len);
166 const rem_key = self.buf[0..self.buf_len];
167
168 return self.state.final(rem_key);
115 }169 }
116170
117 pub fn hash(seed: u64, input: []const u8) u64 {171 pub fn hash(seed: u64, input: []const u8) u64 {
118 var c = Wyhash.init(seed);172 return WyhashStateless.hash(seed, input);
119 c.update(input);
120 return c.final();
121 }173 }
122};174};
123175
176const expectEqual = std.testing.expectEqual;
177
124test "test vectors" {178test "test vectors" {
125 const expectEqual = std.testing.expectEqual;
126 const hash = Wyhash.hash;179 const hash = Wyhash.hash;
127180
128 expectEqual(hash(0, ""), 0x0);181 expectEqual(hash(0, ""), 0x0);
...@@ -133,3 +186,46 @@ test "test vectors" {...@@ -133,3 +186,46 @@ test "test vectors" {
133 expectEqual(hash(5, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 0x602a1894d3bbfe7f);186 expectEqual(hash(5, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 0x602a1894d3bbfe7f);
134 expectEqual(hash(6, "12345678901234567890123456789012345678901234567890123456789012345678901234567890"), 0x829e9c148b75970e);187 expectEqual(hash(6, "12345678901234567890123456789012345678901234567890123456789012345678901234567890"), 0x829e9c148b75970e);
135}188}
189
190test "test vectors streaming" {
191 var wh = Wyhash.init(5);
192 for ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") |e| {
193 wh.update(mem.asBytes(&e));
194 }
195 expectEqual(wh.final(), 0x602a1894d3bbfe7f);
196
197 const pattern = "1234567890";
198 const count = 8;
199 const result = 0x829e9c148b75970e;
200 expectEqual(Wyhash.hash(6, pattern ** 8), result);
201
202 wh = Wyhash.init(6);
203 var i: u32 = 0;
204 while (i < count) : (i += 1) {
205 wh.update(pattern);
206 }
207 expectEqual(wh.final(), result);
208}
209
210test "iterative non-divisible update" {
211 var buf: [8192]u8 = undefined;
212 for (buf) |*e, i| {
213 e.* = @truncate(u8, i);
214 }
215
216 const seed = 0x128dad08f;
217
218 var end: usize = 32;
219 while (end < buf.len) : (end += 32) {
220 const non_iterative_hash = Wyhash.hash(seed, buf[0..end]);
221
222 var wy = Wyhash.init(seed);
223 var i: usize = 0;
224 while (i < end) : (i += 33) {
225 wy.update(buf[i..std.math.min(i + 33, end)]);
226 }
227 const iterative_hash = wy.final();
228
229 std.testing.expectEqual(iterative_hash, non_iterative_hash);
230 }
231}
std/hash_map.zig+15
...@@ -17,6 +17,21 @@ pub fn AutoHashMap(comptime K: type, comptime V: type) type {...@@ -17,6 +17,21 @@ pub fn AutoHashMap(comptime K: type, comptime V: type) type {
17 return HashMap(K, V, getAutoHashFn(K), getAutoEqlFn(K));17 return HashMap(K, V, getAutoHashFn(K), getAutoEqlFn(K));
18}18}
1919
20/// Builtin hashmap for strings as keys.
21pub fn StringHashMap(comptime V: type) type {
22 return HashMap([]const u8, V, hashString, eqlString);
23}
24
25pub fn eqlString(a: []const u8, b: []const u8) bool {
26 if (a.len != b.len) return false;
27 if (a.ptr == b.ptr) return true;
28 return mem.compare(u8, a, b) == .Equal;
29}
30
31pub fn hashString(s: []const u8) u32 {
32 return @truncate(u32, std.hash.Wyhash.hash(0, s));
33}
34
20pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u32, comptime eql: fn (a: K, b: K) bool) type {35pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u32, comptime eql: fn (a: K, b: K) bool) type {
21 return struct {36 return struct {
22 entries: []Entry,37 entries: []Entry,
std/http/headers.zig+1-11
...@@ -102,19 +102,9 @@ test "HeaderEntry" {...@@ -102,19 +102,9 @@ test "HeaderEntry" {
102 testing.expectEqualSlices(u8, "x", e.value);102 testing.expectEqualSlices(u8, "x", e.value);
103}103}
104104
105fn stringEql(a: []const u8, b: []const u8) bool {
106 if (a.len != b.len) return false;
107 if (a.ptr == b.ptr) return true;
108 return mem.compare(u8, a, b) == .Equal;
109}
110
111fn stringHash(s: []const u8) u32 {
112 return @truncate(u32, std.hash.Wyhash.hash(0, s));
113}
114
115const HeaderList = std.ArrayList(HeaderEntry);105const HeaderList = std.ArrayList(HeaderEntry);
116const HeaderIndexList = std.ArrayList(usize);106const HeaderIndexList = std.ArrayList(usize);
117const HeaderIndex = std.HashMap([]const u8, HeaderIndexList, stringHash, stringEql);107const HeaderIndex = std.StringHashMap(HeaderIndexList);
118108
119pub const Headers = struct {109pub const Headers = struct {
120 // the owned header field name is stored in the index as part of the key110 // the owned header field name is stored in the index as part of the key
std/os/windows.zig+3-4
...@@ -65,7 +65,7 @@ pub const CreateFileError = error{...@@ -65,7 +65,7 @@ pub const CreateFileError = error{
65 InvalidUtf8,65 InvalidUtf8,
6666
67 /// On Windows, file paths cannot contain these characters:67 /// On Windows, file paths cannot contain these characters:
68 /// '/', '*', '?', '"', '<', '>', '|'68 /// '*', '?', '"', '<', '>', '|', and '/' (when the ABI is not GNU)
69 BadPathName,69 BadPathName,
7070
71 Unexpected,71 Unexpected,
...@@ -836,11 +836,10 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)...@@ -836,11 +836,10 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
836 // > converting the name to an NT-style name, except when using the "\\?\"836 // > converting the name to an NT-style name, except when using the "\\?\"
837 // > prefix as detailed in the following sections.837 // > prefix as detailed in the following sections.
838 // from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation838 // from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
839 // Because we want the larger maximum path length for absolute paths, we
840 // disallow forward slashes in zig std lib file functions on Windows.
841 for (s) |byte| {839 for (s) |byte| {
842 switch (byte) {840 switch (byte) {
843 '/', '*', '?', '"', '<', '>', '|' => return error.BadPathName,841 '*', '?', '"', '<', '>', '|' => return error.BadPathName,
842 '/' => if (builtin.abi == .msvc) return error.BadPathName,
844 else => {},843 else => {},
845 }844 }
846 }845 }
std/std.zig+1
...@@ -17,6 +17,7 @@ pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList;...@@ -17,6 +17,7 @@ pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList;
17pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;17pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
18pub const SegmentedList = @import("segmented_list.zig").SegmentedList;18pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
19pub const SpinLock = @import("spinlock.zig").SpinLock;19pub const SpinLock = @import("spinlock.zig").SpinLock;
20pub const StringHashMap = @import("hash_map.zig").StringHashMap;
20pub const ChildProcess = @import("child_process.zig").ChildProcess;21pub const ChildProcess = @import("child_process.zig").ChildProcess;
21pub const TailQueue = @import("linked_list.zig").TailQueue;22pub const TailQueue = @import("linked_list.zig").TailQueue;
22pub const Thread = @import("thread.zig").Thread;23pub const Thread = @import("thread.zig").Thread;
std/zig/ast.zig+1
...@@ -761,6 +761,7 @@ pub const Node = struct {...@@ -761,6 +761,7 @@ pub const Node = struct {
761 name_token: TokenIndex,761 name_token: TokenIndex,
762 type_expr: ?*Node,762 type_expr: ?*Node,
763 value_expr: ?*Node,763 value_expr: ?*Node,
764 align_expr: ?*Node,
764765
765 pub fn iterate(self: *ContainerField, index: usize) ?*Node {766 pub fn iterate(self: *ContainerField, index: usize) ?*Node {
766 var i = index;767 var i = index;
std/zig/parse.zig+9-6
...@@ -380,16 +380,18 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -380,16 +380,18 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
380 return &node.base;380 return &node.base;
381}381}
382382
383/// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?383/// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
384fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {384fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
385 const name_token = eatToken(it, .Identifier) orelse return null;385 const name_token = eatToken(it, .Identifier) orelse return null;
386386
387 const type_expr = if (eatToken(it, .Colon)) |_|387 var align_expr: ?*Node = null;
388 try expectNode(arena, it, tree, parseTypeExpr, AstError{388 var type_expr: ?*Node = null;
389 if (eatToken(it, .Colon)) |_| {
390 type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
389 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },391 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
390 })392 });
391 else393 align_expr = try parseByteAlign(arena, it, tree);
392 null;394 }
393395
394 const value_expr = if (eatToken(it, .Equal)) |_|396 const value_expr = if (eatToken(it, .Equal)) |_|
395 try expectNode(arena, it, tree, parseExpr, AstError{397 try expectNode(arena, it, tree, parseExpr, AstError{
...@@ -406,6 +408,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -406,6 +408,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
406 .name_token = name_token,408 .name_token = name_token,
407 .type_expr = type_expr,409 .type_expr = type_expr,
408 .value_expr = value_expr,410 .value_expr = value_expr,
411 .align_expr = align_expr,
409 };412 };
410 return &node.base;413 return &node.base;
411}414}
std/zig/parser_test.zig+120-1
...@@ -166,6 +166,15 @@ test "zig fmt: doc comments on param decl" {...@@ -166,6 +166,15 @@ test "zig fmt: doc comments on param decl" {
166 );166 );
167}167}
168168
169test "zig fmt: aligned struct field" {
170 try testCanonical(
171 \\pub const S = struct {
172 \\ f: i32 align(32),
173 \\};
174 \\
175 );
176}
177
169test "zig fmt: preserve space between async fn definitions" {178test "zig fmt: preserve space between async fn definitions" {
170 try testCanonical(179 try testCanonical(
171 \\async fn a() void {}180 \\async fn a() void {}
...@@ -201,6 +210,103 @@ test "zig fmt: comment to disable/enable zig fmt" {...@@ -201,6 +210,103 @@ test "zig fmt: comment to disable/enable zig fmt" {
201 );210 );
202}211}
203212
213test "zig fmt: line comment following 'zig fmt: off'" {
214 try testCanonical(
215 \\// zig fmt: off
216 \\// Test
217 \\const e = f;
218 );
219}
220
221test "zig fmt: doc comment following 'zig fmt: off'" {
222 try testCanonical(
223 \\// zig fmt: off
224 \\/// test
225 \\const e = f;
226 );
227}
228
229test "zig fmt: line and doc comment following 'zig fmt: off'" {
230 try testCanonical(
231 \\// zig fmt: off
232 \\// test 1
233 \\/// test 2
234 \\const e = f;
235 );
236}
237
238test "zig fmt: doc and line comment following 'zig fmt: off'" {
239 try testCanonical(
240 \\// zig fmt: off
241 \\/// test 1
242 \\// test 2
243 \\const e = f;
244 );
245}
246
247test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
248 try testCanonical(
249 \\// zig fmt: off
250 \\// zig fmt: on
251 \\// zig fmt: off
252 \\const e = f;
253 \\// zig fmt: off
254 \\// zig fmt: on
255 \\// zig fmt: off
256 \\const a = b;
257 \\// zig fmt: on
258 \\const c = d;
259 \\// zig fmt: on
260 \\
261 );
262}
263
264test "zig fmt: line comment following 'zig fmt: on'" {
265 try testCanonical(
266 \\// zig fmt: off
267 \\const e = f;
268 \\// zig fmt: on
269 \\// test
270 \\const e = f;
271 \\
272 );
273}
274
275test "zig fmt: doc comment following 'zig fmt: on'" {
276 try testCanonical(
277 \\// zig fmt: off
278 \\const e = f;
279 \\// zig fmt: on
280 \\/// test
281 \\const e = f;
282 \\
283 );
284}
285
286test "zig fmt: line and doc comment following 'zig fmt: on'" {
287 try testCanonical(
288 \\// zig fmt: off
289 \\const e = f;
290 \\// zig fmt: on
291 \\// test1
292 \\/// test2
293 \\const e = f;
294 \\
295 );
296}
297
298test "zig fmt: doc and line comment following 'zig fmt: on'" {
299 try testCanonical(
300 \\// zig fmt: off
301 \\const e = f;
302 \\// zig fmt: on
303 \\/// test1
304 \\// test2
305 \\const e = f;
306 \\
307 );
308}
309
204test "zig fmt: pointer of unknown length" {310test "zig fmt: pointer of unknown length" {
205 try testCanonical(311 try testCanonical(
206 \\fn foo(ptr: [*]u8) void {}312 \\fn foo(ptr: [*]u8) void {}
...@@ -2269,7 +2375,6 @@ test "zig fmt: if type expr" {...@@ -2269,7 +2375,6 @@ test "zig fmt: if type expr" {
2269 \\2375 \\
2270 );2376 );
2271}2377}
2272
2273test "zig fmt: file ends with struct field" {2378test "zig fmt: file ends with struct field" {
2274 try testTransform(2379 try testTransform(
2275 \\a: bool2380 \\a: bool
...@@ -2279,6 +2384,20 @@ test "zig fmt: file ends with struct field" {...@@ -2279,6 +2384,20 @@ test "zig fmt: file ends with struct field" {
2279 );2384 );
2280}2385}
22812386
2387test "zig fmt: comment after empty comment" {
2388 try testTransform(
2389 \\const x = true; //
2390 \\//
2391 \\//
2392 \\//a
2393 \\
2394 ,
2395 \\const x = true;
2396 \\//a
2397 \\
2398 );
2399}
2400
2282test "zig fmt: comments at several places in struct init" {2401test "zig fmt: comments at several places in struct init" {
2283 try testTransform(2402 try testTransform(
2284 \\var bar = Bar{2403 \\var bar = Bar{
std/zig/render.zig+115-36
...@@ -89,41 +89,98 @@ fn renderRoot(...@@ -89,41 +89,98 @@ fn renderRoot(
89 var it = tree.root_node.decls.iterator(0);89 var it = tree.root_node.decls.iterator(0);
90 while (true) {90 while (true) {
91 var decl = (it.next() orelse return).*;91 var decl = (it.next() orelse return).*;
92 // look for zig fmt: off comment92
93 var start_token_index = decl.firstToken();93 // This loop does the following:
94 zig_fmt_loop: while (start_token_index != 0) {94 //
95 start_token_index -= 1;95 // - Iterates through line/doc comment tokens that precedes the current
96 const start_token = tree.tokens.at(start_token_index);96 // decl.
97 switch (start_token.id) {97 // - Figures out the first token index (`copy_start_token_index`) which
98 // hasn't been copied to the output stream yet.
99 // - Detects `zig fmt: (off|on)` in the line comment tokens, and
100 // determines whether the current decl should be reformatted or not.
101 //
102 var token_index = decl.firstToken();
103 var fmt_active = true;
104 var found_fmt_directive = false;
105
106 var copy_start_token_index = token_index;
107
108 while (token_index != 0) {
109 token_index -= 1;
110 const token = tree.tokens.at(token_index);
111 switch (token.id) {
98 Token.Id.LineComment => {},112 Token.Id.LineComment => {},
99 Token.Id.DocComment => continue,113 Token.Id.DocComment => {
114 copy_start_token_index = token_index;
115 continue;
116 },
100 else => break,117 else => break,
101 }118 }
102 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(start_token)[2..], " "), "zig fmt: off")) {119
103 var end_token_index = start_token_index;120 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: off")) {
104 while (true) {121 if (!found_fmt_directive) {
105 end_token_index += 1;122 fmt_active = false;
106 const end_token = tree.tokens.at(end_token_index);123 found_fmt_directive = true;
107 switch (end_token.id) {124 }
125 } else if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: on")) {
126 if (!found_fmt_directive) {
127 fmt_active = true;
128 found_fmt_directive = true;
129 }
130 }
131 }
132
133 if (!fmt_active) {
134 // Reformatting is disabled for the current decl and possibly some
135 // more decls that follow.
136 // Find the next `decl` for which reformatting is re-enabled.
137 token_index = decl.firstToken();
138
139 while (!fmt_active) {
140 decl = (it.next() orelse {
141 // If there's no next reformatted `decl`, just copy the
142 // remaining input tokens and bail out.
143 const start = tree.tokens.at(copy_start_token_index).start;
144 try copyFixingWhitespace(stream, tree.source[start..]);
145 return;
146 }).*;
147 var decl_first_token_index = decl.firstToken();
148
149 while (token_index < decl_first_token_index) : (token_index += 1) {
150 const token = tree.tokens.at(token_index);
151 switch (token.id) {
108 Token.Id.LineComment => {},152 Token.Id.LineComment => {},
109 Token.Id.Eof => {153 Token.Id.Eof => unreachable,
110 const start = tree.tokens.at(start_token_index + 1).start;
111 try copyFixingWhitespace(stream, tree.source[start..]);
112 return;
113 },
114 else => continue,154 else => continue,
115 }155 }
116 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(end_token)[2..], " "), "zig fmt: on")) {156 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: on")) {
117 const start = tree.tokens.at(start_token_index + 1).start;157 fmt_active = true;
118 try copyFixingWhitespace(stream, tree.source[start..end_token.end]);158 } else if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: off")) {
119 try stream.writeByte('\n');159 fmt_active = false;
120 while (tree.tokens.at(decl.firstToken()).start < end_token.end) {
121 decl = (it.next() orelse return).*;
122 }
123 break :zig_fmt_loop;
124 }160 }
125 }161 }
126 }162 }
163
164 // Found the next `decl` for which reformatting is enabled. Copy
165 // the input tokens before the `decl` that haven't been copied yet.
166 var copy_end_token_index = decl.firstToken();
167 token_index = copy_end_token_index;
168 while (token_index != 0) {
169 token_index -= 1;
170 const token = tree.tokens.at(token_index);
171 switch (token.id) {
172 Token.Id.LineComment => {},
173 Token.Id.DocComment => {
174 copy_end_token_index = token_index;
175 continue;
176 },
177 else => break,
178 }
179 }
180
181 const start = tree.tokens.at(copy_start_token_index).start;
182 const end = tree.tokens.at(copy_end_token_index).start;
183 try copyFixingWhitespace(stream, tree.source[start..end]);
127 }184 }
128185
129 try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl);186 try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl);
...@@ -206,7 +263,20 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i...@@ -206,7 +263,20 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
206 } else if (field.type_expr != null and field.value_expr == null) {263 } else if (field.type_expr != null and field.value_expr == null) {
207 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name264 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
208 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :265 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :
209 return renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Comma); // type,266
267 if (field.align_expr) |align_value_expr| {
268 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type
269 const lparen_token = tree.prevToken(align_value_expr.firstToken());
270 const align_kw = tree.prevToken(lparen_token);
271 const rparen_token = tree.nextToken(align_value_expr.lastToken());
272 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align
273 try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // (
274 try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, Space.None); // alignment
275 try renderToken(tree, stream, rparen_token, indent, start_col, Space.Comma); // )
276 } else {
277 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Comma); // type,
278 }
279
210 } else if (field.type_expr == null and field.value_expr != null) {280 } else if (field.type_expr == null and field.value_expr != null) {
211 try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name281 try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name
212 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =282 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =
...@@ -1924,15 +1994,24 @@ fn renderTokenOffset(...@@ -1924,15 +1994,24 @@ fn renderTokenOffset(
1924 }1994 }
1925 }1995 }
19261996
1927 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;1997 while (true) {
1928 if (comment_is_empty) {1998 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;
1929 switch (space) {1999 if (comment_is_empty) {
1930 Space.Newline => {2000 switch (space) {
1931 try stream.writeByte('\n');2001 Space.Newline => {
1932 start_col.* = 0;2002 offset += 1;
1933 return;2003 token = next_token;
1934 },2004 next_token = tree.tokens.at(token_index + offset);
1935 else => {},2005 if (next_token.id != .LineComment) {
2006 try stream.writeByte('\n');
2007 start_col.* = 0;
2008 return;
2009 }
2010 },
2011 else => break,
2012 }
2013 } else {
2014 break;
1936 }2015 }
1937 }2016 }
19382017
test/compile_errors.zig+89-44
...@@ -2,6 +2,51 @@ const tests = @import("tests.zig");...@@ -2,6 +2,51 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "struct depends on itself via optional field",
7 \\const LhsExpr = struct {
8 \\ rhsExpr: ?AstObject,
9 \\};
10 \\const AstObject = union {
11 \\ lhsExpr: LhsExpr,
12 \\};
13 \\export fn entry() void {
14 \\ const lhsExpr = LhsExpr{ .rhsExpr = null };
15 \\ const obj = AstObject{ .lhsExpr = lhsExpr };
16 \\}
17 ,
18 "tmp.zig:1:17: error: struct 'LhsExpr' depends on itself",
19 "tmp.zig:5:5: note: while checking this field",
20 "tmp.zig:2:5: note: while checking this field",
21 );
22
23 cases.add(
24 "alignment of enum field specified",
25 \\const Number = enum {
26 \\ a,
27 \\ b align(i32),
28 \\};
29 \\export fn entry1() void {
30 \\ var x: Number = undefined;
31 \\}
32 ,
33 "tmp.zig:3:13: error: structs and unions, not enums, support field alignment",
34 "tmp.zig:1:16: note: consider 'union(enum)' here",
35 );
36
37 cases.add(
38 "bad alignment type",
39 \\export fn entry1() void {
40 \\ var x: []align(true) i32 = undefined;
41 \\}
42 \\export fn entry2() void {
43 \\ var x: *align(f64(12.34)) i32 = undefined;
44 \\}
45 ,
46 "tmp.zig:2:20: error: expected type 'u29', found 'bool'",
47 "tmp.zig:5:22: error: fractional component prevents float value 12.340000 from being casted to type 'u29'",
48 );
49
5 cases.addCase(x: {50 cases.addCase(x: {
6 var tc = cases.create("variable in inline assembly template cannot be found",51 var tc = cases.create("variable in inline assembly template cannot be found",
7 \\export fn entry() void {52 \\export fn entry() void {
...@@ -10,7 +55,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -10,7 +55,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10 \\ : [bar] "=r" (-> usize)55 \\ : [bar] "=r" (-> usize)
11 \\ );56 \\ );
12 \\}57 \\}
13 , "tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs.");58 , "tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs");
14 tc.target = tests.Target{59 tc.target = tests.Target{
15 .Cross = tests.CrossTarget{60 .Cross = tests.CrossTarget{
16 .arch = .x86_64,61 .arch = .x86_64,
...@@ -53,8 +98,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -53,8 +98,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
53 \\}98 \\}
54 ,99 ,
55 "tmp.zig:8:1: error: '@Frame(rangeSum)' depends on itself",100 "tmp.zig:8:1: error: '@Frame(rangeSum)' depends on itself",
56 "tmp.zig:15:33: note: when analyzing type '@Frame(rangeSumIndirect)' here",101 "tmp.zig:15:33: note: when analyzing type '@Frame(rangeSum)' here",
57 "tmp.zig:26:25: note: when analyzing type '@Frame(rangeSum)' here",102 "tmp.zig:26:25: note: when analyzing type '@Frame(rangeSumIndirect)' here",
58 );103 );
59104
60 cases.add(105 cases.add(
...@@ -245,7 +290,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -245,7 +290,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
245 ,290 ,
246 "tmp.zig:4:1: error: unable to determine async function frame of 'amain'",291 "tmp.zig:4:1: error: unable to determine async function frame of 'amain'",
247 "tmp.zig:5:10: note: analysis of function 'other' depends on the frame",292 "tmp.zig:5:10: note: analysis of function 'other' depends on the frame",
248 "tmp.zig:8:13: note: depends on the frame here",293 "tmp.zig:8:13: note: referenced here",
249 );294 );
250295
251 cases.add(296 cases.add(
...@@ -258,7 +303,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -258,7 +303,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
258 \\}303 \\}
259 ,304 ,
260 "tmp.zig:4:1: error: cannot resolve '@Frame(amain)': function not fully analyzed yet",305 "tmp.zig:4:1: error: cannot resolve '@Frame(amain)': function not fully analyzed yet",
261 "tmp.zig:5:13: note: depends on its own frame here",306 "tmp.zig:5:13: note: referenced here",
262 );307 );
263308
264 cases.add(309 cases.add(
...@@ -404,7 +449,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -404,7 +449,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
404 \\ const foo: Foo = undefined;449 \\ const foo: Foo = undefined;
405 \\}450 \\}
406 ,451 ,
407 "tmp.zig:2:8: error: expected type 'type', found '(undefined)'",452 "tmp.zig:2:8: error: use of undefined value here causes undefined behavior",
408 );453 );
409454
410 cases.add(455 cases.add(
...@@ -470,7 +515,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -470,7 +515,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
470 );515 );
471516
472 cases.add(517 cases.add(
473 "Generic function where return type is self-referenced",518 "generic function where return type is self-referenced",
474 \\fn Foo(comptime T: type) Foo(T) {519 \\fn Foo(comptime T: type) Foo(T) {
475 \\ return struct{ x: T };520 \\ return struct{ x: T };
476 \\}521 \\}
...@@ -481,7 +526,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -481,7 +526,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
481 \\}526 \\}
482 ,527 ,
483 "tmp.zig:1:29: error: evaluation exceeded 1000 backwards branches",528 "tmp.zig:1:29: error: evaluation exceeded 1000 backwards branches",
484 "tmp.zig:1:29: note: called from here",529 "tmp.zig:5:18: note: referenced here",
485 );530 );
486531
487 cases.add(532 cases.add(
...@@ -645,7 +690,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -645,7 +690,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
645 \\const A = struct { a : A, };690 \\const A = struct { a : A, };
646 \\export fn entry() usize { return @sizeOf(A); }691 \\export fn entry() usize { return @sizeOf(A); }
647 ,692 ,
648 "tmp.zig:1:11: error: struct 'A' contains itself",693 "tmp.zig:1:11: error: struct 'A' depends on itself",
649 );694 );
650695
651 cases.add(696 cases.add(
...@@ -655,7 +700,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -655,7 +700,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
655 \\const C = struct { a : A, };700 \\const C = struct { a : A, };
656 \\export fn entry() usize { return @sizeOf(A); }701 \\export fn entry() usize { return @sizeOf(A); }
657 ,702 ,
658 "tmp.zig:1:11: error: struct 'A' contains itself",703 "tmp.zig:1:11: error: struct 'A' depends on itself",
659 );704 );
660705
661 cases.add(706 cases.add(
...@@ -670,7 +715,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -670,7 +715,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
670 \\ return @sizeOf(@typeOf(foo.x));715 \\ return @sizeOf(@typeOf(foo.x));
671 \\}716 \\}
672 ,717 ,
673 "tmp.zig:1:13: error: struct 'Foo' contains itself",718 "tmp.zig:1:13: error: struct 'Foo' depends on itself",
674 "tmp.zig:8:28: note: referenced here",719 "tmp.zig:8:28: note: referenced here",
675 );720 );
676721
...@@ -689,7 +734,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -689,7 +734,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
689 \\}734 \\}
690 ,735 ,
691 "tmp.zig:7:9: error: dependency loop detected",736 "tmp.zig:7:9: error: dependency loop detected",
692 "tmp.zig:2:19: note: called from here",737 "tmp.zig:2:19: note: referenced here",
693 "tmp.zig:10:21: note: referenced here",738 "tmp.zig:10:21: note: referenced here",
694 );739 );
695740
...@@ -703,7 +748,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -703,7 +748,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
703 \\ var s: Foo = Foo.E;748 \\ var s: Foo = Foo.E;
704 \\}749 \\}
705 ,750 ,
706 "tmp.zig:1:17: error: 'Foo' depends on itself",751 "tmp.zig:1:17: error: enum 'Foo' depends on itself",
707 );752 );
708753
709 cases.add(754 cases.add(
...@@ -866,7 +911,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -866,7 +911,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
866 break :x tc;911 break :x tc;
867 });912 });
868913
869 cases.addTest(914 cases.add(
870 "export generic function",915 "export generic function",
871 \\export fn foo(num: var) i32 {916 \\export fn foo(num: var) i32 {
872 \\ return 0;917 \\ return 0;
...@@ -875,17 +920,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -875,17 +920,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
875 "tmp.zig:1:15: error: parameter of type 'var' not allowed in function with calling convention 'ccc'",920 "tmp.zig:1:15: error: parameter of type 'var' not allowed in function with calling convention 'ccc'",
876 );921 );
877922
878 cases.addTest(923 cases.add(
879 "C pointer to c_void",924 "C pointer to c_void",
880 \\export fn a() void {925 \\export fn a() void {
881 \\ var x: *c_void = undefined;926 \\ var x: *c_void = undefined;
882 \\ var y: [*c]c_void = x;927 \\ var y: [*c]c_void = x;
883 \\}928 \\}
884 ,929 ,
885 "tmp.zig:3:12: error: C pointers cannot point opaque types",930 "tmp.zig:3:16: error: C pointers cannot point opaque types",
886 );931 );
887932
888 cases.addTest(933 cases.add(
889 "directly embedding opaque type in struct and union",934 "directly embedding opaque type in struct and union",
890 \\const O = @OpaqueType();935 \\const O = @OpaqueType();
891 \\const Foo = struct {936 \\const Foo = struct {
...@@ -906,7 +951,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -906,7 +951,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
906 "tmp.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions",951 "tmp.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
907 );952 );
908953
909 cases.addTest(954 cases.add(
910 "implicit cast between C pointer and Zig pointer - bad const/align/child",955 "implicit cast between C pointer and Zig pointer - bad const/align/child",
911 \\export fn a() void {956 \\export fn a() void {
912 \\ var x: [*c]u8 = undefined;957 \\ var x: [*c]u8 = undefined;
...@@ -942,7 +987,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -942,7 +987,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
942 "tmp.zig:23:22: error: expected type '[*c]u32', found '*u8'",987 "tmp.zig:23:22: error: expected type '[*c]u32', found '*u8'",
943 );988 );
944989
945 cases.addTest(990 cases.add(
946 "implicit casting null c pointer to zig pointer",991 "implicit casting null c pointer to zig pointer",
947 \\comptime {992 \\comptime {
948 \\ var c_ptr: [*c]u8 = 0;993 \\ var c_ptr: [*c]u8 = 0;
...@@ -952,7 +997,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -952,7 +997,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
952 "tmp.zig:3:24: error: null pointer casted to type '*u8'",997 "tmp.zig:3:24: error: null pointer casted to type '*u8'",
953 );998 );
954999
955 cases.addTest(1000 cases.add(
956 "implicit casting undefined c pointer to zig pointer",1001 "implicit casting undefined c pointer to zig pointer",
957 \\comptime {1002 \\comptime {
958 \\ var c_ptr: [*c]u8 = undefined;1003 \\ var c_ptr: [*c]u8 = undefined;
...@@ -962,7 +1007,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -962,7 +1007,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
962 "tmp.zig:3:24: error: use of undefined value here causes undefined behavior",1007 "tmp.zig:3:24: error: use of undefined value here causes undefined behavior",
963 );1008 );
9641009
965 cases.addTest(1010 cases.add(
966 "implicit casting C pointers which would mess up null semantics",1011 "implicit casting C pointers which would mess up null semantics",
967 \\export fn entry() void {1012 \\export fn entry() void {
968 \\ var slice: []const u8 = "aoeu";1013 \\ var slice: []const u8 = "aoeu";
...@@ -987,7 +1032,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -987,7 +1032,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
987 "tmp.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'",1032 "tmp.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'",
988 );1033 );
9891034
990 cases.addTest(1035 cases.add(
991 "implicit casting too big integers to C pointers",1036 "implicit casting too big integers to C pointers",
992 \\export fn a() void {1037 \\export fn a() void {
993 \\ var ptr: [*c]u8 = (1 << 64) + 1;1038 \\ var ptr: [*c]u8 = (1 << 64) + 1;
...@@ -1001,14 +1046,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1001,14 +1046,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1001 "tmp.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'",1046 "tmp.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'",
1002 );1047 );
10031048
1004 cases.addTest(1049 cases.add(
1005 "C pointer pointing to non C ABI compatible type or has align attr",1050 "C pointer pointing to non C ABI compatible type or has align attr",
1006 \\const Foo = struct {};1051 \\const Foo = struct {};
1007 \\export fn a() void {1052 \\export fn a() void {
1008 \\ const T = [*c]Foo;1053 \\ const T = [*c]Foo;
1009 \\}1054 \\}
1010 ,1055 ,
1011 "tmp.zig:3:15: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'",1056 "tmp.zig:3:19: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'",
1012 );1057 );
10131058
1014 cases.addCase(x: {1059 cases.addCase(x: {
...@@ -1029,7 +1074,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1029,7 +1074,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1029 break :x tc;1074 break :x tc;
1030 });1075 });
10311076
1032 cases.addTest(1077 cases.add(
1033 "assign to invalid dereference",1078 "assign to invalid dereference",
1034 \\export fn entry() void {1079 \\export fn entry() void {
1035 \\ 'a'.* = 1;1080 \\ 'a'.* = 1;
...@@ -1038,7 +1083,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1038,7 +1083,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1038 "tmp.zig:2:8: error: attempt to dereference non-pointer type 'comptime_int'",1083 "tmp.zig:2:8: error: attempt to dereference non-pointer type 'comptime_int'",
1039 );1084 );
10401085
1041 cases.addTest(1086 cases.add(
1042 "take slice of invalid dereference",1087 "take slice of invalid dereference",
1043 \\export fn entry() void {1088 \\export fn entry() void {
1044 \\ const x = 'a'.*[0..];1089 \\ const x = 'a'.*[0..];
...@@ -1047,7 +1092,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1047,7 +1092,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1047 "tmp.zig:2:18: error: attempt to dereference non-pointer type 'comptime_int'",1092 "tmp.zig:2:18: error: attempt to dereference non-pointer type 'comptime_int'",
1048 );1093 );
10491094
1050 cases.addTest(1095 cases.add(
1051 "@truncate undefined value",1096 "@truncate undefined value",
1052 \\export fn entry() void {1097 \\export fn entry() void {
1053 \\ var z = @truncate(u8, u16(undefined));1098 \\ var z = @truncate(u8, u16(undefined));
...@@ -1091,7 +1136,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1091,7 +1136,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1091 \\ return 5678;1136 \\ return 5678;
1092 \\}1137 \\}
1093 ,1138 ,
1094 "tmp.zig:2:12: error: `&&` is invalid. Note that `and` is boolean AND.",1139 "tmp.zig:2:12: error: `&&` is invalid. Note that `and` is boolean AND",
1095 );1140 );
10961141
1097 cases.add(1142 cases.add(
...@@ -1935,7 +1980,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1935,7 +1980,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1935 "unknown length pointer to opaque",1980 "unknown length pointer to opaque",
1936 \\export const T = [*]@OpaqueType();1981 \\export const T = [*]@OpaqueType();
1937 ,1982 ,
1938 "tmp.zig:1:18: error: unknown-length pointer to opaque",1983 "tmp.zig:1:21: error: unknown-length pointer to opaque",
1939 );1984 );
19401985
1941 cases.add(1986 cases.add(
...@@ -2924,7 +2969,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2924,7 +2969,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2924 \\fn a() *noreturn {}2969 \\fn a() *noreturn {}
2925 \\export fn entry() void { _ = a(); }2970 \\export fn entry() void { _ = a(); }
2926 ,2971 ,
2927 "tmp.zig:1:8: error: pointer to noreturn not allowed",2972 "tmp.zig:1:9: error: pointer to noreturn not allowed",
2928 );2973 );
29292974
2930 cases.add(2975 cases.add(
...@@ -3596,7 +3641,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3596,7 +3641,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3596 );3641 );
35973642
3598 cases.add(3643 cases.add(
3599 "non constant expression in array size outside function",3644 "non constant expression in array size",
3600 \\const Foo = struct {3645 \\const Foo = struct {
3601 \\ y: [get()]u8,3646 \\ y: [get()]u8,
3602 \\};3647 \\};
...@@ -3606,8 +3651,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3606,8 +3651,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3606 \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); }3651 \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); }
3607 ,3652 ,
3608 "tmp.zig:5:25: error: unable to evaluate constant expression",3653 "tmp.zig:5:25: error: unable to evaluate constant expression",
3609 "tmp.zig:2:12: note: called from here",3654 "tmp.zig:2:12: note: referenced here",
3610 "tmp.zig:2:8: note: called from here",
3611 );3655 );
36123656
3613 cases.add(3657 cases.add(
...@@ -3701,7 +3745,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3701,7 +3745,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3701 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }3745 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
3702 ,3746 ,
3703 "tmp.zig:3:14: error: division by zero",3747 "tmp.zig:3:14: error: division by zero",
3704 "tmp.zig:1:14: note: called from here",3748 "tmp.zig:1:14: note: referenced here",
3705 );3749 );
37063750
3707 cases.add(3751 cases.add(
...@@ -4133,7 +4177,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4133,7 +4177,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4133 \\export fn entry() usize { return @sizeOf(@typeOf(seventh_fib_number)); }4177 \\export fn entry() usize { return @sizeOf(@typeOf(seventh_fib_number)); }
4134 ,4178 ,
4135 "tmp.zig:3:21: error: evaluation exceeded 1000 backwards branches",4179 "tmp.zig:3:21: error: evaluation exceeded 1000 backwards branches",
4136 "tmp.zig:3:21: note: called from here",4180 "tmp.zig:1:37: note: referenced here",
4181 "tmp.zig:6:50: note: referenced here",
4137 );4182 );
41384183
4139 cases.add(4184 cases.add(
...@@ -4174,7 +4219,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4174,7 +4219,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4174 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }4219 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
4175 ,4220 ,
4176 "tmp.zig:6:26: error: unable to evaluate constant expression",4221 "tmp.zig:6:26: error: unable to evaluate constant expression",
4177 "tmp.zig:4:17: note: called from here",4222 "tmp.zig:4:17: note: referenced here",
4178 );4223 );
41794224
4180 cases.add(4225 cases.add(
...@@ -4257,7 +4302,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4257,7 +4302,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4257 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }4302 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
4258 ,4303 ,
4259 "tmp.zig:3:12: error: negation caused overflow",4304 "tmp.zig:3:12: error: negation caused overflow",
4260 "tmp.zig:1:14: note: called from here",4305 "tmp.zig:1:14: note: referenced here",
4261 );4306 );
42624307
4263 cases.add(4308 cases.add(
...@@ -4270,7 +4315,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4270,7 +4315,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4270 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }4315 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
4271 ,4316 ,
4272 "tmp.zig:3:14: error: operation caused overflow",4317 "tmp.zig:3:14: error: operation caused overflow",
4273 "tmp.zig:1:14: note: called from here",4318 "tmp.zig:1:14: note: referenced here",
4274 );4319 );
42754320
4276 cases.add(4321 cases.add(
...@@ -4283,7 +4328,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4283,7 +4328,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4283 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }4328 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
4284 ,4329 ,
4285 "tmp.zig:3:14: error: operation caused overflow",4330 "tmp.zig:3:14: error: operation caused overflow",
4286 "tmp.zig:1:14: note: called from here",4331 "tmp.zig:1:14: note: referenced here",
4287 );4332 );
42884333
4289 cases.add(4334 cases.add(
...@@ -4296,7 +4341,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4296,7 +4341,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4296 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }4341 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
4297 ,4342 ,
4298 "tmp.zig:3:14: error: operation caused overflow",4343 "tmp.zig:3:14: error: operation caused overflow",
4299 "tmp.zig:1:14: note: called from here",4344 "tmp.zig:1:14: note: referenced here",
4300 );4345 );
43014346
4302 cases.add(4347 cases.add(
...@@ -4388,7 +4433,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4388,7 +4433,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4388 \\}4433 \\}
4389 ,4434 ,
4390 "tmp.zig:3:7: error: unable to evaluate constant expression",4435 "tmp.zig:3:7: error: unable to evaluate constant expression",
4391 "tmp.zig:16:19: note: called from here",4436 "tmp.zig:16:19: note: referenced here",
4392 );4437 );
43934438
4394 cases.add(4439 cases.add(
...@@ -4717,7 +4762,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4717,7 +4762,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4717 \\}4762 \\}
4718 ,4763 ,
4719 "tmp.zig:10:14: error: unable to evaluate constant expression",4764 "tmp.zig:10:14: error: unable to evaluate constant expression",
4720 "tmp.zig:6:20: note: called from here",4765 "tmp.zig:6:20: note: referenced here",
4721 );4766 );
47224767
4723 cases.add(4768 cases.add(
...@@ -5864,7 +5909,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5864,7 +5909,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5864 \\}5909 \\}
5865 ,5910 ,
5866 "tmp.zig:4:25: error: aoeu",5911 "tmp.zig:4:25: error: aoeu",
5867 "tmp.zig:1:36: note: called from here",5912 "tmp.zig:1:36: note: referenced here",
5868 "tmp.zig:12:20: note: referenced here",5913 "tmp.zig:12:20: note: referenced here",
5869 );5914 );
58705915
...@@ -5939,7 +5984,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5939,7 +5984,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5939 \\ var x: MultipleChoice = undefined;5984 \\ var x: MultipleChoice = undefined;
5940 \\}5985 \\}
5941 ,5986 ,
5942 "tmp.zig:2:14: error: non-enum union field assignment",5987 "tmp.zig:2:14: error: untagged union field assignment",
5943 "tmp.zig:1:24: note: consider 'union(enum)' here",5988 "tmp.zig:1:24: note: consider 'union(enum)' here",
5944 );5989 );
59455990
test/stage1/behavior.zig+4
...@@ -15,6 +15,7 @@ comptime {...@@ -15,6 +15,7 @@ comptime {
15 _ = @import("behavior/bugs/1111.zig");15 _ = @import("behavior/bugs/1111.zig");
16 _ = @import("behavior/bugs/1120.zig");16 _ = @import("behavior/bugs/1120.zig");
17 _ = @import("behavior/bugs/1277.zig");17 _ = @import("behavior/bugs/1277.zig");
18 _ = @import("behavior/bugs/1310.zig");
18 _ = @import("behavior/bugs/1322.zig");19 _ = @import("behavior/bugs/1322.zig");
19 _ = @import("behavior/bugs/1381.zig");20 _ = @import("behavior/bugs/1381.zig");
20 _ = @import("behavior/bugs/1421.zig");21 _ = @import("behavior/bugs/1421.zig");
...@@ -22,15 +23,18 @@ comptime {...@@ -22,15 +23,18 @@ comptime {
22 _ = @import("behavior/bugs/1486.zig");23 _ = @import("behavior/bugs/1486.zig");
23 _ = @import("behavior/bugs/1500.zig");24 _ = @import("behavior/bugs/1500.zig");
24 _ = @import("behavior/bugs/1607.zig");25 _ = @import("behavior/bugs/1607.zig");
26 _ = @import("behavior/bugs/1735.zig");
25 _ = @import("behavior/bugs/1851.zig");27 _ = @import("behavior/bugs/1851.zig");
26 _ = @import("behavior/bugs/1914.zig");28 _ = @import("behavior/bugs/1914.zig");
27 _ = @import("behavior/bugs/2006.zig");29 _ = @import("behavior/bugs/2006.zig");
28 _ = @import("behavior/bugs/2114.zig");30 _ = @import("behavior/bugs/2114.zig");
29 _ = @import("behavior/bugs/2346.zig");31 _ = @import("behavior/bugs/2346.zig");
30 _ = @import("behavior/bugs/2578.zig");32 _ = @import("behavior/bugs/2578.zig");
33 _ = @import("behavior/bugs/3112.zig");
31 _ = @import("behavior/bugs/394.zig");34 _ = @import("behavior/bugs/394.zig");
32 _ = @import("behavior/bugs/421.zig");35 _ = @import("behavior/bugs/421.zig");
33 _ = @import("behavior/bugs/529.zig");36 _ = @import("behavior/bugs/529.zig");
37 _ = @import("behavior/bugs/624.zig");
34 _ = @import("behavior/bugs/655.zig");38 _ = @import("behavior/bugs/655.zig");
35 _ = @import("behavior/bugs/656.zig");39 _ = @import("behavior/bugs/656.zig");
36 _ = @import("behavior/bugs/679.zig");40 _ = @import("behavior/bugs/679.zig");
test/stage1/behavior/align.zig+15
...@@ -290,3 +290,18 @@ test "read 128-bit field from default aligned struct in global memory" {...@@ -290,3 +290,18 @@ test "read 128-bit field from default aligned struct in global memory" {
290 expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);290 expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
291 expect(12 == default_aligned_global.badguy);291 expect(12 == default_aligned_global.badguy);
292}292}
293
294test "struct field explicit alignment" {
295 const S = struct {
296 const Node = struct {
297 next: *Node,
298 massive_byte: u8 align(64),
299 };
300 };
301
302 var node: S.Node = undefined;
303 node.massive_byte = 100;
304 expect(node.massive_byte == 100);
305 comptime expect(@typeOf(&node.massive_byte) == *align(64) u8);
306 expect(@ptrToInt(&node.massive_byte) % 64 == 0);
307}
test/stage1/behavior/array.zig+6
...@@ -292,3 +292,9 @@ test "read/write through global variable array of struct fields initialized via...@@ -292,3 +292,9 @@ test "read/write through global variable array of struct fields initialized via
292 };292 };
293 S.doTheTest();293 S.doTheTest();
294}294}
295
296test "implicit cast zero sized array ptr to slice" {
297 var b = "";
298 const c: []const u8 = &b;
299 expect(c.len == 0);
300}
test/stage1/behavior/bugs/1310.zig created+24
...@@ -0,0 +1,24 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4pub const VM = ?[*]const struct_InvocationTable_;
5pub const struct_InvocationTable_ = extern struct {
6 GetVM: ?extern fn (?[*]VM) c_int,
7};
8
9pub const struct_VM_ = extern struct {
10 functions: ?[*]const struct_InvocationTable_,
11};
12
13//excised output from stdlib.h etc
14
15pub const InvocationTable_ = struct_InvocationTable_;
16pub const VM_ = struct_VM_;
17
18extern fn agent_callback(_vm: [*]VM, options: [*]u8) i32 {
19 return 11;
20}
21
22test "fixed" {
23 expect(agent_callback(undefined, undefined) == 11);
24}
test/stage1/behavior/bugs/1735.zig created+46
...@@ -0,0 +1,46 @@
1const std = @import("std");
2
3const mystruct = struct {
4 pending: ?listofstructs,
5};
6pub fn TailQueue(comptime T: type) type {
7 return struct {
8 const Self = @This();
9
10 pub const Node = struct {
11 prev: ?*Node,
12 next: ?*Node,
13 data: T,
14 };
15
16 first: ?*Node,
17 last: ?*Node,
18 len: usize,
19
20 pub fn init() Self {
21 return Self{
22 .first = null,
23 .last = null,
24 .len = 0,
25 };
26 }
27 };
28}
29const listofstructs = TailQueue(mystruct);
30
31const a = struct {
32 const Self = @This();
33
34 foo: listofstructs,
35
36 pub fn init() Self {
37 return Self{
38 .foo = listofstructs.init(),
39 };
40 }
41};
42
43test "intialization" {
44 var t = a.init();
45 std.testing.expect(t.foo.len == 0);
46}
test/stage1/behavior/bugs/3112.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const State = struct {
5 const Self = @This();
6 enter: fn (previous: ?Self) void,
7};
8
9fn prev(p: ?State) void {
10 expect(p == null);
11}
12
13test "zig test crash" {
14 var global: State = undefined;
15 global.enter = prev;
16 global.enter(null);
17}
test/stage1/behavior/bugs/624.zig created+23
...@@ -0,0 +1,23 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const TestContext = struct {
5 server_context: *ListenerContext,
6};
7
8const ListenerContext = struct {
9 context_alloc: *ContextAllocator,
10};
11
12const ContextAllocator = MemoryPool(TestContext);
13
14fn MemoryPool(comptime T: type) type {
15 return struct {
16 n: usize,
17 };
18}
19
20test "foo" {
21 var allocator = ContextAllocator{ .n = 10 };
22 expect(allocator.n == 10);
23}
test/stage1/behavior/error.zig+20
...@@ -375,3 +375,23 @@ test "implicit cast to optional to error union to return result loc" {...@@ -375,3 +375,23 @@ test "implicit cast to optional to error union to return result loc" {
375 S.entry();375 S.entry();
376 //comptime S.entry(); TODO376 //comptime S.entry(); TODO
377}377}
378
379test "function pointer with return type that is error union with payload which is pointer of parent struct" {
380 const S = struct {
381 const Foo = struct {
382 fun: fn (a: i32) (anyerror!*Foo),
383 };
384
385 const Err = error{UnspecifiedErr};
386
387 fn bar(a: i32) anyerror!*Foo {
388 return Err.UnspecifiedErr;
389 }
390
391 fn doTheTest() void {
392 var x = Foo{ .fun = bar };
393 expectError(error.UnspecifiedErr, x.fun(1));
394 }
395 };
396 S.doTheTest();
397}
test/stage1/behavior/misc.zig+15
...@@ -706,3 +706,18 @@ test "result location zero sized array inside struct field implicit cast to slic...@@ -706,3 +706,18 @@ test "result location zero sized array inside struct field implicit cast to slic
706 var foo = E{ .entries = [_]u32{} };706 var foo = E{ .entries = [_]u32{} };
707 expect(foo.entries.len == 0);707 expect(foo.entries.len == 0);
708}708}
709
710var global_foo: *i32 = undefined;
711
712test "global variable assignment with optional unwrapping with var initialized to undefined" {
713 const S = struct {
714 var data: i32 = 1234;
715 fn foo() ?*i32 {
716 return &data;
717 }
718 };
719 global_foo = S.foo() orelse {
720 @panic("bad");
721 };
722 expect(global_foo.* == 1234);
723}
test/stage1/behavior/optional.zig+19
...@@ -100,3 +100,22 @@ test "nested orelse" {...@@ -100,3 +100,22 @@ test "nested orelse" {
100 S.entry();100 S.entry();
101 comptime S.entry();101 comptime S.entry();
102}102}
103
104test "self-referential struct through a slice of optional" {
105 const S = struct {
106 const Node = struct {
107 children: []?Node,
108 data: ?u8,
109
110 fn new() Node {
111 return Node{
112 .children = undefined,
113 .data = null,
114 };
115 }
116 };
117 };
118
119 var n = S.Node.new();
120 expect(n.data == null);
121}
tools/process_headers.zig+2-5
...@@ -504,12 +504,9 @@ const Contents = struct {...@@ -504,12 +504,9 @@ const Contents = struct {
504 }504 }
505};505};
506506
507comptime {507const HashToContents = std.StringHashMap(Contents);
508 @compileError("the behavior of std.AutoHashMap changed and []const u8 will be treated as a pointer. will need to update the hash maps to actually do some kind of hashing on the slices.");
509}
510const HashToContents = std.AutoHashMap([]const u8, Contents);
511const TargetToHash = std.HashMap(DestTarget, []const u8, DestTarget.hash, DestTarget.eql);508const TargetToHash = std.HashMap(DestTarget, []const u8, DestTarget.hash, DestTarget.eql);
512const PathTable = std.AutoHashMap([]const u8, *TargetToHash);509const PathTable = std.StringHashMap(*TargetToHash);
513510
514const LibCVendor = enum {511const LibCVendor = enum {
515 musl,512 musl,
tools/update_glibc.zig+3-3
...@@ -118,7 +118,7 @@ const FunctionSet = struct {...@@ -118,7 +118,7 @@ const FunctionSet = struct {
118 list: std.ArrayList(VersionedFn),118 list: std.ArrayList(VersionedFn),
119 fn_vers_list: FnVersionList,119 fn_vers_list: FnVersionList,
120};120};
121const FnVersionList = std.AutoHashMap([]const u8, std.ArrayList(usize));121const FnVersionList = std.StringHashMap(std.ArrayList(usize));
122122
123const VersionedFn = struct {123const VersionedFn = struct {
124 ver: []const u8, // example: "GLIBC_2.15"124 ver: []const u8, // example: "GLIBC_2.15"
...@@ -140,8 +140,8 @@ pub fn main() !void {...@@ -140,8 +140,8 @@ pub fn main() !void {
140 const prefix = try fs.path.join(allocator, [_][]const u8{ in_glibc_dir, "sysdeps", "unix", "sysv", "linux" });140 const prefix = try fs.path.join(allocator, [_][]const u8{ in_glibc_dir, "sysdeps", "unix", "sysv", "linux" });
141 const glibc_out_dir = try fs.path.join(allocator, [_][]const u8{ zig_src_dir, "libc", "glibc" });141 const glibc_out_dir = try fs.path.join(allocator, [_][]const u8{ zig_src_dir, "libc", "glibc" });
142142
143 var global_fn_set = std.AutoHashMap([]const u8, Function).init(allocator);143 var global_fn_set = std.StringHashMap(Function).init(allocator);
144 var global_ver_set = std.AutoHashMap([]const u8, usize).init(allocator);144 var global_ver_set = std.StringHashMap(usize).init(allocator);
145 var target_functions = std.AutoHashMap(usize, FunctionSet).init(allocator);145 var target_functions = std.AutoHashMap(usize, FunctionSet).init(allocator);
146146
147 for (abi_lists) |*abi_list| {147 for (abi_lists) |*abi_list| {